agent-messenger 1.0.0 → 1.1.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 (330) hide show
  1. package/.claude/commands/release.md +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +1 -1
  4. package/.github/workflows/e2e.yml.disabled +69 -0
  5. package/README.md +16 -14
  6. package/biome.json +33 -1
  7. package/bun.lock +63 -0
  8. package/dist/package.json +8 -4
  9. package/dist/src/cli.d.ts.map +1 -1
  10. package/dist/src/cli.js +4 -1
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/platforms/discord/cli.js +1 -1
  13. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/client.js +3 -3
  15. package/dist/src/platforms/discord/client.js.map +1 -1
  16. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/user.js +10 -1
  18. package/dist/src/platforms/discord/commands/user.js.map +1 -1
  19. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/credential-manager.js +18 -12
  21. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  22. package/dist/src/platforms/slack/cli.js +1 -1
  23. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
  24. package/dist/src/platforms/slack/credential-manager.js +20 -6
  25. package/dist/src/platforms/slack/credential-manager.js.map +1 -1
  26. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  27. package/dist/src/platforms/slack/token-extractor.js +34 -9
  28. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  29. package/dist/src/platforms/teams/cli.d.ts.map +1 -0
  30. package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
  31. package/dist/src/platforms/teams/cli.js.map +1 -0
  32. package/dist/src/platforms/teams/client.d.ts +32 -0
  33. package/dist/src/platforms/teams/client.d.ts.map +1 -0
  34. package/dist/src/platforms/teams/client.js +202 -0
  35. package/dist/src/platforms/teams/client.js.map +1 -0
  36. package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
  37. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
  38. package/dist/src/platforms/teams/commands/auth.js +176 -0
  39. package/dist/src/platforms/teams/commands/auth.js.map +1 -0
  40. package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
  41. package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
  42. package/dist/src/platforms/teams/commands/channel.js +97 -0
  43. package/dist/src/platforms/teams/commands/channel.js.map +1 -0
  44. package/dist/src/platforms/teams/commands/file.d.ts +12 -0
  45. package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
  46. package/dist/src/platforms/teams/commands/file.js +104 -0
  47. package/dist/src/platforms/teams/commands/file.js.map +1 -0
  48. package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
  49. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
  50. package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
  51. package/dist/src/platforms/teams/commands/index.js.map +1 -0
  52. package/dist/src/platforms/teams/commands/message.d.ts +17 -0
  53. package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
  54. package/dist/src/platforms/teams/commands/message.js +133 -0
  55. package/dist/src/platforms/teams/commands/message.js.map +1 -0
  56. package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
  57. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
  58. package/dist/src/platforms/teams/commands/reaction.js +68 -0
  59. package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
  60. package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
  61. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
  62. package/dist/src/platforms/teams/commands/snapshot.js +85 -0
  63. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
  64. package/dist/src/platforms/teams/commands/team.d.ts +18 -0
  65. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
  66. package/dist/src/platforms/teams/commands/team.js +130 -0
  67. package/dist/src/platforms/teams/commands/team.js.map +1 -0
  68. package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
  69. package/dist/src/platforms/teams/commands/user.js +88 -0
  70. package/dist/src/platforms/teams/commands/user.js.map +1 -0
  71. package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
  72. package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
  73. package/dist/src/platforms/teams/credential-manager.js +81 -0
  74. package/dist/src/platforms/teams/credential-manager.js.map +1 -0
  75. package/dist/src/platforms/teams/index.d.ts +4 -0
  76. package/dist/src/platforms/teams/index.d.ts.map +1 -0
  77. package/dist/src/platforms/teams/index.js +6 -0
  78. package/dist/src/platforms/teams/index.js.map +1 -0
  79. package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
  80. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
  81. package/dist/src/platforms/teams/token-extractor.js +335 -0
  82. package/dist/src/platforms/teams/token-extractor.js.map +1 -0
  83. package/dist/src/platforms/teams/types.d.ts +209 -0
  84. package/dist/src/platforms/teams/types.d.ts.map +1 -0
  85. package/dist/src/platforms/teams/types.js +65 -0
  86. package/dist/src/platforms/teams/types.js.map +1 -0
  87. package/docs/teams.md +321 -0
  88. package/e2e/README.md +256 -0
  89. package/e2e/config.ts +45 -0
  90. package/e2e/discord.e2e.test.ts +252 -0
  91. package/e2e/helpers.ts +107 -0
  92. package/e2e/slack.e2e.test.ts +309 -0
  93. package/package.json +8 -4
  94. package/scripts/postbuild.ts +15 -0
  95. package/skills/agent-teams/SKILL.md +292 -0
  96. package/skills/agent-teams/references/authentication.md +375 -0
  97. package/skills/agent-teams/references/common-patterns.md +596 -0
  98. package/skills/agent-teams/templates/monitor-channel.sh +239 -0
  99. package/skills/agent-teams/templates/post-message.sh +224 -0
  100. package/skills/agent-teams/templates/team-summary.sh +210 -0
  101. package/src/cli.ts +4 -0
  102. package/src/platforms/discord/client.ts +3 -3
  103. package/src/platforms/discord/commands/auth.test.ts +48 -32
  104. package/src/platforms/discord/commands/channel.test.ts +54 -42
  105. package/src/platforms/discord/commands/file.test.ts +40 -53
  106. package/src/platforms/discord/commands/guild.test.ts +47 -27
  107. package/src/platforms/discord/commands/message.test.ts +54 -51
  108. package/src/platforms/discord/commands/reaction.test.ts +54 -42
  109. package/src/platforms/discord/commands/user.ts +12 -1
  110. package/src/platforms/discord/credential-manager.test.ts +137 -136
  111. package/src/platforms/discord/credential-manager.ts +20 -13
  112. package/src/platforms/discord/token-extractor.test.ts +133 -383
  113. package/{tests → src/platforms/slack}/cli.test.ts +3 -3
  114. package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
  115. package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
  116. package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
  117. package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
  118. package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
  119. package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
  120. package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
  121. package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
  122. package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
  123. package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
  124. package/src/platforms/slack/credential-manager.ts +22 -7
  125. package/src/platforms/slack/token-extractor-node-test.ts +40 -0
  126. package/src/platforms/slack/token-extractor-node.test.ts +10 -0
  127. package/src/platforms/slack/token-extractor.ts +36 -10
  128. package/{tests → src/platforms/slack}/types.test.ts +1 -1
  129. package/src/platforms/teams/cli.ts +36 -0
  130. package/src/platforms/teams/client.test.ts +500 -0
  131. package/src/platforms/teams/client.ts +365 -0
  132. package/src/platforms/teams/commands/auth.test.ts +99 -0
  133. package/src/platforms/teams/commands/auth.ts +232 -0
  134. package/src/platforms/teams/commands/channel.test.ts +147 -0
  135. package/src/platforms/teams/commands/channel.ts +129 -0
  136. package/src/platforms/teams/commands/file.test.ts +88 -0
  137. package/src/platforms/teams/commands/file.ts +144 -0
  138. package/src/platforms/teams/commands/index.ts +12 -0
  139. package/src/platforms/teams/commands/message.test.ts +110 -0
  140. package/src/platforms/teams/commands/message.ts +188 -0
  141. package/src/platforms/teams/commands/reaction.test.ts +87 -0
  142. package/src/platforms/teams/commands/reaction.ts +104 -0
  143. package/src/platforms/teams/commands/snapshot.test.ts +35 -0
  144. package/src/platforms/teams/commands/snapshot.ts +115 -0
  145. package/src/platforms/teams/commands/team.test.ts +157 -0
  146. package/src/platforms/teams/commands/team.ts +164 -0
  147. package/src/platforms/teams/commands/user.test.ts +83 -0
  148. package/src/platforms/teams/commands/user.ts +112 -0
  149. package/src/platforms/teams/credential-manager.test.ts +178 -0
  150. package/src/platforms/teams/credential-manager.ts +92 -0
  151. package/src/platforms/teams/index.ts +5 -0
  152. package/src/platforms/teams/token-extractor.test.ts +429 -0
  153. package/src/platforms/teams/token-extractor.ts +462 -0
  154. package/src/platforms/teams/types.test.ts +226 -0
  155. package/src/platforms/teams/types.ts +140 -0
  156. package/tsconfig.json +1 -1
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/auth.d.ts +0 -3
  160. package/dist/commands/auth.d.ts.map +0 -1
  161. package/dist/commands/auth.js +0 -140
  162. package/dist/commands/auth.js.map +0 -1
  163. package/dist/commands/channel.d.ts +0 -3
  164. package/dist/commands/channel.d.ts.map +0 -1
  165. package/dist/commands/channel.js +0 -118
  166. package/dist/commands/channel.js.map +0 -1
  167. package/dist/commands/file.d.ts +0 -3
  168. package/dist/commands/file.d.ts.map +0 -1
  169. package/dist/commands/file.js +0 -113
  170. package/dist/commands/file.js.map +0 -1
  171. package/dist/commands/index.d.ts.map +0 -1
  172. package/dist/commands/index.js.map +0 -1
  173. package/dist/commands/message.d.ts +0 -3
  174. package/dist/commands/message.d.ts.map +0 -1
  175. package/dist/commands/message.js +0 -214
  176. package/dist/commands/message.js.map +0 -1
  177. package/dist/commands/reaction.d.ts +0 -3
  178. package/dist/commands/reaction.d.ts.map +0 -1
  179. package/dist/commands/reaction.js +0 -100
  180. package/dist/commands/reaction.js.map +0 -1
  181. package/dist/commands/snapshot.d.ts +0 -3
  182. package/dist/commands/snapshot.d.ts.map +0 -1
  183. package/dist/commands/snapshot.js +0 -88
  184. package/dist/commands/snapshot.js.map +0 -1
  185. package/dist/commands/user.d.ts.map +0 -1
  186. package/dist/commands/user.js +0 -96
  187. package/dist/commands/user.js.map +0 -1
  188. package/dist/commands/workspace.d.ts +0 -3
  189. package/dist/commands/workspace.d.ts.map +0 -1
  190. package/dist/commands/workspace.js +0 -89
  191. package/dist/commands/workspace.js.map +0 -1
  192. package/dist/lib/credential-manager.d.ts +0 -13
  193. package/dist/lib/credential-manager.d.ts.map +0 -1
  194. package/dist/lib/credential-manager.js +0 -58
  195. package/dist/lib/credential-manager.js.map +0 -1
  196. package/dist/lib/index.d.ts +0 -3
  197. package/dist/lib/index.d.ts.map +0 -1
  198. package/dist/lib/index.js +0 -3
  199. package/dist/lib/index.js.map +0 -1
  200. package/dist/lib/ref-manager.d.ts +0 -26
  201. package/dist/lib/ref-manager.d.ts.map +0 -1
  202. package/dist/lib/ref-manager.js +0 -92
  203. package/dist/lib/ref-manager.js.map +0 -1
  204. package/dist/lib/slack-client.d.ts +0 -37
  205. package/dist/lib/slack-client.d.ts.map +0 -1
  206. package/dist/lib/slack-client.js +0 -379
  207. package/dist/lib/slack-client.js.map +0 -1
  208. package/dist/lib/token-extractor.d.ts +0 -28
  209. package/dist/lib/token-extractor.d.ts.map +0 -1
  210. package/dist/lib/token-extractor.js +0 -401
  211. package/dist/lib/token-extractor.js.map +0 -1
  212. package/dist/src/platforms/discord/client.test.d.ts +0 -2
  213. package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
  214. package/dist/src/platforms/discord/client.test.js +0 -367
  215. package/dist/src/platforms/discord/client.test.js.map +0 -1
  216. package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
  217. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
  218. package/dist/src/platforms/discord/commands/auth.test.js +0 -65
  219. package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
  220. package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
  221. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
  222. package/dist/src/platforms/discord/commands/channel.test.js +0 -136
  223. package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
  224. package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
  225. package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
  226. package/dist/src/platforms/discord/commands/file.test.js +0 -83
  227. package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
  228. package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
  229. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
  230. package/dist/src/platforms/discord/commands/guild.test.js +0 -100
  231. package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
  232. package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
  233. package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
  234. package/dist/src/platforms/discord/commands/message.test.js +0 -91
  235. package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
  236. package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
  237. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
  238. package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
  239. package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
  240. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
  241. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
  242. package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
  243. package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
  244. package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
  245. package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
  246. package/dist/src/platforms/discord/commands/user.test.js +0 -103
  247. package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
  248. package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
  249. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
  250. package/dist/src/platforms/discord/credential-manager.test.js +0 -136
  251. package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
  252. package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
  253. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
  254. package/dist/src/platforms/discord/token-extractor.test.js +0 -789
  255. package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
  256. package/dist/src/platforms/discord/types.test.d.ts +0 -2
  257. package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
  258. package/dist/src/platforms/discord/types.test.js +0 -211
  259. package/dist/src/platforms/discord/types.test.js.map +0 -1
  260. package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
  261. package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
  262. package/dist/src/shared/utils/concurrency.test.js +0 -39
  263. package/dist/src/shared/utils/concurrency.test.js.map +0 -1
  264. package/dist/tests/cli.test.d.ts +0 -2
  265. package/dist/tests/cli.test.d.ts.map +0 -1
  266. package/dist/tests/cli.test.js +0 -83
  267. package/dist/tests/cli.test.js.map +0 -1
  268. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
  269. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  270. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
  271. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
  272. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  273. package/dist/tests/commands/auth.test.d.ts +0 -2
  274. package/dist/tests/commands/auth.test.d.ts.map +0 -1
  275. package/dist/tests/commands/auth.test.js +0 -304
  276. package/dist/tests/commands/auth.test.js.map +0 -1
  277. package/dist/tests/commands/channel.test.d.ts +0 -2
  278. package/dist/tests/commands/channel.test.d.ts.map +0 -1
  279. package/dist/tests/commands/channel.test.js +0 -166
  280. package/dist/tests/commands/channel.test.js.map +0 -1
  281. package/dist/tests/commands/file.test.d.ts +0 -2
  282. package/dist/tests/commands/file.test.d.ts.map +0 -1
  283. package/dist/tests/commands/file.test.js +0 -175
  284. package/dist/tests/commands/file.test.js.map +0 -1
  285. package/dist/tests/commands/message.test.d.ts +0 -2
  286. package/dist/tests/commands/message.test.d.ts.map +0 -1
  287. package/dist/tests/commands/message.test.js +0 -293
  288. package/dist/tests/commands/message.test.js.map +0 -1
  289. package/dist/tests/commands/reaction.test.d.ts +0 -2
  290. package/dist/tests/commands/reaction.test.d.ts.map +0 -1
  291. package/dist/tests/commands/reaction.test.js +0 -84
  292. package/dist/tests/commands/reaction.test.js.map +0 -1
  293. package/dist/tests/commands/snapshot.test.d.ts +0 -2
  294. package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
  295. package/dist/tests/commands/snapshot.test.js +0 -280
  296. package/dist/tests/commands/snapshot.test.js.map +0 -1
  297. package/dist/tests/commands/user.test.d.ts +0 -2
  298. package/dist/tests/commands/user.test.d.ts.map +0 -1
  299. package/dist/tests/commands/user.test.js +0 -117
  300. package/dist/tests/commands/user.test.js.map +0 -1
  301. package/dist/tests/commands/workspace.test.d.ts +0 -2
  302. package/dist/tests/commands/workspace.test.d.ts.map +0 -1
  303. package/dist/tests/commands/workspace.test.js +0 -453
  304. package/dist/tests/commands/workspace.test.js.map +0 -1
  305. package/dist/tests/credential-manager.test.d.ts +0 -2
  306. package/dist/tests/credential-manager.test.d.ts.map +0 -1
  307. package/dist/tests/credential-manager.test.js +0 -199
  308. package/dist/tests/credential-manager.test.js.map +0 -1
  309. package/dist/tests/slack-client.test.d.ts +0 -2
  310. package/dist/tests/slack-client.test.d.ts.map +0 -1
  311. package/dist/tests/slack-client.test.js +0 -741
  312. package/dist/tests/slack-client.test.js.map +0 -1
  313. package/dist/tests/types.test.d.ts +0 -2
  314. package/dist/tests/types.test.d.ts.map +0 -1
  315. package/dist/tests/types.test.js +0 -215
  316. package/dist/tests/types.test.js.map +0 -1
  317. package/dist/types/index.d.ts +0 -369
  318. package/dist/types/index.d.ts.map +0 -1
  319. package/dist/types/index.js +0 -92
  320. package/dist/types/index.js.map +0 -1
  321. package/dist/utils/error-handler.d.ts +0 -2
  322. package/dist/utils/error-handler.d.ts.map +0 -1
  323. package/dist/utils/error-handler.js +0 -5
  324. package/dist/utils/error-handler.js.map +0 -1
  325. package/dist/utils/output.d.ts +0 -2
  326. package/dist/utils/output.d.ts.map +0 -1
  327. package/dist/utils/output.js +0 -4
  328. package/dist/utils/output.js.map +0 -1
  329. /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
  330. /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
@@ -0,0 +1,239 @@
1
+ #!/bin/bash
2
+ #
3
+ # monitor-channel.sh - Monitor a Microsoft Teams channel for new messages
4
+ #
5
+ # Usage:
6
+ # ./monitor-channel.sh <channel-id> [interval]
7
+ #
8
+ # Arguments:
9
+ # channel-id - Channel ID to monitor (use 'channel list' to find IDs)
10
+ # interval - Polling interval in seconds (default: 10)
11
+ #
12
+ # Example:
13
+ # ./monitor-channel.sh "19:abc123@thread.tacv2"
14
+ # ./monitor-channel.sh "19:abc123@thread.tacv2" 5
15
+ #
16
+ # NOTE: Teams tokens expire in 60-90 minutes! This script handles automatic refresh.
17
+
18
+ set -euo pipefail
19
+
20
+ # Check arguments
21
+ if [ $# -lt 1 ]; then
22
+ echo "Usage: $0 <channel-id> [interval]"
23
+ echo ""
24
+ echo "Examples:"
25
+ echo " $0 '19:abc123@thread.tacv2' # Monitor channel, poll every 10s"
26
+ echo " $0 '19:abc123@thread.tacv2' 5 # Monitor channel, poll every 5s"
27
+ echo ""
28
+ echo "To find channel IDs, run: agent-teams channel list"
29
+ echo ""
30
+ echo "NOTE: Teams tokens expire in 60-90 minutes - this script auto-refreshes!"
31
+ exit 1
32
+ fi
33
+
34
+ CHANNEL_ID="$1"
35
+ INTERVAL="${2:-10}" # Default 10 seconds
36
+
37
+ # Colors for output
38
+ RED='\033[0;31m'
39
+ GREEN='\033[0;32m'
40
+ YELLOW='\033[1;33m'
41
+ BLUE='\033[0;34m'
42
+ NC='\033[0m' # No Color
43
+
44
+ # State tracking
45
+ LAST_ID=""
46
+ FIRST_RUN=true
47
+ LAST_TOKEN_CHECK=$(date +%s)
48
+ TOKEN_CHECK_INTERVAL=300 # Check token every 5 minutes
49
+
50
+ # Function to format ISO timestamp to readable format
51
+ format_time() {
52
+ local ts=$1
53
+ # Handle ISO 8601 format
54
+ if command -v gdate &> /dev/null; then
55
+ gdate -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
56
+ else
57
+ date -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
58
+ fi
59
+ }
60
+
61
+ # Function to truncate text
62
+ truncate_text() {
63
+ local text=$1
64
+ local max_length=100
65
+
66
+ if [ ${#text} -gt $max_length ]; then
67
+ echo "${text:0:$max_length}..."
68
+ else
69
+ echo "$text"
70
+ fi
71
+ }
72
+
73
+ # Function to refresh token if needed (TEAMS-SPECIFIC)
74
+ refresh_token_if_needed() {
75
+ local now=$(date +%s)
76
+ local elapsed=$((now - LAST_TOKEN_CHECK))
77
+
78
+ # Only check periodically to avoid API spam
79
+ if [ $elapsed -lt $TOKEN_CHECK_INTERVAL ]; then
80
+ return 0
81
+ fi
82
+
83
+ LAST_TOKEN_CHECK=$now
84
+
85
+ echo -e "${YELLOW}Checking token validity...${NC}"
86
+
87
+ local status
88
+ status=$(agent-teams auth status 2>&1)
89
+
90
+ # Check if token is expired or expiring soon
91
+ if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
92
+ echo -e "${YELLOW}Token expired, refreshing...${NC}"
93
+ agent-teams auth extract
94
+ return 0
95
+ fi
96
+
97
+ local expires_soon
98
+ expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
99
+ local token_age
100
+ token_age=$(echo "$status" | jq -r '.token_age_minutes // 0')
101
+
102
+ if [ "$expires_soon" = "true" ]; then
103
+ echo -e "${YELLOW}Token expiring soon (${token_age} min old), refreshing...${NC}"
104
+ agent-teams auth extract
105
+ else
106
+ echo -e "${GREEN}Token valid (${token_age} min old)${NC}"
107
+ fi
108
+ }
109
+
110
+ # Function to check for new messages
111
+ check_messages() {
112
+ # Get latest message
113
+ MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1 2>&1)
114
+
115
+ # Check for token expiry error
116
+ if echo "$MESSAGES" | grep -Eqi "expired|401|unauthorized" 2>/dev/null; then
117
+ echo -e "${YELLOW}Token expired during operation, refreshing...${NC}"
118
+ agent-teams auth extract
119
+ # Retry
120
+ MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1 2>&1)
121
+ fi
122
+
123
+ # Check if successful
124
+ if echo "$MESSAGES" | jq -e '.error' > /dev/null 2>&1; then
125
+ ERROR_MSG=$(echo "$MESSAGES" | jq -r '.error // "Unknown error"')
126
+ echo -e "${RED}Error: $ERROR_MSG${NC}"
127
+ return 1
128
+ fi
129
+
130
+ # Extract latest message
131
+ LATEST_ID=$(echo "$MESSAGES" | jq -r '.[0].id // ""')
132
+
133
+ # No messages in channel
134
+ if [ -z "$LATEST_ID" ]; then
135
+ if [ "$FIRST_RUN" = true ]; then
136
+ echo -e "${YELLOW}No messages in channel yet${NC}"
137
+ fi
138
+ return 0
139
+ fi
140
+
141
+ # Check if new message
142
+ if [ "$LATEST_ID" != "$LAST_ID" ]; then
143
+ # Skip notification on first run (just initialize)
144
+ if [ "$FIRST_RUN" = false ] && [ -n "$LAST_ID" ]; then
145
+ # Extract message details
146
+ CONTENT=$(echo "$MESSAGES" | jq -r '.[0].content // ""')
147
+ AUTHOR=$(echo "$MESSAGES" | jq -r '.[0].author // "Unknown"')
148
+ TIMESTAMP=$(echo "$MESSAGES" | jq -r '.[0].timestamp // ""')
149
+
150
+ # Format timestamp
151
+ TIME=$(format_time "$TIMESTAMP")
152
+
153
+ # Display new message
154
+ echo ""
155
+ echo -e "${GREEN}----------------------------------------------${NC}"
156
+ echo -e "${BLUE}New message in channel${NC}"
157
+ echo -e "${GREEN}----------------------------------------------${NC}"
158
+ echo -e "Time: $TIME"
159
+ echo -e "From: $AUTHOR"
160
+ echo -e "Message: $(truncate_text "$CONTENT")"
161
+ echo -e "${GREEN}----------------------------------------------${NC}"
162
+
163
+ # Example: Auto-respond to keywords
164
+ # Uncomment to enable
165
+ # if echo "$CONTENT" | grep -qi "bot"; then
166
+ # echo -e "${YELLOW}Detected keyword, responding...${NC}"
167
+ # agent-teams message send "$CHANNEL_ID" "You called?"
168
+ # fi
169
+ fi
170
+
171
+ LAST_ID="$LATEST_ID"
172
+ fi
173
+
174
+ FIRST_RUN=false
175
+ return 0
176
+ }
177
+
178
+ # Check if agent-teams is installed
179
+ if ! command -v agent-teams &> /dev/null; then
180
+ echo -e "${RED}Error: agent-teams not found${NC}"
181
+ echo ""
182
+ echo "Install it with:"
183
+ echo " bun install -g agent-teams"
184
+ exit 1
185
+ fi
186
+
187
+ # Check authentication and refresh if needed
188
+ echo "Checking authentication..."
189
+ refresh_token_if_needed
190
+
191
+ AUTH_STATUS=$(agent-teams auth status 2>&1)
192
+
193
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
194
+ echo -e "${RED}Not authenticated!${NC}"
195
+ echo ""
196
+ echo "Run this to authenticate:"
197
+ echo " agent-teams auth extract"
198
+ exit 1
199
+ fi
200
+
201
+ USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.user // "Unknown"')
202
+ TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
203
+ echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
204
+ echo -e "Token age: ${TOKEN_AGE} minutes"
205
+ echo ""
206
+
207
+ # Verify channel exists
208
+ echo "Verifying channel..."
209
+ CHANNEL_INFO=$(agent-teams channel info "$CHANNEL_ID" 2>&1)
210
+
211
+ if echo "$CHANNEL_INFO" | jq -e '.error' > /dev/null 2>&1; then
212
+ echo -e "${RED}Channel '$CHANNEL_ID' not found${NC}"
213
+ echo ""
214
+ echo "List available channels with:"
215
+ echo " agent-teams channel list"
216
+ exit 1
217
+ fi
218
+
219
+ CHANNEL_NAME=$(echo "$CHANNEL_INFO" | jq -r '.name // "Unknown"')
220
+ echo -e "${GREEN}Monitoring: #$CHANNEL_NAME ($CHANNEL_ID)${NC}"
221
+ echo ""
222
+
223
+ # Start monitoring
224
+ echo -e "${YELLOW}Monitoring for new messages (polling every ${INTERVAL}s)...${NC}"
225
+ echo -e "${YELLOW}Token will be auto-refreshed before expiry (60-90 min limit)${NC}"
226
+ echo -e "${YELLOW}Press Ctrl+C to stop${NC}"
227
+ echo ""
228
+
229
+ # Trap Ctrl+C for clean exit
230
+ trap 'echo -e "\n${YELLOW}Monitoring stopped${NC}"; exit 0' INT
231
+
232
+ # Main monitoring loop
233
+ while true; do
234
+ # Proactively refresh token before it expires
235
+ refresh_token_if_needed
236
+
237
+ check_messages
238
+ sleep "$INTERVAL"
239
+ done
@@ -0,0 +1,224 @@
1
+ #!/bin/bash
2
+ #
3
+ # post-message.sh - Send a message to Microsoft Teams with error handling
4
+ #
5
+ # Usage:
6
+ # ./post-message.sh <channel-id> <message>
7
+ # ./post-message.sh --channel-name <name> <message>
8
+ #
9
+ # Example:
10
+ # ./post-message.sh "19:abc123@thread.tacv2" "Hello from script!"
11
+ # ./post-message.sh --channel-name General "Deployment completed"
12
+ #
13
+ # NOTE: Teams tokens expire in 60-90 minutes! This script handles token refresh.
14
+
15
+ set -euo pipefail
16
+
17
+ # Colors for output
18
+ RED='\033[0;31m'
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ NC='\033[0m' # No Color
22
+
23
+ # Parse arguments
24
+ CHANNEL_ID=""
25
+ CHANNEL_NAME=""
26
+ MESSAGE=""
27
+
28
+ if [ "$1" = "--channel-name" ]; then
29
+ if [ $# -lt 3 ]; then
30
+ echo "Usage: $0 --channel-name <name> <message>"
31
+ echo ""
32
+ echo "Example:"
33
+ echo " $0 --channel-name General 'Build completed'"
34
+ echo ""
35
+ echo "NOTE: Teams tokens expire in 60-90 minutes!"
36
+ exit 1
37
+ fi
38
+ CHANNEL_NAME="$2"
39
+ MESSAGE="$3"
40
+ elif [ $# -lt 2 ]; then
41
+ echo "Usage: $0 <channel-id> <message>"
42
+ echo " $0 --channel-name <name> <message>"
43
+ echo ""
44
+ echo "Examples:"
45
+ echo " $0 '19:abc123@thread.tacv2' 'Hello world!'"
46
+ echo " $0 --channel-name General 'Build completed'"
47
+ echo ""
48
+ echo "NOTE: Teams tokens expire in 60-90 minutes!"
49
+ exit 1
50
+ else
51
+ CHANNEL_ID="$1"
52
+ MESSAGE="$2"
53
+ fi
54
+
55
+ # Function to refresh token if needed
56
+ refresh_token_if_needed() {
57
+ local status
58
+ status=$(agent-teams auth status 2>&1)
59
+
60
+ # Check if token is expired or expiring soon
61
+ if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
62
+ echo -e "${YELLOW}Token expired or invalid, refreshing...${NC}"
63
+ agent-teams auth extract
64
+ return 0
65
+ fi
66
+
67
+ local expires_soon
68
+ expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
69
+
70
+ if [ "$expires_soon" = "true" ]; then
71
+ echo -e "${YELLOW}Token expiring soon, refreshing...${NC}"
72
+ agent-teams auth extract
73
+ fi
74
+ }
75
+
76
+ # Function to send message with retry logic
77
+ send_message() {
78
+ local channel_id=$1
79
+ local message=$2
80
+ local max_attempts=3
81
+ local attempt=1
82
+ local token_refresh_attempts=0
83
+ local max_token_refresh=2
84
+
85
+ while [ $attempt -le $max_attempts ]; do
86
+ echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}"
87
+
88
+ # Send message and capture result
89
+ RESULT=$(agent-teams message send "$channel_id" "$message" 2>&1)
90
+
91
+ # Check if successful (has an 'id' field)
92
+ if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
93
+ echo -e "${GREEN}Message sent successfully!${NC}"
94
+
95
+ # Extract message details
96
+ MSG_ID=$(echo "$RESULT" | jq -r '.id')
97
+
98
+ echo ""
99
+ echo "Message details:"
100
+ echo " Channel: $channel_id"
101
+ echo " Message ID: $MSG_ID"
102
+
103
+ return 0
104
+ fi
105
+
106
+ # Extract error information
107
+ if echo "$RESULT" | jq -e '.error' > /dev/null 2>&1; then
108
+ ERROR_MSG=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
109
+ echo -e "${RED}Failed: $ERROR_MSG${NC}"
110
+
111
+ # Handle token expiry - refresh and retry (with a limit on refresh attempts)
112
+ if echo "$ERROR_MSG" | grep -Eqi "expired|401|unauthorized"; then
113
+ token_refresh_attempts=$((token_refresh_attempts + 1))
114
+ if [ $token_refresh_attempts -le $max_token_refresh ]; then
115
+ echo -e "${YELLOW}Token expired, refreshing (attempt $token_refresh_attempts/$max_token_refresh)...${NC}"
116
+ agent-teams auth extract
117
+ continue
118
+ else
119
+ echo -e "${RED}Token refresh failed after $max_token_refresh attempts${NC}"
120
+ return 1
121
+ fi
122
+ fi
123
+
124
+ # Don't retry on certain errors
125
+ if echo "$ERROR_MSG" | grep -q "Not authenticated"; then
126
+ echo ""
127
+ echo "Not authenticated. Run:"
128
+ echo " agent-teams auth extract"
129
+ return 1
130
+ fi
131
+
132
+ if echo "$ERROR_MSG" | grep -q "Channel not found"; then
133
+ echo ""
134
+ echo "Channel '$channel_id' not found. Check channel ID."
135
+ echo "List channels with: agent-teams channel list"
136
+ return 1
137
+ fi
138
+ else
139
+ echo -e "${RED}Unexpected error: $RESULT${NC}"
140
+ fi
141
+
142
+ # Exponential backoff before retry
143
+ if [ $attempt -lt $max_attempts ]; then
144
+ SLEEP_TIME=$((attempt * 2))
145
+ echo "Retrying in ${SLEEP_TIME}s..."
146
+ sleep $SLEEP_TIME
147
+ fi
148
+
149
+ attempt=$((attempt + 1))
150
+ done
151
+
152
+ echo -e "${RED}Failed after $max_attempts attempts${NC}"
153
+ return 1
154
+ }
155
+
156
+ # Check if agent-teams is installed
157
+ if ! command -v agent-teams &> /dev/null; then
158
+ echo -e "${RED}Error: agent-teams not found${NC}"
159
+ echo ""
160
+ echo "Install it with:"
161
+ echo " bun install -g agent-teams"
162
+ exit 1
163
+ fi
164
+
165
+ # Check and refresh authentication
166
+ echo "Checking authentication..."
167
+ refresh_token_if_needed
168
+
169
+ AUTH_STATUS=$(agent-teams auth status 2>&1)
170
+
171
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
172
+ echo -e "${RED}Not authenticated!${NC}"
173
+ echo ""
174
+ echo "Run this to authenticate:"
175
+ echo " agent-teams auth extract"
176
+ exit 1
177
+ fi
178
+
179
+ USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.user // "Unknown"')
180
+ TEAM_ID=$(echo "$AUTH_STATUS" | jq -r '.current_team // ""')
181
+ TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
182
+ echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
183
+ echo -e "Token age: ${TOKEN_AGE} minutes"
184
+
185
+ if [ -z "$TEAM_ID" ]; then
186
+ echo -e "${RED}No team selected!${NC}"
187
+ echo ""
188
+ echo "Run this to select a team:"
189
+ echo " agent-teams team list"
190
+ echo " agent-teams team switch <team-id>"
191
+ exit 1
192
+ fi
193
+
194
+ # If channel name provided, look up channel ID
195
+ if [ -n "$CHANNEL_NAME" ]; then
196
+ echo "Looking up channel #$CHANNEL_NAME..."
197
+ CHANNELS=$(agent-teams channel list 2>&1)
198
+
199
+ if echo "$CHANNELS" | jq -e '.error' > /dev/null 2>&1; then
200
+ echo -e "${RED}Failed to list channels${NC}"
201
+ exit 1
202
+ fi
203
+
204
+ CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg name "$CHANNEL_NAME" '.[] | select(.name==$name) | .id')
205
+
206
+ if [ -z "$CHANNEL_ID" ]; then
207
+ echo -e "${RED}Channel #$CHANNEL_NAME not found${NC}"
208
+ echo ""
209
+ echo "Available channels:"
210
+ echo "$CHANNELS" | jq -r '.[] | " #\(.name) (\(.id))"'
211
+ exit 1
212
+ fi
213
+
214
+ echo -e "${GREEN}Found channel: $CHANNEL_ID${NC}"
215
+ fi
216
+
217
+ echo ""
218
+
219
+ # Send the message
220
+ echo "Sending message to channel $CHANNEL_ID..."
221
+ echo "Message: $MESSAGE"
222
+ echo ""
223
+
224
+ send_message "$CHANNEL_ID" "$MESSAGE"
@@ -0,0 +1,210 @@
1
+ #!/bin/bash
2
+ #
3
+ # team-summary.sh - Generate a comprehensive Microsoft Teams team summary
4
+ #
5
+ # Usage:
6
+ # ./team-summary.sh [--json]
7
+ #
8
+ # Options:
9
+ # --json Output raw JSON instead of formatted text
10
+ #
11
+ # Example:
12
+ # ./team-summary.sh
13
+ # ./team-summary.sh --json > summary.json
14
+ #
15
+ # NOTE: Teams tokens expire in 60-90 minutes! This script handles token refresh.
16
+
17
+ set -euo pipefail
18
+
19
+ OUTPUT_JSON=false
20
+ if [ $# -gt 0 ] && [ "$1" = "--json" ]; then
21
+ OUTPUT_JSON=true
22
+ fi
23
+
24
+ RED='\033[0;31m'
25
+ GREEN='\033[0;32m'
26
+ YELLOW='\033[1;33m'
27
+ BLUE='\033[0;34m'
28
+ CYAN='\033[0;36m'
29
+ BOLD='\033[1m'
30
+ NC='\033[0m'
31
+
32
+ # Function to refresh token if needed
33
+ refresh_token_if_needed() {
34
+ local status
35
+ status=$(agent-teams auth status 2>&1)
36
+
37
+ if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
38
+ echo -e "${YELLOW}Token expired, refreshing...${NC}" >&2
39
+ agent-teams auth extract >&2
40
+ return 0
41
+ fi
42
+
43
+ local expires_soon
44
+ expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
45
+
46
+ if [ "$expires_soon" = "true" ]; then
47
+ echo -e "${YELLOW}Token expiring soon, refreshing...${NC}" >&2
48
+ agent-teams auth extract >&2
49
+ fi
50
+ }
51
+
52
+ if ! command -v agent-teams &> /dev/null; then
53
+ echo -e "${RED}Error: agent-teams not found${NC}" >&2
54
+ echo "" >&2
55
+ echo "Install it with:" >&2
56
+ echo " bun install -g agent-teams" >&2
57
+ exit 1
58
+ fi
59
+
60
+ # Check and refresh token
61
+ refresh_token_if_needed
62
+
63
+ AUTH_STATUS=$(agent-teams auth status 2>&1)
64
+
65
+ if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
66
+ echo -e "${RED}Not authenticated!${NC}" >&2
67
+ echo "" >&2
68
+ echo "Run this to authenticate:" >&2
69
+ echo " agent-teams auth extract" >&2
70
+ exit 1
71
+ fi
72
+
73
+ CURRENT_TEAM=$(echo "$AUTH_STATUS" | jq -r '.current_team // ""')
74
+ TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
75
+
76
+ if [ -z "$CURRENT_TEAM" ]; then
77
+ echo -e "${RED}No team selected!${NC}" >&2
78
+ echo "" >&2
79
+ echo "Run this to select a team:" >&2
80
+ echo " agent-teams team list" >&2
81
+ echo " agent-teams team switch <team-id>" >&2
82
+ exit 1
83
+ fi
84
+
85
+ echo -e "${YELLOW}Fetching team snapshot...${NC}" >&2
86
+ echo -e "Token age: ${TOKEN_AGE} minutes" >&2
87
+ SNAPSHOT=$(agent-teams snapshot 2>&1)
88
+
89
+ # Handle token expiry during snapshot
90
+ if echo "$SNAPSHOT" | grep -Eqi "expired|401|unauthorized" 2>/dev/null; then
91
+ echo -e "${YELLOW}Token expired during snapshot, refreshing...${NC}" >&2
92
+ agent-teams auth extract >&2
93
+ SNAPSHOT=$(agent-teams snapshot 2>&1)
94
+ fi
95
+
96
+ if echo "$SNAPSHOT" | jq -e '.error' > /dev/null 2>&1; then
97
+ echo -e "${RED}Failed to get snapshot${NC}" >&2
98
+ ERROR_MSG=$(echo "$SNAPSHOT" | jq -r '.error // "Unknown error"')
99
+ echo -e "${RED}Error: $ERROR_MSG${NC}" >&2
100
+ exit 1
101
+ fi
102
+
103
+ if [ "$OUTPUT_JSON" = true ]; then
104
+ echo "$SNAPSHOT"
105
+ exit 0
106
+ fi
107
+
108
+ TEAM_NAME=$(echo "$SNAPSHOT" | jq -r '.team.name // "Unknown"')
109
+ TEAM_ID=$(echo "$SNAPSHOT" | jq -r '.team.id // "Unknown"')
110
+
111
+ CHANNELS=$(echo "$SNAPSHOT" | jq '.channels // []')
112
+ CHANNEL_COUNT=$(echo "$CHANNELS" | jq 'length')
113
+ STANDARD_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "standard")] | length')
114
+ PRIVATE_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "private")] | length')
115
+
116
+ MEMBERS=$(echo "$SNAPSHOT" | jq '.members // []')
117
+ MEMBER_COUNT=$(echo "$MEMBERS" | jq 'length')
118
+
119
+ MESSAGES=$(echo "$SNAPSHOT" | jq '.recent_messages // []')
120
+ MESSAGE_COUNT=$(echo "$MESSAGES" | jq 'length')
121
+
122
+ echo ""
123
+ echo -e "${BOLD}${BLUE}=====================================================${NC}"
124
+ echo -e "${BOLD}${BLUE} Microsoft Teams Summary${NC}"
125
+ echo -e "${BOLD}${BLUE}=====================================================${NC}"
126
+ echo ""
127
+ echo -e "${BOLD}Team:${NC} $TEAM_NAME"
128
+ echo -e "${BOLD}ID:${NC} $TEAM_ID"
129
+ echo -e "${BOLD}Token Age:${NC} ${TOKEN_AGE} minutes (expires at ~60-90 min)"
130
+ echo ""
131
+
132
+ echo -e "${BOLD}${CYAN}Channels (${CHANNEL_COUNT} total)${NC}"
133
+ echo -e " Standard: $STANDARD_COUNT"
134
+ echo -e " Private: $PRIVATE_COUNT"
135
+ echo ""
136
+
137
+ echo -e "${BOLD}${CYAN}Channels:${NC}"
138
+ echo "$CHANNELS" | jq -r '
139
+ .[0:10] |
140
+ .[] |
141
+ " #\(.name) (\(.id[0:30])...)"
142
+ '
143
+ if [ "$CHANNEL_COUNT" -gt 10 ]; then
144
+ echo " ... and $((CHANNEL_COUNT - 10)) more"
145
+ fi
146
+ echo ""
147
+
148
+ echo -e "${BOLD}${CYAN}Members (${MEMBER_COUNT} shown)${NC}"
149
+ echo ""
150
+
151
+ echo -e "${BOLD}${CYAN}Sample Members:${NC}"
152
+ echo "$MEMBERS" | jq -r '
153
+ .[0:10] |
154
+ .[] |
155
+ " \(.displayName) \(if .email then "(\(.email))" else "" end)"
156
+ '
157
+ if [ "$MEMBER_COUNT" -gt 10 ]; then
158
+ echo " ... and $((MEMBER_COUNT - 10)) more"
159
+ fi
160
+ echo ""
161
+
162
+ echo -e "${BOLD}${CYAN}Recent Activity (${MESSAGE_COUNT} messages)${NC}"
163
+ echo ""
164
+
165
+ if [ "$MESSAGE_COUNT" -gt 0 ]; then
166
+ echo -e "${BOLD}${CYAN}Latest Messages:${NC}"
167
+ echo "$MESSAGES" | jq -r '
168
+ .[0:5] |
169
+ .[] |
170
+ " [#\(.channel_name)] \(.author): \(.content[0:50])\(if (.content | length) > 50 then "..." else "" end)"
171
+ '
172
+ echo ""
173
+ fi
174
+
175
+ echo -e "${BOLD}${CYAN}Quick Actions:${NC}"
176
+ echo ""
177
+ echo -e " ${GREEN}# Send message to a channel${NC}"
178
+ FIRST_CHANNEL=$(echo "$CHANNELS" | jq -r '.[0].id // "CHANNEL_ID"')
179
+ FIRST_CHANNEL_NAME=$(echo "$CHANNELS" | jq -r '.[0].name // "General"')
180
+ echo -e " agent-teams message send \"$FIRST_CHANNEL\" \"Hello!\""
181
+ echo ""
182
+ echo -e " ${GREEN}# List messages in #$FIRST_CHANNEL_NAME${NC}"
183
+ echo -e " agent-teams message list \"$FIRST_CHANNEL\" --limit 10"
184
+ echo ""
185
+ echo -e " ${GREEN}# Get user info${NC}"
186
+ FIRST_USER=$(echo "$MEMBERS" | jq -r '.[0].id // "USER_ID"')
187
+ echo -e " agent-teams user info \"$FIRST_USER\""
188
+ echo ""
189
+ echo -e " ${GREEN}# Switch to another team${NC}"
190
+ echo -e " agent-teams team list"
191
+ echo -e " agent-teams team switch <team-id>"
192
+ echo ""
193
+ echo -e " ${GREEN}# Refresh token (expires in 60-90 min!)${NC}"
194
+ echo -e " agent-teams auth extract"
195
+ echo ""
196
+
197
+ echo -e "${BOLD}${BLUE}=====================================================${NC}"
198
+ echo ""
199
+
200
+ SNAPSHOT_FILE="team-snapshot-$(date +%Y%m%d-%H%M%S).json"
201
+ echo "$SNAPSHOT" > "$SNAPSHOT_FILE"
202
+ echo -e "${GREEN}Full snapshot saved to: $SNAPSHOT_FILE${NC}"
203
+ echo ""
204
+
205
+ # Warn if token is getting old
206
+ if [ "$TOKEN_AGE" != "unknown" ] && [ "${TOKEN_AGE%.*}" -gt 45 ] 2>/dev/null; then
207
+ echo -e "${YELLOW}WARNING: Token is ${TOKEN_AGE} minutes old. Consider refreshing soon!${NC}"
208
+ echo -e "${YELLOW}Run: agent-teams auth extract${NC}"
209
+ echo ""
210
+ fi
package/src/cli.ts CHANGED
@@ -24,6 +24,10 @@ program.command('discord', 'Interact with Discord guilds', {
24
24
  executableFile: join(__dirname, 'platforms', 'discord', 'cli.ts'),
25
25
  })
26
26
 
27
+ program.command('teams', 'Interact with Microsoft Teams', {
28
+ executableFile: join(__dirname, 'platforms', 'teams', 'cli.ts'),
29
+ })
30
+
27
31
  program.parse(process.argv)
28
32
 
29
33
  export default program
@@ -1,3 +1,4 @@
1
+ import { readFile } from 'node:fs/promises'
1
2
  import type {
2
3
  DiscordChannel,
3
4
  DiscordFile,
@@ -243,12 +244,11 @@ export class DiscordClient {
243
244
  }
244
245
 
245
246
  async uploadFile(channelId: string, filePath: string): Promise<DiscordFile> {
246
- const file = Bun.file(filePath)
247
+ const fileBuffer = await readFile(filePath)
247
248
  const filename = filePath.split('/').pop() || 'file'
248
- const blob = await file.arrayBuffer()
249
249
 
250
250
  const formData = new FormData()
251
- formData.append('files[0]', new Blob([blob]), filename)
251
+ formData.append('files[0]', new Blob([fileBuffer]), filename)
252
252
 
253
253
  interface MessageWithAttachments extends DiscordMessage {
254
254
  attachments: DiscordFile[]