agent-messenger 1.3.6 → 1.5.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 (127) 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/cli.d.ts.map +1 -1
  8. package/dist/src/cli.js +3 -0
  9. package/dist/src/cli.js.map +1 -1
  10. package/dist/src/platforms/discord/cli.d.ts +2 -2
  11. package/dist/src/platforms/discord/cli.d.ts.map +1 -1
  12. package/dist/src/platforms/discord/cli.js +23 -1
  13. package/dist/src/platforms/discord/cli.js.map +1 -1
  14. package/dist/src/platforms/discord/commands/file.d.ts.map +1 -1
  15. package/dist/src/platforms/discord/commands/file.js +13 -7
  16. package/dist/src/platforms/discord/commands/file.js.map +1 -1
  17. package/dist/src/platforms/discord/commands/friend.d.ts.map +1 -1
  18. package/dist/src/platforms/discord/commands/friend.js +30 -30
  19. package/dist/src/platforms/discord/commands/friend.js.map +1 -1
  20. package/dist/src/platforms/discord/commands/index.d.ts +7 -0
  21. package/dist/src/platforms/discord/commands/index.d.ts.map +1 -1
  22. package/dist/src/platforms/discord/commands/index.js +7 -0
  23. package/dist/src/platforms/discord/commands/index.js.map +1 -1
  24. package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
  25. package/dist/src/platforms/discord/commands/snapshot.js +1 -2
  26. package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
  27. package/dist/src/platforms/discord/ensure-auth.d.ts +2 -0
  28. package/dist/src/platforms/discord/ensure-auth.d.ts.map +1 -0
  29. package/dist/src/platforms/discord/ensure-auth.js +31 -0
  30. package/dist/src/platforms/discord/ensure-auth.js.map +1 -0
  31. package/dist/src/platforms/slack/cli.d.ts +2 -2
  32. package/dist/src/platforms/slack/cli.d.ts.map +1 -1
  33. package/dist/src/platforms/slack/cli.js +15 -0
  34. package/dist/src/platforms/slack/cli.js.map +1 -1
  35. package/dist/src/platforms/slack/client.d.ts +1 -0
  36. package/dist/src/platforms/slack/client.d.ts.map +1 -1
  37. package/dist/src/platforms/slack/client.js +13 -0
  38. package/dist/src/platforms/slack/client.js.map +1 -1
  39. package/dist/src/platforms/slack/commands/channel.d.ts.map +1 -1
  40. package/dist/src/platforms/slack/commands/channel.js +2 -0
  41. package/dist/src/platforms/slack/commands/channel.js.map +1 -1
  42. package/dist/src/platforms/slack/commands/file.d.ts.map +1 -1
  43. package/dist/src/platforms/slack/commands/file.js +13 -5
  44. package/dist/src/platforms/slack/commands/file.js.map +1 -1
  45. package/dist/src/platforms/slack/commands/message.d.ts.map +1 -1
  46. package/dist/src/platforms/slack/commands/message.js +12 -6
  47. package/dist/src/platforms/slack/commands/message.js.map +1 -1
  48. package/dist/src/platforms/slack/commands/reaction.d.ts.map +1 -1
  49. package/dist/src/platforms/slack/commands/reaction.js +3 -0
  50. package/dist/src/platforms/slack/commands/reaction.js.map +1 -1
  51. package/dist/src/platforms/slack/commands/sections.d.ts.map +1 -1
  52. package/dist/src/platforms/slack/commands/sections.js +5 -6
  53. package/dist/src/platforms/slack/commands/sections.js.map +1 -1
  54. package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
  55. package/dist/src/platforms/slack/commands/snapshot.js +1 -2
  56. package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
  57. package/dist/src/platforms/slack/commands/unread.d.ts.map +1 -1
  58. package/dist/src/platforms/slack/commands/unread.js +2 -0
  59. package/dist/src/platforms/slack/commands/unread.js.map +1 -1
  60. package/dist/src/platforms/slack/commands/user.js +8 -8
  61. package/dist/src/platforms/slack/ensure-auth.d.ts +2 -0
  62. package/dist/src/platforms/slack/ensure-auth.d.ts.map +1 -0
  63. package/dist/src/platforms/slack/ensure-auth.js +30 -0
  64. package/dist/src/platforms/slack/ensure-auth.js.map +1 -0
  65. package/dist/src/platforms/slackbot/client.d.ts +1 -0
  66. package/dist/src/platforms/slackbot/client.d.ts.map +1 -1
  67. package/dist/src/platforms/slackbot/client.js +13 -0
  68. package/dist/src/platforms/slackbot/client.js.map +1 -1
  69. package/dist/src/platforms/slackbot/commands/channel.d.ts.map +1 -1
  70. package/dist/src/platforms/slackbot/commands/channel.js +3 -2
  71. package/dist/src/platforms/slackbot/commands/channel.js.map +1 -1
  72. package/dist/src/platforms/slackbot/commands/message.d.ts.map +1 -1
  73. package/dist/src/platforms/slackbot/commands/message.js +18 -12
  74. package/dist/src/platforms/slackbot/commands/message.js.map +1 -1
  75. package/dist/src/platforms/slackbot/commands/reaction.d.ts.map +1 -1
  76. package/dist/src/platforms/slackbot/commands/reaction.js +8 -6
  77. package/dist/src/platforms/slackbot/commands/reaction.js.map +1 -1
  78. package/dist/src/platforms/teams/cli.d.ts +2 -2
  79. package/dist/src/platforms/teams/cli.d.ts.map +1 -1
  80. package/dist/src/platforms/teams/cli.js +15 -0
  81. package/dist/src/platforms/teams/cli.js.map +1 -1
  82. package/dist/src/platforms/teams/commands/file.js +12 -12
  83. package/dist/src/platforms/teams/commands/file.js.map +1 -1
  84. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
  85. package/dist/src/platforms/teams/commands/snapshot.js +1 -2
  86. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
  87. package/dist/src/platforms/teams/ensure-auth.d.ts +2 -0
  88. package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -0
  89. package/dist/src/platforms/teams/ensure-auth.js +32 -0
  90. package/dist/src/platforms/teams/ensure-auth.js.map +1 -0
  91. package/e2e/README.md +1 -1
  92. package/package.json +1 -1
  93. package/skills/agent-discord/SKILL.md +22 -22
  94. package/skills/agent-slack/SKILL.md +28 -40
  95. package/skills/agent-teams/SKILL.md +41 -65
  96. package/skills/agent-teams/references/common-patterns.md +63 -49
  97. package/src/cli.ts +4 -0
  98. package/src/platforms/discord/cli.ts +30 -0
  99. package/src/platforms/discord/commands/file.ts +13 -7
  100. package/src/platforms/discord/commands/friend.ts +34 -34
  101. package/src/platforms/discord/commands/index.ts +7 -0
  102. package/src/platforms/discord/commands/snapshot.ts +1 -2
  103. package/src/platforms/discord/ensure-auth.test.ts +123 -0
  104. package/src/platforms/discord/ensure-auth.ts +31 -0
  105. package/src/platforms/slack/cli.ts +16 -0
  106. package/src/platforms/slack/client.test.ts +101 -0
  107. package/src/platforms/slack/client.ts +22 -0
  108. package/src/platforms/slack/commands/channel.ts +2 -0
  109. package/src/platforms/slack/commands/file.ts +15 -5
  110. package/src/platforms/slack/commands/message.ts +17 -6
  111. package/src/platforms/slack/commands/reaction.ts +3 -0
  112. package/src/platforms/slack/commands/sections.ts +8 -9
  113. package/src/platforms/slack/commands/snapshot.ts +1 -2
  114. package/src/platforms/slack/commands/unread.ts +2 -0
  115. package/src/platforms/slack/commands/user.ts +8 -8
  116. package/src/platforms/slack/ensure-auth.test.ts +186 -0
  117. package/src/platforms/slack/ensure-auth.ts +30 -0
  118. package/src/platforms/slackbot/client.test.ts +87 -0
  119. package/src/platforms/slackbot/client.ts +21 -0
  120. package/src/platforms/slackbot/commands/channel.ts +3 -2
  121. package/src/platforms/slackbot/commands/message.ts +18 -12
  122. package/src/platforms/slackbot/commands/reaction.ts +8 -6
  123. package/src/platforms/teams/cli.ts +16 -0
  124. package/src/platforms/teams/commands/file.ts +12 -12
  125. package/src/platforms/teams/commands/snapshot.ts +1 -2
  126. package/src/platforms/teams/ensure-auth.test.ts +167 -0
  127. package/src/platforms/teams/ensure-auth.ts +34 -0
@@ -15,18 +15,20 @@ This guide covers typical workflows for AI agents interacting with Microsoft Tea
15
15
  ```bash
16
16
  #!/bin/bash
17
17
 
18
+ TEAM_ID="team-uuid-here"
19
+
18
20
  # First, ensure token is valid
19
21
  agent-teams auth extract 2>/dev/null || true
20
22
 
21
23
  # Get channel ID from channel list
22
- CHANNELS=$(agent-teams channel list)
24
+ CHANNELS=$(agent-teams channel list "$TEAM_ID")
23
25
  CHANNEL_ID=$(echo "$CHANNELS" | jq -r '.[] | select(.name=="General") | .id')
24
26
 
25
27
  # Send message using channel ID
26
- agent-teams message send "$CHANNEL_ID" "Deployment completed successfully!"
28
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Deployment completed successfully!"
27
29
 
28
30
  # With error handling
29
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello world")
31
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello world")
30
32
  if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
31
33
  echo "Message sent!"
32
34
  else
@@ -36,7 +38,7 @@ else
36
38
  if echo "$ERROR" | grep -qi "expired\|401"; then
37
39
  echo "Token expired, refreshing..."
38
40
  agent-teams auth extract
39
- agent-teams message send "$CHANNEL_ID" "Hello world"
41
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello world"
40
42
  else
41
43
  echo "Failed: $ERROR"
42
44
  exit 1
@@ -53,6 +55,7 @@ fi
53
55
  ```bash
54
56
  #!/bin/bash
55
57
 
58
+ TEAM_ID="team-uuid-here"
56
59
  CHANNEL_ID="19:abc123@thread.tacv2"
57
60
  LAST_ID=""
58
61
  TOKEN_CHECK_INTERVAL=300 # Check token every 5 minutes
@@ -81,7 +84,7 @@ while true; do
81
84
  refresh_token_if_needed
82
85
 
83
86
  # Get latest message
84
- MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1)
87
+ MESSAGES=$(agent-teams message list "$TEAM_ID" "$CHANNEL_ID" --limit 1)
85
88
 
86
89
  # Handle token expiry error
87
90
  if echo "$MESSAGES" | jq -e '.error' | grep -qi "expired\|401" 2>/dev/null; then
@@ -101,7 +104,7 @@ while true; do
101
104
 
102
105
  # Process message here
103
106
  if echo "$CONTENT" | grep -q "bot"; then
104
- agent-teams message send "$CHANNEL_ID" "You called?"
107
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "You called?"
105
108
  fi
106
109
  fi
107
110
 
@@ -154,10 +157,12 @@ echo "$SNAPSHOT" | jq -r '.recent_messages[] | " [\(.channel_name)] \(.author):
154
157
  ```bash
155
158
  #!/bin/bash
156
159
 
160
+ TEAM_ID="team-uuid-here"
161
+
157
162
  get_channel_id() {
158
163
  local channel_name=$1
159
164
 
160
- CHANNELS=$(agent-teams channel list)
165
+ CHANNELS=$(agent-teams channel list "$TEAM_ID")
161
166
  CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg name "$channel_name" '.[] | select(.name==$name) | .id')
162
167
 
163
168
  if [ -z "$CHANNEL_ID" ]; then
@@ -171,7 +176,7 @@ get_channel_id() {
171
176
  # Usage
172
177
  GENERAL_ID=$(get_channel_id "General")
173
178
  if [ $? -eq 0 ]; then
174
- agent-teams message send "$GENERAL_ID" "Hello!"
179
+ agent-teams message send "$TEAM_ID" "$GENERAL_ID" "Hello!"
175
180
  fi
176
181
  ```
177
182
 
@@ -184,6 +189,7 @@ fi
184
189
  ```bash
185
190
  #!/bin/bash
186
191
 
192
+ TEAM_ID="team-uuid-here"
187
193
  MESSAGE="System maintenance in 30 minutes"
188
194
  CHANNEL_NAMES=("General" "Announcements" "Engineering")
189
195
 
@@ -191,7 +197,7 @@ CHANNEL_NAMES=("General" "Announcements" "Engineering")
191
197
  agent-teams auth extract
192
198
 
193
199
  # Get all channels once
194
- CHANNELS=$(agent-teams channel list)
200
+ CHANNELS=$(agent-teams channel list "$TEAM_ID")
195
201
 
196
202
  for name in "${CHANNEL_NAMES[@]}"; do
197
203
  CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
@@ -202,7 +208,7 @@ for name in "${CHANNEL_NAMES[@]}"; do
202
208
  fi
203
209
 
204
210
  echo "Posting to #$name..."
205
- RESULT=$(agent-teams message send "$CHANNEL_ID" "$MESSAGE")
211
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "$MESSAGE")
206
212
 
207
213
  if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
208
214
  echo " Posted to #$name"
@@ -224,18 +230,19 @@ done
224
230
  ```bash
225
231
  #!/bin/bash
226
232
 
233
+ TEAM_ID="team-uuid-here"
227
234
  CHANNEL_ID="19:abc123@thread.tacv2"
228
235
  REPORT_FILE="./daily-report.pdf"
229
236
 
230
237
  # Upload file
231
- UPLOAD_RESULT=$(agent-teams file upload "$CHANNEL_ID" "$REPORT_FILE")
238
+ UPLOAD_RESULT=$(agent-teams file upload "$TEAM_ID" "$CHANNEL_ID" "$REPORT_FILE")
232
239
 
233
240
  if echo "$UPLOAD_RESULT" | jq -e '.id' > /dev/null 2>&1; then
234
241
  FILE_ID=$(echo "$UPLOAD_RESULT" | jq -r '.id')
235
242
  echo "File uploaded: $FILE_ID"
236
243
 
237
244
  # Send context message
238
- agent-teams message send "$CHANNEL_ID" "Daily report is ready! Key highlights:
245
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Daily report is ready! Key highlights:
239
246
  - 95% test coverage
240
247
  - 3 bugs fixed
241
248
  - 2 new features deployed"
@@ -254,11 +261,12 @@ fi
254
261
  ```bash
255
262
  #!/bin/bash
256
263
 
264
+ TEAM_ID="team-uuid-here"
257
265
  CHANNEL_ID="19:abc123@thread.tacv2"
258
266
  USERNAME="john"
259
267
 
260
268
  # Get team members
261
- USERS=$(agent-teams user list)
269
+ USERS=$(agent-teams user list "$TEAM_ID")
262
270
  USER=$(echo "$USERS" | jq -r --arg name "$USERNAME" 'first(.[] | select(.displayName | ascii_downcase | contains($name | ascii_downcase)))')
263
271
  USER_ID=$(echo "$USER" | jq -r '.id')
264
272
  USER_NAME=$(echo "$USER" | jq -r '.displayName')
@@ -269,7 +277,7 @@ if [ -z "$USER_ID" ] || [ "$USER_ID" = "null" ]; then
269
277
  fi
270
278
 
271
279
  # Send message with mention (Teams format)
272
- agent-teams message send "$CHANNEL_ID" "Hey <at id=\"$USER_ID\">$USER_NAME</at>, the build is ready for review!"
280
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hey <at id=\"$USER_ID\">$USER_NAME</at>, the build is ready for review!"
273
281
  ```
274
282
 
275
283
  **When to use**: Notifications, task assignments, code review requests.
@@ -283,24 +291,25 @@ agent-teams message send "$CHANNEL_ID" "Hey <at id=\"$USER_ID\">$USER_NAME</at>,
283
291
  ```bash
284
292
  #!/bin/bash
285
293
 
294
+ TEAM_ID="team-uuid-here"
286
295
  CHANNEL_ID="19:abc123@thread.tacv2"
287
296
 
288
297
  # Send deployment message
289
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Deploying v2.1.0 to production...")
298
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Deploying v2.1.0 to production...")
290
299
  MSG_ID=$(echo "$RESULT" | jq -r '.id')
291
300
 
292
301
  # Mark as in-progress
293
- agent-teams reaction add "$CHANNEL_ID" "$MSG_ID" "hourglass"
302
+ agent-teams reaction add "$TEAM_ID" "$CHANNEL_ID" "$MSG_ID" "hourglass"
294
303
 
295
304
  # Simulate deployment
296
305
  sleep 5
297
306
 
298
307
  # Remove in-progress, add success
299
- agent-teams reaction remove "$CHANNEL_ID" "$MSG_ID" "hourglass"
300
- agent-teams reaction add "$CHANNEL_ID" "$MSG_ID" "checkmark"
308
+ agent-teams reaction remove "$TEAM_ID" "$CHANNEL_ID" "$MSG_ID" "hourglass"
309
+ agent-teams reaction add "$TEAM_ID" "$CHANNEL_ID" "$MSG_ID" "checkmark"
301
310
 
302
311
  # Send completion message
303
- agent-teams message send "$CHANNEL_ID" "Deployed v2.1.0 to production successfully!"
312
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Deployed v2.1.0 to production successfully!"
304
313
  ```
305
314
 
306
315
  **When to use**: Visual status tracking, workflow states, quick acknowledgments.
@@ -312,16 +321,19 @@ agent-teams message send "$CHANNEL_ID" "Deployed v2.1.0 to production successful
312
321
  ```bash
313
322
  #!/bin/bash
314
323
 
324
+ TEAM_ID="team-uuid-here"
325
+
315
326
  send_with_retry() {
316
- local channel_id=$1
317
- local message=$2
327
+ local team_id=$1
328
+ local channel_id=$2
329
+ local message=$3
318
330
  local max_attempts=3
319
331
  local attempt=1
320
332
 
321
333
  while [ $attempt -le $max_attempts ]; do
322
334
  echo "Attempt $attempt/$max_attempts..."
323
335
 
324
- RESULT=$(agent-teams message send "$channel_id" "$message")
336
+ RESULT=$(agent-teams message send "$team_id" "$channel_id" "$message")
325
337
 
326
338
  if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
327
339
  echo "Message sent successfully!"
@@ -358,7 +370,7 @@ send_with_retry() {
358
370
 
359
371
  # Usage
360
372
  CHANNEL_ID="19:abc123@thread.tacv2"
361
- send_with_retry "$CHANNEL_ID" "Important message!"
373
+ send_with_retry "$TEAM_ID" "$CHANNEL_ID" "Important message!"
362
374
  ```
363
375
 
364
376
  **When to use**: Production scripts, critical notifications, unreliable networks.
@@ -383,7 +395,7 @@ if [ -n "$TARGET_TEAM" ]; then
383
395
  fi
384
396
 
385
397
  # Now operations use the new team
386
- agent-teams channel list
398
+ agent-teams channel list "$TARGET_TEAM"
387
399
  ```
388
400
 
389
401
  **When to use**: Managing multiple teams, cross-team operations.
@@ -395,6 +407,8 @@ agent-teams channel list
395
407
  ```bash
396
408
  #!/bin/bash
397
409
 
410
+ TEAM_ID="team-uuid-here"
411
+
398
412
  # Wrapper function that handles token refresh
399
413
  teams_cmd() {
400
414
  local result
@@ -415,8 +429,8 @@ teams_cmd() {
415
429
  }
416
430
 
417
431
  # Usage - wrap any agent-teams command
418
- CHANNELS=$(teams_cmd agent-teams channel list)
419
- RESULT=$(teams_cmd agent-teams message send "$CHANNEL_ID" "Hello!")
432
+ CHANNELS=$(teams_cmd agent-teams channel list "$TEAM_ID")
433
+ RESULT=$(teams_cmd agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello!")
420
434
  SNAPSHOT=$(teams_cmd agent-teams snapshot)
421
435
  ```
422
436
 
@@ -428,14 +442,14 @@ SNAPSHOT=$(teams_cmd agent-teams snapshot)
428
442
 
429
443
  ```bash
430
444
  # Good - handle token expiry
431
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
445
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello")
432
446
  if echo "$RESULT" | grep -qi "expired\|401"; then
433
447
  agent-teams auth extract
434
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
448
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello")
435
449
  fi
436
450
 
437
451
  # Bad - assume token is always valid
438
- agent-teams message send "$CHANNEL_ID" "Hello"
452
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello"
439
453
  ```
440
454
 
441
455
  ### 2. Refresh Token Proactively for Long-Running Scripts
@@ -454,7 +468,7 @@ done
454
468
 
455
469
  # Bad - wait for failure
456
470
  while true; do
457
- agent-teams message send "$CHANNEL_ID" "Status update" # Will fail after 60-90 min
471
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Status update" # Will fail after 60-90 min
458
472
  sleep 60
459
473
  done
460
474
  ```
@@ -463,19 +477,19 @@ done
463
477
 
464
478
  ```bash
465
479
  # Good - look up channel ID
466
- CHANNELS=$(agent-teams channel list)
480
+ CHANNELS=$(agent-teams channel list "$TEAM_ID")
467
481
  CHANNEL_ID=$(echo "$CHANNELS" | jq -r '.[] | select(.name=="General") | .id')
468
- agent-teams message send "$CHANNEL_ID" "Hello"
482
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello"
469
483
 
470
484
  # Bad - hardcoded IDs without documentation
471
- agent-teams message send "19:abc123@thread.tacv2" "Hello"
485
+ agent-teams message send "$TEAM_ID" "19:abc123@thread.tacv2" "Hello"
472
486
  ```
473
487
 
474
488
  ### 4. Check for Success
475
489
 
476
490
  ```bash
477
491
  # Good
478
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
492
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello")
479
493
  if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
480
494
  echo "Success!"
481
495
  else
@@ -483,7 +497,7 @@ else
483
497
  fi
484
498
 
485
499
  # Bad
486
- agent-teams message send "$CHANNEL_ID" "Hello" # No error checking
500
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello" # No error checking
487
501
  ```
488
502
 
489
503
  ### 5. Rate Limit Your Requests
@@ -491,13 +505,13 @@ agent-teams message send "$CHANNEL_ID" "Hello" # No error checking
491
505
  ```bash
492
506
  # Good - respect Teams API limits
493
507
  for channel_id in "${CHANNEL_IDS[@]}"; do
494
- agent-teams message send "$channel_id" "$MESSAGE"
508
+ agent-teams message send "$TEAM_ID" "$channel_id" "$MESSAGE"
495
509
  sleep 1 # 1 second between requests
496
510
  done
497
511
 
498
512
  # Bad - rapid-fire requests
499
513
  for channel_id in "${CHANNEL_IDS[@]}"; do
500
- agent-teams message send "$channel_id" "$MESSAGE"
514
+ agent-teams message send "$TEAM_ID" "$channel_id" "$MESSAGE"
501
515
  done
502
516
  ```
503
517
 
@@ -505,17 +519,17 @@ done
505
519
 
506
520
  ```bash
507
521
  # Good - fetch once, reuse
508
- CHANNELS=$(agent-teams channel list)
522
+ CHANNELS=$(agent-teams channel list "$TEAM_ID")
509
523
  for name in "${CHANNEL_NAMES[@]}"; do
510
524
  id=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
511
- agent-teams message send "$id" "$MESSAGE"
525
+ agent-teams message send "$TEAM_ID" "$id" "$MESSAGE"
512
526
  done
513
527
 
514
528
  # Bad - fetch repeatedly
515
529
  for name in "${CHANNEL_NAMES[@]}"; do
516
- CHANNELS=$(agent-teams channel list) # Wasteful!
530
+ CHANNELS=$(agent-teams channel list "$TEAM_ID") # Wasteful!
517
531
  id=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
518
- agent-teams message send "$id" "$MESSAGE"
532
+ agent-teams message send "$TEAM_ID" "$id" "$MESSAGE"
519
533
  done
520
534
  ```
521
535
 
@@ -526,7 +540,7 @@ done
526
540
  ```bash
527
541
  # Bad - ignores the 60-90 minute token limit
528
542
  while true; do
529
- agent-teams message list "$CHANNEL_ID" --limit 1
543
+ agent-teams message list "$TEAM_ID" "$CHANNEL_ID" --limit 1
530
544
  sleep 10
531
545
  done
532
546
  # Will fail silently after ~1 hour
@@ -538,7 +552,7 @@ while true; do
538
552
  agent-teams auth extract
539
553
  fi
540
554
 
541
- agent-teams message list "$CHANNEL_ID" --limit 1
555
+ agent-teams message list "$TEAM_ID" "$CHANNEL_ID" --limit 1
542
556
  sleep 10
543
557
  done
544
558
  ```
@@ -548,13 +562,13 @@ done
548
562
  ```bash
549
563
  # Bad - polls every second (may get rate limited)
550
564
  while true; do
551
- agent-teams message list "$CHANNEL_ID" --limit 1
565
+ agent-teams message list "$TEAM_ID" "$CHANNEL_ID" --limit 1
552
566
  sleep 1
553
567
  done
554
568
 
555
569
  # Good - reasonable interval
556
570
  while true; do
557
- agent-teams message list "$CHANNEL_ID" --limit 1
571
+ agent-teams message list "$TEAM_ID" "$CHANNEL_ID" --limit 1
558
572
  sleep 10 # 10 seconds
559
573
  done
560
574
  ```
@@ -563,11 +577,11 @@ done
563
577
 
564
578
  ```bash
565
579
  # Bad
566
- agent-teams message send "$CHANNEL_ID" "Hello"
580
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello"
567
581
  # Continues even if it failed
568
582
 
569
583
  # Good
570
- RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
584
+ RESULT=$(agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Hello")
571
585
  if ! echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
572
586
  echo "Failed to send message"
573
587
  exit 1
@@ -579,7 +593,7 @@ fi
579
593
  ```bash
580
594
  # Bad - sends 100 messages
581
595
  for i in {1..100}; do
582
- agent-teams message send "$CHANNEL_ID" "Message $i"
596
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "Message $i"
583
597
  done
584
598
 
585
599
  # Good - batch into single message
@@ -587,7 +601,7 @@ MESSAGE="Updates:"
587
601
  for i in {1..100}; do
588
602
  MESSAGE="$MESSAGE\n$i. Item $i"
589
603
  done
590
- agent-teams message send "$CHANNEL_ID" "$MESSAGE"
604
+ agent-teams message send "$TEAM_ID" "$CHANNEL_ID" "$MESSAGE"
591
605
  ```
592
606
 
593
607
  ## See Also
package/src/cli.ts CHANGED
@@ -26,6 +26,10 @@ program.command('teams', 'Interact with Microsoft Teams', {
26
26
  executableFile: join(__dirname, 'platforms', 'teams', `cli${ext}`),
27
27
  })
28
28
 
29
+ program.command('slackbot', 'Interact with Slack using bot tokens', {
30
+ executableFile: join(__dirname, 'platforms', 'slackbot', `cli${ext}`),
31
+ })
32
+
29
33
  program.parse(process.argv)
30
34
 
31
35
  export default program
@@ -1,17 +1,35 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
+ import type { Command as CommandType } from 'commander'
3
4
  import { Command } from 'commander'
4
5
  import pkg from '../../../package.json' with { type: 'json' }
5
6
  import {
6
7
  authCommand,
7
8
  channelCommand,
9
+ dmCommand,
8
10
  fileCommand,
11
+ friendCommand,
12
+ memberCommand,
13
+ mentionCommand,
9
14
  messageCommand,
15
+ noteCommand,
16
+ profileCommand,
10
17
  reactionCommand,
11
18
  serverCommand,
12
19
  snapshotCommand,
20
+ threadCommand,
13
21
  userCommand,
14
22
  } from './commands'
23
+ import { ensureDiscordAuth } from './ensure-auth'
24
+
25
+ function isAuthCommand(command: CommandType): boolean {
26
+ let cmd: CommandType | null = command
27
+ while (cmd) {
28
+ if (cmd.name() === 'auth') return true
29
+ cmd = cmd.parent
30
+ }
31
+ return false
32
+ }
15
33
 
16
34
  const program = new Command()
17
35
 
@@ -22,13 +40,25 @@ program
22
40
  .option('--pretty', 'Pretty-print JSON output')
23
41
  .option('--server <id>', 'Use specific server')
24
42
 
43
+ program.hook('preAction', async (_thisCommand, actionCommand) => {
44
+ if (isAuthCommand(actionCommand)) return
45
+ await ensureDiscordAuth()
46
+ })
47
+
25
48
  program.addCommand(authCommand)
26
49
  program.addCommand(serverCommand)
27
50
  program.addCommand(channelCommand)
51
+ program.addCommand(dmCommand)
28
52
  program.addCommand(fileCommand)
53
+ program.addCommand(friendCommand)
54
+ program.addCommand(memberCommand)
55
+ program.addCommand(mentionCommand)
29
56
  program.addCommand(messageCommand)
57
+ program.addCommand(noteCommand)
58
+ program.addCommand(profileCommand)
30
59
  program.addCommand(reactionCommand)
31
60
  program.addCommand(snapshotCommand)
61
+ program.addCommand(threadCommand)
32
62
  program.addCommand(userCommand)
33
63
 
34
64
  program.parse(process.argv)
@@ -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)')