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.
- package/.claude-plugin/README.md +38 -14
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +3 -0
- package/CONTRIBUTING.md +24 -1
- package/README.md +12 -8
- package/dist/package.json +1 -1
- package/dist/src/platforms/discord/cli.d.ts.map +1 -1
- package/dist/src/platforms/discord/cli.js +8 -1
- package/dist/src/platforms/discord/cli.js.map +1 -1
- package/dist/src/platforms/discord/commands/file.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/file.js +13 -7
- package/dist/src/platforms/discord/commands/file.js.map +1 -1
- package/dist/src/platforms/discord/commands/friend.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/friend.js +30 -30
- package/dist/src/platforms/discord/commands/friend.js.map +1 -1
- package/dist/src/platforms/discord/commands/index.d.ts +7 -0
- package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/index.js +7 -0
- package/dist/src/platforms/discord/commands/index.js.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.js +1 -2
- package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/slack/commands/file.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/file.js +10 -4
- package/dist/src/platforms/slack/commands/file.js.map +1 -1
- package/dist/src/platforms/slack/commands/sections.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/sections.js +5 -6
- package/dist/src/platforms/slack/commands/sections.js.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.js +1 -2
- package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/slack/commands/user.js +8 -8
- package/dist/src/platforms/slackbot/commands/reaction.js +2 -2
- package/dist/src/platforms/slackbot/commands/reaction.js.map +1 -1
- package/dist/src/platforms/teams/cli.d.ts.map +1 -1
- package/dist/src/platforms/teams/cli.js +7 -1
- package/dist/src/platforms/teams/cli.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts +3 -0
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +208 -107
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/commands/channel.js +9 -9
- package/dist/src/platforms/teams/commands/channel.js.map +1 -1
- package/dist/src/platforms/teams/commands/file.js +21 -21
- package/dist/src/platforms/teams/commands/file.js.map +1 -1
- package/dist/src/platforms/teams/commands/message.js +12 -12
- package/dist/src/platforms/teams/commands/message.js.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.js +6 -6
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.js +6 -6
- 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 +21 -25
- package/dist/src/platforms/teams/commands/team.js.map +1 -1
- package/dist/src/platforms/teams/commands/user.js +9 -9
- package/dist/src/platforms/teams/commands/user.js.map +1 -1
- package/dist/src/platforms/teams/credential-manager.d.ts +15 -2
- package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/teams/credential-manager.js +110 -28
- 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 +46 -16
- package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +8 -2
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +36 -24
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/types.d.ts +121 -0
- package/dist/src/platforms/teams/types.d.ts.map +1 -1
- package/dist/src/platforms/teams/types.js +16 -0
- package/dist/src/platforms/teams/types.js.map +1 -1
- package/e2e/README.md +1 -1
- package/package.json +1 -1
- package/skills/agent-discord/SKILL.md +5 -0
- package/skills/agent-slack/SKILL.md +11 -17
- package/skills/agent-teams/SKILL.md +21 -24
- package/skills/agent-teams/references/common-patterns.md +63 -49
- package/src/platforms/discord/cli.ts +14 -0
- package/src/platforms/discord/commands/file.ts +13 -7
- package/src/platforms/discord/commands/friend.ts +34 -34
- package/src/platforms/discord/commands/index.ts +7 -0
- package/src/platforms/discord/commands/snapshot.ts +1 -2
- package/src/platforms/slack/commands/file.ts +12 -4
- package/src/platforms/slack/commands/sections.ts +8 -9
- package/src/platforms/slack/commands/snapshot.ts +1 -2
- package/src/platforms/slack/commands/user.ts +8 -8
- package/src/platforms/slackbot/commands/reaction.ts +2 -2
- package/src/platforms/teams/cli.ts +7 -0
- package/src/platforms/teams/commands/auth.test.ts +6 -5
- package/src/platforms/teams/commands/auth.ts +283 -120
- package/src/platforms/teams/commands/channel.test.ts +10 -4
- package/src/platforms/teams/commands/channel.ts +9 -9
- package/src/platforms/teams/commands/file.test.ts +9 -3
- package/src/platforms/teams/commands/file.ts +21 -21
- package/src/platforms/teams/commands/message.test.ts +9 -3
- package/src/platforms/teams/commands/message.ts +12 -12
- package/src/platforms/teams/commands/reaction.test.ts +9 -3
- package/src/platforms/teams/commands/reaction.ts +6 -6
- package/src/platforms/teams/commands/snapshot.ts +6 -6
- package/src/platforms/teams/commands/team.test.ts +19 -12
- package/src/platforms/teams/commands/team.ts +22 -28
- package/src/platforms/teams/commands/user.ts +9 -9
- package/src/platforms/teams/credential-manager.test.ts +30 -24
- package/src/platforms/teams/credential-manager.ts +106 -31
- package/src/platforms/teams/ensure-auth.test.ts +125 -26
- package/src/platforms/teams/ensure-auth.ts +47 -15
- package/src/platforms/teams/token-extractor.test.ts +116 -85
- package/src/platforms/teams/token-extractor.ts +65 -97
- package/src/platforms/teams/types.test.ts +31 -13
- package/src/platforms/teams/types.ts +45 -0
|
@@ -47,9 +47,15 @@ beforeEach(() => {
|
|
|
47
47
|
clientDeleteMessageSpy = spyOn(TeamsClient.prototype, 'deleteMessage').mockResolvedValue(undefined)
|
|
48
48
|
|
|
49
49
|
credManagerLoadSpy = spyOn(TeamsCredentialManager.prototype, 'loadConfig').mockResolvedValue({
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
current_account: 'work',
|
|
51
|
+
accounts: {
|
|
52
|
+
work: {
|
|
53
|
+
token: 'test_token',
|
|
54
|
+
account_type: 'work' as const,
|
|
55
|
+
current_team: 'team_123',
|
|
56
|
+
teams: { team_123: { team_id: 'team_123', team_name: 'Test Team' } },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
53
59
|
})
|
|
54
60
|
})
|
|
55
61
|
|
|
@@ -13,14 +13,14 @@ export async function sendAction(
|
|
|
13
13
|
): Promise<void> {
|
|
14
14
|
try {
|
|
15
15
|
const credManager = new TeamsCredentialManager()
|
|
16
|
-
const
|
|
16
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
17
17
|
|
|
18
|
-
if (!
|
|
18
|
+
if (!cred) {
|
|
19
19
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
20
20
|
process.exit(1)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const client = new TeamsClient(
|
|
23
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
24
24
|
const message = await client.sendMessage(teamId, channelId, content)
|
|
25
25
|
|
|
26
26
|
const output = {
|
|
@@ -43,14 +43,14 @@ export async function listAction(
|
|
|
43
43
|
): Promise<void> {
|
|
44
44
|
try {
|
|
45
45
|
const credManager = new TeamsCredentialManager()
|
|
46
|
-
const
|
|
46
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
47
47
|
|
|
48
|
-
if (!
|
|
48
|
+
if (!cred) {
|
|
49
49
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
50
50
|
process.exit(1)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const client = new TeamsClient(
|
|
53
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
54
54
|
const limit = options.limit || 50
|
|
55
55
|
const messages = await client.getMessages(teamId, channelId, limit)
|
|
56
56
|
|
|
@@ -75,14 +75,14 @@ export async function getAction(
|
|
|
75
75
|
): Promise<void> {
|
|
76
76
|
try {
|
|
77
77
|
const credManager = new TeamsCredentialManager()
|
|
78
|
-
const
|
|
78
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
79
79
|
|
|
80
|
-
if (!
|
|
80
|
+
if (!cred) {
|
|
81
81
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
82
82
|
process.exit(1)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
const client = new TeamsClient(
|
|
85
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
86
86
|
const message = await client.getMessage(teamId, channelId, messageId)
|
|
87
87
|
|
|
88
88
|
if (!message) {
|
|
@@ -111,9 +111,9 @@ export async function deleteAction(
|
|
|
111
111
|
): Promise<void> {
|
|
112
112
|
try {
|
|
113
113
|
const credManager = new TeamsCredentialManager()
|
|
114
|
-
const
|
|
114
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
115
115
|
|
|
116
|
-
if (!
|
|
116
|
+
if (!cred) {
|
|
117
117
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
118
118
|
process.exit(1)
|
|
119
119
|
}
|
|
@@ -123,7 +123,7 @@ export async function deleteAction(
|
|
|
123
123
|
process.exit(0)
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
const client = new TeamsClient(
|
|
126
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
127
127
|
await client.deleteMessage(teamId, channelId, messageId)
|
|
128
128
|
|
|
129
129
|
console.log(formatOutput({ deleted: messageId }, options.pretty))
|
|
@@ -11,9 +11,15 @@ beforeEach(() => {
|
|
|
11
11
|
clientAddReactionSpy = spyOn(TeamsClient.prototype, 'addReaction').mockResolvedValue(undefined)
|
|
12
12
|
clientRemoveReactionSpy = spyOn(TeamsClient.prototype, 'removeReaction').mockResolvedValue(undefined)
|
|
13
13
|
credManagerLoadConfigSpy = spyOn(TeamsCredentialManager.prototype, 'loadConfig').mockResolvedValue({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
current_account: 'work',
|
|
15
|
+
accounts: {
|
|
16
|
+
work: {
|
|
17
|
+
token: 'test-token',
|
|
18
|
+
account_type: 'work' as const,
|
|
19
|
+
current_team: null,
|
|
20
|
+
teams: {},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
17
23
|
})
|
|
18
24
|
})
|
|
19
25
|
|
|
@@ -13,14 +13,14 @@ export async function addAction(
|
|
|
13
13
|
): Promise<void> {
|
|
14
14
|
try {
|
|
15
15
|
const credManager = new TeamsCredentialManager()
|
|
16
|
-
const
|
|
16
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
17
17
|
|
|
18
|
-
if (!
|
|
18
|
+
if (!cred) {
|
|
19
19
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
20
20
|
process.exit(1)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
const client = new TeamsClient(
|
|
23
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
24
24
|
await client.addReaction(teamId, channelId, messageId, emoji)
|
|
25
25
|
|
|
26
26
|
console.log(
|
|
@@ -49,14 +49,14 @@ export async function removeAction(
|
|
|
49
49
|
): Promise<void> {
|
|
50
50
|
try {
|
|
51
51
|
const credManager = new TeamsCredentialManager()
|
|
52
|
-
const
|
|
52
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
53
53
|
|
|
54
|
-
if (!
|
|
54
|
+
if (!cred) {
|
|
55
55
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
56
56
|
process.exit(1)
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const client = new TeamsClient(
|
|
59
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
60
60
|
await client.removeReaction(teamId, channelId, messageId, emoji)
|
|
61
61
|
|
|
62
62
|
console.log(
|
|
@@ -15,14 +15,15 @@ export async function snapshotAction(options: {
|
|
|
15
15
|
}): Promise<void> {
|
|
16
16
|
try {
|
|
17
17
|
const credManager = new TeamsCredentialManager()
|
|
18
|
-
const
|
|
18
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
19
19
|
|
|
20
|
-
if (!
|
|
20
|
+
if (!cred) {
|
|
21
21
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
22
22
|
process.exit(1)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const currentTeam = await credManager.getCurrentTeam()
|
|
26
|
+
const teamId = options.teamId || currentTeam?.team_id
|
|
26
27
|
if (!teamId) {
|
|
27
28
|
console.log(
|
|
28
29
|
formatOutput({ error: 'No current team set. Run "team switch" first or use --team-id.' }, options.pretty),
|
|
@@ -30,7 +31,7 @@ export async function snapshotAction(options: {
|
|
|
30
31
|
process.exit(1)
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
const client = new TeamsClient(
|
|
34
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
34
35
|
const messageLimit = options.limit || 20
|
|
35
36
|
|
|
36
37
|
const snapshot: Record<string, unknown> = {}
|
|
@@ -91,8 +92,7 @@ export async function snapshotAction(options: {
|
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
|
|
94
|
-
export const snapshotCommand = new Command()
|
|
95
|
-
.name('snapshot')
|
|
95
|
+
export const snapshotCommand = new Command('snapshot')
|
|
96
96
|
.description('Get comprehensive team state for AI agents')
|
|
97
97
|
.option('--channels-only', 'Include only channels (exclude messages and members)')
|
|
98
98
|
.option('--users-only', 'Include only members (exclude channels and messages)')
|
|
@@ -26,11 +26,17 @@ beforeEach(() => {
|
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
credManagerLoadConfigSpy = spyOn(TeamsCredentialManager.prototype, 'loadConfig').mockResolvedValue({
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
current_account: 'work',
|
|
30
|
+
accounts: {
|
|
31
|
+
work: {
|
|
32
|
+
token: 'test-token',
|
|
33
|
+
account_type: 'work' as const,
|
|
34
|
+
current_team: 'team-1',
|
|
35
|
+
teams: {
|
|
36
|
+
'team-1': { team_id: 'team-1', team_name: 'Team One' },
|
|
37
|
+
'team-2': { team_id: 'team-2', team_name: 'Team Two' },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
34
40
|
},
|
|
35
41
|
})
|
|
36
42
|
|
|
@@ -59,12 +65,13 @@ test('list: returns teams with current marker', async () => {
|
|
|
59
65
|
const config = await credManager.loadConfig()
|
|
60
66
|
|
|
61
67
|
// when: checking teams
|
|
62
|
-
|
|
63
|
-
expect(
|
|
68
|
+
const account = config!.accounts.work
|
|
69
|
+
expect(account.teams).toBeDefined()
|
|
70
|
+
expect(Object.keys(account.teams)).toHaveLength(2)
|
|
64
71
|
|
|
65
72
|
// then: teams are returned
|
|
66
|
-
expect(
|
|
67
|
-
expect(
|
|
73
|
+
expect(account.teams['team-1']).toBeDefined()
|
|
74
|
+
expect(account.teams['team-2']).toBeDefined()
|
|
68
75
|
})
|
|
69
76
|
|
|
70
77
|
test('list: marks current team', async () => {
|
|
@@ -77,7 +84,7 @@ test('list: marks current team', async () => {
|
|
|
77
84
|
expect(current?.team_id).toBe('team-1')
|
|
78
85
|
|
|
79
86
|
// then: current team is marked
|
|
80
|
-
expect(config!.current_team).toBe('team-1')
|
|
87
|
+
expect(config!.accounts.work.current_team).toBe('team-1')
|
|
81
88
|
})
|
|
82
89
|
|
|
83
90
|
test('info: returns team details', async () => {
|
|
@@ -129,7 +136,7 @@ test('current: returns current team info', async () => {
|
|
|
129
136
|
|
|
130
137
|
// then: current team is returned
|
|
131
138
|
expect(current?.team_id).toBe('team-1')
|
|
132
|
-
expect(config!.current_team).toBe('team-1')
|
|
139
|
+
expect(config!.accounts.work.current_team).toBe('team-1')
|
|
133
140
|
})
|
|
134
141
|
|
|
135
142
|
test('remove: removes team from config', async () => {
|
|
@@ -138,7 +145,7 @@ test('remove: removes team from config', async () => {
|
|
|
138
145
|
const config = await credManager.loadConfig()
|
|
139
146
|
|
|
140
147
|
// when: removing team
|
|
141
|
-
delete config!.teams['team-2']
|
|
148
|
+
delete config!.accounts.work.teams['team-2']
|
|
142
149
|
await credManager.saveConfig(config!)
|
|
143
150
|
|
|
144
151
|
// then: saveConfig is called
|
|
@@ -7,13 +7,13 @@ import { TeamsCredentialManager } from '../credential-manager'
|
|
|
7
7
|
export async function listAction(options: { pretty?: boolean }): Promise<void> {
|
|
8
8
|
try {
|
|
9
9
|
const credManager = new TeamsCredentialManager()
|
|
10
|
-
const
|
|
11
|
-
const teams =
|
|
10
|
+
const account = await credManager.getCurrentAccount()
|
|
11
|
+
const teams = account?.teams ? Object.values(account.teams) : []
|
|
12
12
|
|
|
13
13
|
const output = teams.map((team) => ({
|
|
14
14
|
id: team.team_id,
|
|
15
15
|
name: team.team_name,
|
|
16
|
-
current: team.team_id ===
|
|
16
|
+
current: team.team_id === account?.current_team,
|
|
17
17
|
}))
|
|
18
18
|
|
|
19
19
|
console.log(formatOutput(output, options.pretty))
|
|
@@ -25,14 +25,14 @@ export async function listAction(options: { pretty?: boolean }): Promise<void> {
|
|
|
25
25
|
export async function infoAction(teamId: string, options: { pretty?: boolean }): Promise<void> {
|
|
26
26
|
try {
|
|
27
27
|
const credManager = new TeamsCredentialManager()
|
|
28
|
-
const
|
|
28
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
29
29
|
|
|
30
|
-
if (!
|
|
30
|
+
if (!cred) {
|
|
31
31
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
32
32
|
process.exit(1)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const client = new TeamsClient(
|
|
35
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
36
36
|
const team = await client.getTeam(teamId)
|
|
37
37
|
|
|
38
38
|
const output = {
|
|
@@ -50,14 +50,14 @@ export async function infoAction(teamId: string, options: { pretty?: boolean }):
|
|
|
50
50
|
export async function switchAction(teamId: string, options: { pretty?: boolean }): Promise<void> {
|
|
51
51
|
try {
|
|
52
52
|
const credManager = new TeamsCredentialManager()
|
|
53
|
-
const
|
|
53
|
+
const account = await credManager.getCurrentAccount()
|
|
54
54
|
|
|
55
|
-
if (!
|
|
55
|
+
if (!account?.teams?.[teamId]) {
|
|
56
56
|
console.log(formatOutput({ error: `Team not found: ${teamId}` }, options.pretty))
|
|
57
57
|
process.exit(1)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const team =
|
|
60
|
+
const team = account.teams[teamId]
|
|
61
61
|
await credManager.setCurrentTeam(teamId, team.team_name)
|
|
62
62
|
console.log(formatOutput({ current: teamId }, options.pretty))
|
|
63
63
|
} catch (error) {
|
|
@@ -68,26 +68,14 @@ export async function switchAction(teamId: string, options: { pretty?: boolean }
|
|
|
68
68
|
export async function currentAction(options: { pretty?: boolean }): Promise<void> {
|
|
69
69
|
try {
|
|
70
70
|
const credManager = new TeamsCredentialManager()
|
|
71
|
-
const
|
|
71
|
+
const currentTeam = await credManager.getCurrentTeam()
|
|
72
72
|
|
|
73
|
-
if (!
|
|
73
|
+
if (!currentTeam) {
|
|
74
74
|
console.log(formatOutput({ error: 'No current team set. Run "auth extract" first.' }, options.pretty))
|
|
75
75
|
process.exit(1)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (!team) {
|
|
81
|
-
console.log(formatOutput({ error: 'Current team not found in configuration.' }, options.pretty))
|
|
82
|
-
process.exit(1)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const output = {
|
|
86
|
-
team_id: team.team_id,
|
|
87
|
-
team_name: team.team_name,
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
console.log(formatOutput(output, options.pretty))
|
|
78
|
+
console.log(formatOutput({ team_id: currentTeam.team_id, team_name: currentTeam.team_name }, options.pretty))
|
|
91
79
|
} catch (error) {
|
|
92
80
|
handleError(error as Error)
|
|
93
81
|
}
|
|
@@ -103,15 +91,21 @@ export async function removeAction(teamId: string, options: { pretty?: boolean }
|
|
|
103
91
|
process.exit(1)
|
|
104
92
|
}
|
|
105
93
|
|
|
106
|
-
|
|
94
|
+
const account = await credManager.getCurrentAccount()
|
|
95
|
+
if (!account) {
|
|
96
|
+
console.log(formatOutput({ error: 'No active account.' }, options.pretty))
|
|
97
|
+
process.exit(1)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!account.teams[teamId]) {
|
|
107
101
|
console.log(formatOutput({ error: `Team not found: ${teamId}` }, options.pretty))
|
|
108
102
|
process.exit(1)
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
delete
|
|
105
|
+
delete account.teams[teamId]
|
|
112
106
|
|
|
113
|
-
if (
|
|
114
|
-
|
|
107
|
+
if (account.current_team === teamId) {
|
|
108
|
+
account.current_team = null
|
|
115
109
|
}
|
|
116
110
|
|
|
117
111
|
await credManager.saveConfig(config)
|
|
@@ -7,14 +7,14 @@ import { TeamsCredentialManager } from '../credential-manager'
|
|
|
7
7
|
async function listAction(teamId: string, options: { pretty?: boolean }): Promise<void> {
|
|
8
8
|
try {
|
|
9
9
|
const credManager = new TeamsCredentialManager()
|
|
10
|
-
const
|
|
10
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
11
11
|
|
|
12
|
-
if (!
|
|
12
|
+
if (!cred) {
|
|
13
13
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
14
14
|
process.exit(1)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const client = new TeamsClient(
|
|
17
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
18
18
|
const users = await client.listUsers(teamId)
|
|
19
19
|
|
|
20
20
|
const output = users.map((user) => ({
|
|
@@ -33,14 +33,14 @@ async function listAction(teamId: string, options: { pretty?: boolean }): Promis
|
|
|
33
33
|
async function infoAction(userId: string, options: { pretty?: boolean }): Promise<void> {
|
|
34
34
|
try {
|
|
35
35
|
const credManager = new TeamsCredentialManager()
|
|
36
|
-
const
|
|
36
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
37
37
|
|
|
38
|
-
if (!
|
|
38
|
+
if (!cred) {
|
|
39
39
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
40
40
|
process.exit(1)
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const client = new TeamsClient(
|
|
43
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
44
44
|
const user = await client.getUser(userId)
|
|
45
45
|
|
|
46
46
|
const output = {
|
|
@@ -59,14 +59,14 @@ async function infoAction(userId: string, options: { pretty?: boolean }): Promis
|
|
|
59
59
|
async function meAction(options: { pretty?: boolean }): Promise<void> {
|
|
60
60
|
try {
|
|
61
61
|
const credManager = new TeamsCredentialManager()
|
|
62
|
-
const
|
|
62
|
+
const cred = await credManager.getTokenWithExpiry()
|
|
63
63
|
|
|
64
|
-
if (!
|
|
64
|
+
if (!cred) {
|
|
65
65
|
console.log(formatOutput({ error: 'Not authenticated. Run "auth extract" first.' }, options.pretty))
|
|
66
66
|
process.exit(1)
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
const client = new TeamsClient(
|
|
69
|
+
const client = new TeamsClient(cred.token, cred.tokenExpiresAt)
|
|
70
70
|
const user = await client.testAuth()
|
|
71
71
|
|
|
72
72
|
const output = {
|
|
@@ -33,10 +33,16 @@ describe('TeamsCredentialManager', () => {
|
|
|
33
33
|
testDirs.push(testConfigDir)
|
|
34
34
|
const manager = new TeamsCredentialManager(testConfigDir)
|
|
35
35
|
const config = {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
current_account: 'work',
|
|
37
|
+
accounts: {
|
|
38
|
+
work: {
|
|
39
|
+
token: 'test-token',
|
|
40
|
+
current_team: 'team-123',
|
|
41
|
+
account_type: 'work' as const,
|
|
42
|
+
teams: {
|
|
43
|
+
'team-123': { team_id: 'team-123', team_name: 'Test Team' },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
40
46
|
},
|
|
41
47
|
}
|
|
42
48
|
|
|
@@ -59,7 +65,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
59
65
|
|
|
60
66
|
test('setToken saves token to config', async () => {
|
|
61
67
|
const manager = setup()
|
|
62
|
-
await manager.setToken('test-token-123')
|
|
68
|
+
await manager.setToken('test-token-123', 'work')
|
|
63
69
|
|
|
64
70
|
const token = await manager.getToken()
|
|
65
71
|
expect(token).toBe('test-token-123')
|
|
@@ -68,11 +74,11 @@ describe('TeamsCredentialManager', () => {
|
|
|
68
74
|
test('setToken saves token with expiry', async () => {
|
|
69
75
|
const manager = setup()
|
|
70
76
|
const expiresAt = '2025-12-31T23:59:59Z'
|
|
71
|
-
await manager.setToken('test-token-123', expiresAt)
|
|
77
|
+
await manager.setToken('test-token-123', 'work', expiresAt)
|
|
72
78
|
|
|
73
79
|
const config = await manager.loadConfig()
|
|
74
|
-
expect(config?.token).toBe('test-token-123')
|
|
75
|
-
expect(config?.token_expires_at).toBe(expiresAt)
|
|
80
|
+
expect(config?.accounts?.work?.token).toBe('test-token-123')
|
|
81
|
+
expect(config?.accounts?.work?.token_expires_at).toBe(expiresAt)
|
|
76
82
|
})
|
|
77
83
|
|
|
78
84
|
test('getCurrentTeam returns null when not set', async () => {
|
|
@@ -83,10 +89,10 @@ describe('TeamsCredentialManager', () => {
|
|
|
83
89
|
|
|
84
90
|
test('getCurrentTeam returns null when current_team is set but team not in teams record', async () => {
|
|
85
91
|
const manager = setup()
|
|
86
|
-
await manager.setToken('test-token')
|
|
92
|
+
await manager.setToken('test-token', 'work')
|
|
87
93
|
const config = await manager.loadConfig()
|
|
88
|
-
if (config) {
|
|
89
|
-
config.current_team = 'non-existent-team'
|
|
94
|
+
if (config?.accounts?.work) {
|
|
95
|
+
config.accounts.work.current_team = 'non-existent-team'
|
|
90
96
|
await manager.saveConfig(config)
|
|
91
97
|
}
|
|
92
98
|
|
|
@@ -96,7 +102,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
96
102
|
|
|
97
103
|
test('setCurrentTeam saves team info', async () => {
|
|
98
104
|
const manager = setup()
|
|
99
|
-
await manager.setToken('test-token')
|
|
105
|
+
await manager.setToken('test-token', 'work')
|
|
100
106
|
await manager.setCurrentTeam('team-456', 'My Team')
|
|
101
107
|
|
|
102
108
|
const team = await manager.getCurrentTeam()
|
|
@@ -105,7 +111,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
105
111
|
|
|
106
112
|
test('setCurrentTeam updates existing team', async () => {
|
|
107
113
|
const manager = setup()
|
|
108
|
-
await manager.setToken('test-token')
|
|
114
|
+
await manager.setToken('test-token', 'work')
|
|
109
115
|
await manager.setCurrentTeam('team-1', 'Team One')
|
|
110
116
|
await manager.setCurrentTeam('team-2', 'Team Two')
|
|
111
117
|
|
|
@@ -113,13 +119,13 @@ describe('TeamsCredentialManager', () => {
|
|
|
113
119
|
expect(team).toEqual({ team_id: 'team-2', team_name: 'Team Two' })
|
|
114
120
|
|
|
115
121
|
const config = await manager.loadConfig()
|
|
116
|
-
expect(config?.teams['team-1']).toEqual({ team_id: 'team-1', team_name: 'Team One' })
|
|
117
|
-
expect(config?.teams['team-2']).toEqual({ team_id: 'team-2', team_name: 'Team Two' })
|
|
122
|
+
expect(config?.accounts?.work?.teams['team-1']).toEqual({ team_id: 'team-1', team_name: 'Team One' })
|
|
123
|
+
expect(config?.accounts?.work?.teams['team-2']).toEqual({ team_id: 'team-2', team_name: 'Team Two' })
|
|
118
124
|
})
|
|
119
125
|
|
|
120
126
|
test('clearCredentials removes all credentials', async () => {
|
|
121
127
|
const manager = setup()
|
|
122
|
-
await manager.setToken('test-token', '2025-12-31T23:59:59Z')
|
|
128
|
+
await manager.setToken('test-token', 'work', '2025-12-31T23:59:59Z')
|
|
123
129
|
await manager.setCurrentTeam('team-123', 'Test Team')
|
|
124
130
|
|
|
125
131
|
await manager.clearCredentials()
|
|
@@ -136,7 +142,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
136
142
|
|
|
137
143
|
test('isTokenExpired returns true when no token_expires_at is set', async () => {
|
|
138
144
|
const manager = setup()
|
|
139
|
-
await manager.setToken('test-token')
|
|
145
|
+
await manager.setToken('test-token', 'work')
|
|
140
146
|
|
|
141
147
|
const expired = await manager.isTokenExpired()
|
|
142
148
|
expect(expired).toBe(true)
|
|
@@ -145,7 +151,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
145
151
|
test('isTokenExpired returns true when token is expired', async () => {
|
|
146
152
|
const manager = setup()
|
|
147
153
|
const pastDate = new Date(Date.now() - 60000).toISOString()
|
|
148
|
-
await manager.setToken('test-token', pastDate)
|
|
154
|
+
await manager.setToken('test-token', 'work', pastDate)
|
|
149
155
|
|
|
150
156
|
const expired = await manager.isTokenExpired()
|
|
151
157
|
expect(expired).toBe(true)
|
|
@@ -154,7 +160,7 @@ describe('TeamsCredentialManager', () => {
|
|
|
154
160
|
test('isTokenExpired returns false when token is not expired', async () => {
|
|
155
161
|
const manager = setup()
|
|
156
162
|
const futureDate = new Date(Date.now() + 3600000).toISOString()
|
|
157
|
-
await manager.setToken('test-token', futureDate)
|
|
163
|
+
await manager.setToken('test-token', 'work', futureDate)
|
|
158
164
|
|
|
159
165
|
const expired = await manager.isTokenExpired()
|
|
160
166
|
expect(expired).toBe(false)
|
|
@@ -162,14 +168,14 @@ describe('TeamsCredentialManager', () => {
|
|
|
162
168
|
|
|
163
169
|
test('multiple operations preserve existing data', async () => {
|
|
164
170
|
const manager = setup()
|
|
165
|
-
await manager.setToken('token-1', '2025-12-31T23:59:59Z')
|
|
171
|
+
await manager.setToken('token-1', 'work', '2025-12-31T23:59:59Z')
|
|
166
172
|
await manager.setCurrentTeam('team-1', 'Team One')
|
|
167
173
|
|
|
168
|
-
await manager.setToken('token-2')
|
|
174
|
+
await manager.setToken('token-2', 'work')
|
|
169
175
|
|
|
170
176
|
const config = await manager.loadConfig()
|
|
171
|
-
expect(config?.token).toBe('token-2')
|
|
172
|
-
expect(config?.current_team).toBe('team-1')
|
|
173
|
-
expect(config?.teams['team-1']).toEqual({ team_id: 'team-1', team_name: 'Team One' })
|
|
177
|
+
expect(config?.accounts?.work?.token).toBe('token-2')
|
|
178
|
+
expect(config?.accounts?.work?.current_team).toBe('team-1')
|
|
179
|
+
expect(config?.accounts?.work?.teams['team-1']).toEqual({ team_id: 'team-1', team_name: 'Team One' })
|
|
174
180
|
})
|
|
175
181
|
})
|