agent-messenger 2.0.0 → 2.2.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 (272) hide show
  1. package/.claude-plugin/marketplace.json +14 -1
  2. package/.claude-plugin/plugin.json +4 -2
  3. package/.env.template +35 -17
  4. package/README.md +37 -33
  5. package/bun.lock +6 -6
  6. package/dist/package.json +11 -3
  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/channeltalk/commands/auth.d.ts.map +1 -1
  11. package/dist/src/platforms/channeltalk/commands/auth.js +35 -28
  12. package/dist/src/platforms/channeltalk/commands/auth.js.map +1 -1
  13. package/dist/src/platforms/channeltalk/ensure-auth.js +6 -6
  14. package/dist/src/platforms/channeltalk/ensure-auth.js.map +1 -1
  15. package/dist/src/platforms/channeltalk/token-extractor.d.ts +23 -1
  16. package/dist/src/platforms/channeltalk/token-extractor.d.ts.map +1 -1
  17. package/dist/src/platforms/channeltalk/token-extractor.js +299 -29
  18. package/dist/src/platforms/channeltalk/token-extractor.js.map +1 -1
  19. package/dist/src/platforms/discord/commands/auth.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/commands/auth.js +57 -49
  21. package/dist/src/platforms/discord/commands/auth.js.map +1 -1
  22. package/dist/src/platforms/discord/ensure-auth.js +3 -3
  23. package/dist/src/platforms/discord/ensure-auth.js.map +1 -1
  24. package/dist/src/platforms/discord/token-extractor.d.ts +6 -1
  25. package/dist/src/platforms/discord/token-extractor.d.ts.map +1 -1
  26. package/dist/src/platforms/discord/token-extractor.js +167 -14
  27. package/dist/src/platforms/discord/token-extractor.js.map +1 -1
  28. package/dist/src/platforms/instagram/client.d.ts +2 -0
  29. package/dist/src/platforms/instagram/client.d.ts.map +1 -1
  30. package/dist/src/platforms/instagram/client.js +2 -2
  31. package/dist/src/platforms/instagram/client.js.map +1 -1
  32. package/dist/src/platforms/instagram/commands/auth.d.ts.map +1 -1
  33. package/dist/src/platforms/instagram/commands/auth.js +107 -14
  34. package/dist/src/platforms/instagram/commands/auth.js.map +1 -1
  35. package/dist/src/platforms/instagram/ensure-auth.d.ts.map +1 -1
  36. package/dist/src/platforms/instagram/ensure-auth.js +57 -11
  37. package/dist/src/platforms/instagram/ensure-auth.js.map +1 -1
  38. package/dist/src/platforms/instagram/index.d.ts +1 -0
  39. package/dist/src/platforms/instagram/index.d.ts.map +1 -1
  40. package/dist/src/platforms/instagram/index.js +1 -0
  41. package/dist/src/platforms/instagram/index.js.map +1 -1
  42. package/dist/src/platforms/instagram/token-extractor.d.ts +44 -0
  43. package/dist/src/platforms/instagram/token-extractor.d.ts.map +1 -0
  44. package/dist/src/platforms/instagram/token-extractor.js +407 -0
  45. package/dist/src/platforms/instagram/token-extractor.js.map +1 -0
  46. package/dist/src/platforms/kakaotalk/client.d.ts.map +1 -1
  47. package/dist/src/platforms/kakaotalk/client.js +2 -1
  48. package/dist/src/platforms/kakaotalk/client.js.map +1 -1
  49. package/dist/src/platforms/kakaotalk/commands/auth.d.ts.map +1 -1
  50. package/dist/src/platforms/kakaotalk/commands/auth.js +14 -13
  51. package/dist/src/platforms/kakaotalk/commands/auth.js.map +1 -1
  52. package/dist/src/platforms/kakaotalk/protocol/connection.d.ts.map +1 -1
  53. package/dist/src/platforms/kakaotalk/protocol/connection.js +2 -1
  54. package/dist/src/platforms/kakaotalk/protocol/connection.js.map +1 -1
  55. package/dist/src/platforms/line/commands/auth.d.ts.map +1 -1
  56. package/dist/src/platforms/line/commands/auth.js +6 -5
  57. package/dist/src/platforms/line/commands/auth.js.map +1 -1
  58. package/dist/src/platforms/slack/commands/auth.d.ts.map +1 -1
  59. package/dist/src/platforms/slack/commands/auth.js +11 -10
  60. package/dist/src/platforms/slack/commands/auth.js.map +1 -1
  61. package/dist/src/platforms/slack/token-extractor.d.ts +9 -0
  62. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  63. package/dist/src/platforms/slack/token-extractor.js +300 -23
  64. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  65. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
  66. package/dist/src/platforms/teams/commands/auth.js +9 -8
  67. package/dist/src/platforms/teams/commands/auth.js.map +1 -1
  68. package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
  69. package/dist/src/platforms/teams/ensure-auth.js +2 -1
  70. package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
  71. package/dist/src/platforms/teams/token-extractor.d.ts +5 -0
  72. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
  73. package/dist/src/platforms/teams/token-extractor.js +161 -29
  74. package/dist/src/platforms/teams/token-extractor.js.map +1 -1
  75. package/dist/src/platforms/telegram/client.d.ts.map +1 -1
  76. package/dist/src/platforms/telegram/client.js +25 -7
  77. package/dist/src/platforms/telegram/client.js.map +1 -1
  78. package/dist/src/platforms/telegram/commands/auth.d.ts.map +1 -1
  79. package/dist/src/platforms/telegram/commands/auth.js +6 -5
  80. package/dist/src/platforms/telegram/commands/auth.js.map +1 -1
  81. package/dist/src/platforms/webex/app-config.d.ts +7 -0
  82. package/dist/src/platforms/webex/app-config.d.ts.map +1 -0
  83. package/dist/src/platforms/webex/app-config.js +20 -0
  84. package/dist/src/platforms/webex/app-config.js.map +1 -0
  85. package/dist/src/platforms/webex/cli.d.ts +5 -0
  86. package/dist/src/platforms/webex/cli.d.ts.map +1 -0
  87. package/dist/src/platforms/webex/cli.js +32 -0
  88. package/dist/src/platforms/webex/cli.js.map +1 -0
  89. package/dist/src/platforms/webex/client.d.ts +55 -0
  90. package/dist/src/platforms/webex/client.d.ts.map +1 -0
  91. package/dist/src/platforms/webex/client.js +299 -0
  92. package/dist/src/platforms/webex/client.js.map +1 -0
  93. package/dist/src/platforms/webex/commands/auth.d.ts +19 -0
  94. package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -0
  95. package/dist/src/platforms/webex/commands/auth.js +166 -0
  96. package/dist/src/platforms/webex/commands/auth.js.map +1 -0
  97. package/dist/src/platforms/webex/commands/index.d.ts +6 -0
  98. package/dist/src/platforms/webex/commands/index.d.ts.map +1 -0
  99. package/dist/src/platforms/webex/commands/index.js +6 -0
  100. package/dist/src/platforms/webex/commands/index.js.map +1 -0
  101. package/dist/src/platforms/webex/commands/member.d.ts +7 -0
  102. package/dist/src/platforms/webex/commands/member.d.ts.map +1 -0
  103. package/dist/src/platforms/webex/commands/member.js +34 -0
  104. package/dist/src/platforms/webex/commands/member.js.map +1 -0
  105. package/dist/src/platforms/webex/commands/message.d.ts +26 -0
  106. package/dist/src/platforms/webex/commands/message.d.ts.map +1 -0
  107. package/dist/src/platforms/webex/commands/message.js +153 -0
  108. package/dist/src/platforms/webex/commands/message.js.map +1 -0
  109. package/dist/src/platforms/webex/commands/snapshot.d.ts +9 -0
  110. package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -0
  111. package/dist/src/platforms/webex/commands/snapshot.js +72 -0
  112. package/dist/src/platforms/webex/commands/snapshot.js.map +1 -0
  113. package/dist/src/platforms/webex/commands/space.d.ts +11 -0
  114. package/dist/src/platforms/webex/commands/space.d.ts.map +1 -0
  115. package/dist/src/platforms/webex/commands/space.js +59 -0
  116. package/dist/src/platforms/webex/commands/space.js.map +1 -0
  117. package/dist/src/platforms/webex/credential-manager.d.ts +23 -0
  118. package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -0
  119. package/dist/src/platforms/webex/credential-manager.js +148 -0
  120. package/dist/src/platforms/webex/credential-manager.js.map +1 -0
  121. package/dist/src/platforms/webex/ensure-auth.d.ts +2 -0
  122. package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -0
  123. package/dist/src/platforms/webex/ensure-auth.js +36 -0
  124. package/dist/src/platforms/webex/ensure-auth.js.map +1 -0
  125. package/dist/src/platforms/webex/index.d.ts +8 -0
  126. package/dist/src/platforms/webex/index.d.ts.map +1 -0
  127. package/dist/src/platforms/webex/index.js +6 -0
  128. package/dist/src/platforms/webex/index.js.map +1 -0
  129. package/dist/src/platforms/webex/token-extractor.d.ts +28 -0
  130. package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -0
  131. package/dist/src/platforms/webex/token-extractor.js +344 -0
  132. package/dist/src/platforms/webex/token-extractor.js.map +1 -0
  133. package/dist/src/platforms/webex/types.d.ts +127 -0
  134. package/dist/src/platforms/webex/types.d.ts.map +1 -0
  135. package/dist/src/platforms/webex/types.js +64 -0
  136. package/dist/src/platforms/webex/types.js.map +1 -0
  137. package/dist/src/platforms/whatsapp/client.d.ts.map +1 -1
  138. package/dist/src/platforms/whatsapp/client.js +6 -2
  139. package/dist/src/platforms/whatsapp/client.js.map +1 -1
  140. package/dist/src/shared/utils/derived-key-cache.d.ts +1 -1
  141. package/dist/src/shared/utils/derived-key-cache.d.ts.map +1 -1
  142. package/dist/src/shared/utils/error-handler.d.ts +1 -1
  143. package/dist/src/shared/utils/error-handler.d.ts.map +1 -1
  144. package/dist/src/shared/utils/error-handler.js +3 -2
  145. package/dist/src/shared/utils/error-handler.js.map +1 -1
  146. package/dist/src/shared/utils/stderr.d.ts +5 -0
  147. package/dist/src/shared/utils/stderr.d.ts.map +1 -0
  148. package/dist/src/shared/utils/stderr.js +18 -0
  149. package/dist/src/shared/utils/stderr.js.map +1 -0
  150. package/dist/src/tui/adapters/webex-adapter.d.ts +14 -0
  151. package/dist/src/tui/adapters/webex-adapter.d.ts.map +1 -0
  152. package/dist/src/tui/adapters/webex-adapter.js +79 -0
  153. package/dist/src/tui/adapters/webex-adapter.js.map +1 -0
  154. package/dist/src/tui/app.d.ts.map +1 -1
  155. package/dist/src/tui/app.js +2 -0
  156. package/dist/src/tui/app.js.map +1 -1
  157. package/docs/content/docs/cli/channeltalk.mdx +7 -7
  158. package/docs/content/docs/cli/discord.mdx +3 -3
  159. package/docs/content/docs/cli/instagram.mdx +28 -6
  160. package/docs/content/docs/cli/meta.json +1 -0
  161. package/docs/content/docs/cli/slack.mdx +2 -2
  162. package/docs/content/docs/cli/teams.mdx +6 -4
  163. package/docs/content/docs/cli/webex.mdx +310 -0
  164. package/docs/content/docs/sdk/meta.json +1 -1
  165. package/docs/content/docs/sdk/webex.mdx +260 -0
  166. package/docs/content/docs/tui.mdx +4 -3
  167. package/docs/src/app/page.tsx +2 -2
  168. package/e2e/README.md +132 -8
  169. package/e2e/channeltalk.e2e.test.ts +2 -7
  170. package/e2e/channeltalkbot.e2e.test.ts +2 -6
  171. package/e2e/config.ts +172 -10
  172. package/e2e/helpers.ts +7 -0
  173. package/e2e/instagram.e2e.test.ts +97 -0
  174. package/e2e/kakaotalk.e2e.test.ts +74 -0
  175. package/e2e/line.e2e.test.ts +92 -0
  176. package/e2e/teams.e2e.test.ts +46 -1
  177. package/e2e/telegram.e2e.test.ts +84 -0
  178. package/e2e/webex.e2e.test.ts +190 -0
  179. package/e2e/whatsapp.e2e.test.ts +90 -0
  180. package/e2e/whatsappbot.e2e.test.ts +78 -0
  181. package/package.json +11 -3
  182. package/skills/agent-channeltalk/SKILL.md +9 -9
  183. package/skills/agent-channeltalk/references/authentication.md +21 -18
  184. package/skills/agent-channeltalkbot/SKILL.md +1 -1
  185. package/skills/agent-discord/SKILL.md +5 -5
  186. package/skills/agent-discord/references/authentication.md +8 -8
  187. package/skills/agent-discordbot/SKILL.md +1 -1
  188. package/skills/agent-instagram/SKILL.md +51 -9
  189. package/skills/agent-instagram/references/authentication.md +35 -3
  190. package/skills/agent-kakaotalk/SKILL.md +1 -1
  191. package/skills/agent-line/SKILL.md +1 -1
  192. package/skills/agent-slack/SKILL.md +5 -5
  193. package/skills/agent-slack/references/authentication.md +8 -8
  194. package/skills/agent-slackbot/SKILL.md +1 -1
  195. package/skills/agent-teams/SKILL.md +6 -6
  196. package/skills/agent-teams/references/authentication.md +8 -8
  197. package/skills/agent-telegram/SKILL.md +1 -1
  198. package/skills/agent-webex/SKILL.md +406 -0
  199. package/skills/agent-webex/references/authentication.md +371 -0
  200. package/skills/agent-webex/references/common-patterns.md +726 -0
  201. package/skills/agent-webex/templates/monitor-space.sh +165 -0
  202. package/skills/agent-webex/templates/post-message.sh +170 -0
  203. package/skills/agent-whatsapp/SKILL.md +1 -1
  204. package/skills/agent-whatsappbot/SKILL.md +1 -1
  205. package/src/cli.ts +4 -0
  206. package/src/platforms/channeltalk/commands/auth.test.ts +5 -5
  207. package/src/platforms/channeltalk/commands/auth.ts +38 -32
  208. package/src/platforms/channeltalk/ensure-auth.test.ts +6 -6
  209. package/src/platforms/channeltalk/ensure-auth.ts +6 -6
  210. package/src/platforms/channeltalk/token-extractor.test.ts +182 -15
  211. package/src/platforms/channeltalk/token-extractor.ts +344 -30
  212. package/src/platforms/discord/commands/auth.test.ts +3 -3
  213. package/src/platforms/discord/commands/auth.ts +58 -54
  214. package/src/platforms/discord/ensure-auth.test.ts +3 -3
  215. package/src/platforms/discord/ensure-auth.ts +3 -3
  216. package/src/platforms/discord/token-extractor.test.ts +199 -27
  217. package/src/platforms/discord/token-extractor.ts +190 -17
  218. package/src/platforms/instagram/client.ts +2 -2
  219. package/src/platforms/instagram/commands/auth.ts +133 -14
  220. package/src/platforms/instagram/ensure-auth.ts +63 -12
  221. package/src/platforms/instagram/index.ts +1 -0
  222. package/src/platforms/instagram/token-extractor.test.ts +424 -0
  223. package/src/platforms/instagram/token-extractor.ts +478 -0
  224. package/src/platforms/kakaotalk/client.ts +3 -1
  225. package/src/platforms/kakaotalk/commands/auth.ts +14 -13
  226. package/src/platforms/kakaotalk/protocol/connection.ts +3 -1
  227. package/src/platforms/line/commands/auth.ts +7 -6
  228. package/src/platforms/slack/cli.test.ts +6 -5
  229. package/src/platforms/slack/commands/auth.test.ts +11 -7
  230. package/src/platforms/slack/commands/auth.ts +11 -10
  231. package/src/platforms/slack/token-extractor.test.ts +98 -1
  232. package/src/platforms/slack/token-extractor.ts +338 -26
  233. package/src/platforms/teams/commands/auth.ts +9 -8
  234. package/src/platforms/teams/ensure-auth.ts +3 -1
  235. package/src/platforms/teams/token-extractor.test.ts +136 -17
  236. package/src/platforms/teams/token-extractor.ts +182 -31
  237. package/src/platforms/telegram/client.test.ts +134 -0
  238. package/src/platforms/telegram/client.ts +27 -6
  239. package/src/platforms/telegram/commands/auth.ts +6 -5
  240. package/src/platforms/webex/app-config.test.ts +98 -0
  241. package/src/platforms/webex/app-config.ts +31 -0
  242. package/src/platforms/webex/cli.test.ts +58 -0
  243. package/src/platforms/webex/cli.ts +39 -0
  244. package/src/platforms/webex/client.test.ts +743 -0
  245. package/src/platforms/webex/client.ts +405 -0
  246. package/src/platforms/webex/commands/auth.test.ts +222 -0
  247. package/src/platforms/webex/commands/auth.ts +243 -0
  248. package/src/platforms/webex/commands/index.ts +5 -0
  249. package/src/platforms/webex/commands/member.test.ts +112 -0
  250. package/src/platforms/webex/commands/member.ts +45 -0
  251. package/src/platforms/webex/commands/message.test.ts +235 -0
  252. package/src/platforms/webex/commands/message.ts +204 -0
  253. package/src/platforms/webex/commands/snapshot.test.ts +105 -0
  254. package/src/platforms/webex/commands/snapshot.ts +91 -0
  255. package/src/platforms/webex/commands/space.test.ts +216 -0
  256. package/src/platforms/webex/commands/space.ts +74 -0
  257. package/src/platforms/webex/credential-manager.test.ts +314 -0
  258. package/src/platforms/webex/credential-manager.ts +197 -0
  259. package/src/platforms/webex/ensure-auth.test.ts +89 -0
  260. package/src/platforms/webex/ensure-auth.ts +38 -0
  261. package/src/platforms/webex/index.test.ts +25 -0
  262. package/src/platforms/webex/index.ts +19 -0
  263. package/src/platforms/webex/token-extractor.test.ts +327 -0
  264. package/src/platforms/webex/token-extractor.ts +393 -0
  265. package/src/platforms/webex/types.test.ts +307 -0
  266. package/src/platforms/webex/types.ts +129 -0
  267. package/src/platforms/whatsapp/client.ts +11 -7
  268. package/src/shared/utils/derived-key-cache.ts +1 -1
  269. package/src/shared/utils/error-handler.ts +4 -2
  270. package/src/shared/utils/stderr.ts +22 -0
  271. package/src/tui/adapters/webex-adapter.ts +103 -0
  272. package/src/tui/app.ts +2 -0
@@ -0,0 +1,129 @@
1
+ import { z } from 'zod'
2
+
3
+ export interface WebexSpace {
4
+ id: string
5
+ title: string
6
+ type: 'group' | 'direct'
7
+ isLocked: boolean
8
+ teamId?: string
9
+ lastActivity: string
10
+ created: string
11
+ creatorId: string
12
+ }
13
+
14
+ export interface WebexMessage {
15
+ id: string
16
+ roomId: string
17
+ roomType: 'group' | 'direct'
18
+ text?: string
19
+ markdown?: string
20
+ html?: string
21
+ files?: string[]
22
+ personId: string
23
+ personEmail: string
24
+ created: string
25
+ parentId?: string
26
+ mentionedPeople?: string[]
27
+ }
28
+
29
+ export interface WebexPerson {
30
+ id: string
31
+ emails: string[]
32
+ displayName: string
33
+ nickName?: string
34
+ firstName?: string
35
+ lastName?: string
36
+ avatar?: string
37
+ orgId: string
38
+ type: 'person' | 'bot'
39
+ created: string
40
+ }
41
+
42
+ export interface WebexMembership {
43
+ id: string
44
+ roomId: string
45
+ personId: string
46
+ personEmail: string
47
+ personDisplayName: string
48
+ isModerator: boolean
49
+ created: string
50
+ }
51
+
52
+ export interface WebexConfig {
53
+ accessToken: string
54
+ refreshToken: string
55
+ expiresAt: number
56
+ clientId?: string
57
+ clientSecret?: string
58
+ tokenType?: 'oauth' | 'manual' | 'extracted'
59
+ deviceUrl?: string
60
+ }
61
+
62
+ export class WebexError extends Error {
63
+ code: string
64
+
65
+ constructor(message: string, code: string) {
66
+ super(message)
67
+ this.name = 'WebexError'
68
+ this.code = code
69
+ }
70
+ }
71
+
72
+ export const WebexSpaceSchema = z.object({
73
+ id: z.string(),
74
+ title: z.string(),
75
+ type: z.enum(['group', 'direct']),
76
+ isLocked: z.boolean(),
77
+ teamId: z.string().optional(),
78
+ lastActivity: z.string(),
79
+ created: z.string(),
80
+ creatorId: z.string(),
81
+ })
82
+
83
+ export const WebexMessageSchema = z.object({
84
+ id: z.string(),
85
+ roomId: z.string(),
86
+ roomType: z.enum(['group', 'direct']),
87
+ text: z.string().optional(),
88
+ markdown: z.string().optional(),
89
+ html: z.string().optional(),
90
+ files: z.array(z.string()).optional(),
91
+ personId: z.string(),
92
+ personEmail: z.string(),
93
+ created: z.string(),
94
+ parentId: z.string().optional(),
95
+ mentionedPeople: z.array(z.string()).optional(),
96
+ })
97
+
98
+ export const WebexPersonSchema = z.object({
99
+ id: z.string(),
100
+ emails: z.array(z.string()),
101
+ displayName: z.string(),
102
+ nickName: z.string().optional(),
103
+ firstName: z.string().optional(),
104
+ lastName: z.string().optional(),
105
+ avatar: z.string().optional(),
106
+ orgId: z.string(),
107
+ type: z.enum(['person', 'bot']),
108
+ created: z.string(),
109
+ })
110
+
111
+ export const WebexMembershipSchema = z.object({
112
+ id: z.string(),
113
+ roomId: z.string(),
114
+ personId: z.string(),
115
+ personEmail: z.string(),
116
+ personDisplayName: z.string(),
117
+ isModerator: z.boolean(),
118
+ created: z.string(),
119
+ })
120
+
121
+ export const WebexConfigSchema = z.object({
122
+ accessToken: z.string(),
123
+ refreshToken: z.string(),
124
+ expiresAt: z.number(),
125
+ clientId: z.string().optional(),
126
+ clientSecret: z.string().optional(),
127
+ tokenType: z.enum(['oauth', 'manual', 'extracted']).optional(),
128
+ deviceUrl: z.string().optional(),
129
+ })
@@ -25,10 +25,14 @@ import {
25
25
 
26
26
  const MAX_MESSAGES_PER_CHAT = 500
27
27
 
28
- function toTimestampMs(ts: number | { toNumber(): number } | null | undefined): number {
28
+ function toTimestampMs(ts: unknown): number {
29
29
  if (ts == null) return 0
30
- if (typeof ts === 'object') return ts.toNumber() * 1000
31
- return ts * 1000
30
+ if (typeof ts === 'number') return ts * 1000
31
+ if (typeof ts === 'object' && ts !== null && 'toNumber' in ts && typeof (ts as Record<string, unknown>).toNumber === 'function') {
32
+ return (ts as { toNumber(): number }).toNumber() * 1000
33
+ }
34
+ const n = Number(ts)
35
+ return Number.isNaN(n) ? 0 : n * 1000
32
36
  }
33
37
 
34
38
  function resolveJid(input: string): string {
@@ -443,8 +447,8 @@ export class WhatsAppClient {
443
447
  const sorted = chats.sort((a, b) => {
444
448
  const aTime = a.conversationTimestamp
445
449
  const bTime = b.conversationTimestamp
446
- const aMs = toTimestampMs(aTime as number | { toNumber(): number } | null | undefined)
447
- const bMs = toTimestampMs(bTime as number | { toNumber(): number } | null | undefined)
450
+ const aMs = toTimestampMs(aTime)
451
+ const bMs = toTimestampMs(bTime)
448
452
  return bMs - aMs
449
453
  })
450
454
 
@@ -474,8 +478,8 @@ export class WhatsAppClient {
474
478
 
475
479
  const msgs = this.messages.get(resolvedJid) ?? []
476
480
  const sorted = [...msgs].sort((a, b) => {
477
- const aMs = toTimestampMs(a.messageTimestamp as number | { toNumber(): number } | null | undefined)
478
- const bMs = toTimestampMs(b.messageTimestamp as number | { toNumber(): number } | null | undefined)
481
+ const aMs = toTimestampMs(a.messageTimestamp)
482
+ const bMs = toTimestampMs(b.messageTimestamp)
479
483
  return aMs - bMs
480
484
  })
481
485
 
@@ -3,7 +3,7 @@ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'
3
3
  import { homedir } from 'node:os'
4
4
  import { join } from 'node:path'
5
5
 
6
- export type Platform = 'slack' | 'discord' | 'teams'
6
+ export type Platform = 'slack' | 'discord' | 'teams' | 'webex'
7
7
 
8
8
  /**
9
9
  * Caches derived encryption keys to avoid repeated macOS Keychain prompts.
@@ -1,4 +1,6 @@
1
- export function handleError(error: Error): void {
2
- console.error(JSON.stringify({ error: error.message }))
1
+ import { error } from './stderr'
2
+
3
+ export function handleError(err: Error): void {
4
+ error(JSON.stringify({ error: err.message }))
3
5
  process.exit(1)
4
6
  }
@@ -0,0 +1,22 @@
1
+ const isTTY = process.stderr.isTTY ?? false
2
+
3
+ const RESET = isTTY ? '\x1b[0m' : ''
4
+ const RED = isTTY ? '\x1b[31m' : ''
5
+ const YELLOW = isTTY ? '\x1b[33m' : ''
6
+ const DIM = isTTY ? '\x1b[2m' : ''
7
+
8
+ export function info(message: string): void {
9
+ process.stderr.write(`${message}\n`)
10
+ }
11
+
12
+ export function warn(message: string): void {
13
+ process.stderr.write(`${YELLOW}${message}${RESET}\n`)
14
+ }
15
+
16
+ export function error(message: string): void {
17
+ process.stderr.write(`${RED}${message}${RESET}\n`)
18
+ }
19
+
20
+ export function debug(message: string): void {
21
+ process.stderr.write(`${DIM}${message}${RESET}\n`)
22
+ }
@@ -0,0 +1,103 @@
1
+ import { exec } from 'node:child_process'
2
+
3
+ import { WebexClient } from '@/platforms/webex/client'
4
+ import { WebexCredentialManager } from '@/platforms/webex/credential-manager'
5
+ import { getWebexAppCredentials } from '@/platforms/webex/app-config'
6
+
7
+ import type { AuthHint, AuthIO, PlatformAdapter, UnifiedChannel, UnifiedMessage } from './types'
8
+
9
+ export class WebexAdapter implements PlatformAdapter {
10
+ readonly name = 'Webex'
11
+
12
+ private client: WebexClient | null = null
13
+ private personEmail: string | null = null
14
+
15
+ async login(): Promise<void> {
16
+ const client = new WebexClient()
17
+ await client.login()
18
+ const me = await client.testAuth()
19
+ this.client = client
20
+ this.personEmail = me.emails[0] ?? null
21
+ }
22
+
23
+ async getChannels(): Promise<UnifiedChannel[]> {
24
+ this.ensureClient()
25
+ const spaces = await this.client!.listSpaces()
26
+ return spaces.map((space) => ({
27
+ id: space.id,
28
+ name: space.title,
29
+ }))
30
+ }
31
+
32
+ async getMessages(channelId: string, limit = 50): Promise<UnifiedMessage[]> {
33
+ this.ensureClient()
34
+ const messages = await this.client!.listMessages(channelId, { max: limit })
35
+ return messages
36
+ .map((msg) => ({
37
+ id: msg.id,
38
+ channelId: msg.roomId,
39
+ author: msg.personEmail,
40
+ content: msg.text ?? '',
41
+ timestamp: msg.created,
42
+ }))
43
+ .reverse()
44
+ }
45
+
46
+ async sendMessage(channelId: string, text: string): Promise<void> {
47
+ this.ensureClient()
48
+ await this.client!.sendMessage(channelId, text)
49
+ }
50
+
51
+ getAuthHint(): AuthHint {
52
+ return {
53
+ command: 'agent-webex auth login',
54
+ description: 'Authenticate with Cisco Webex using OAuth Device Grant. Run the command below to start.',
55
+ }
56
+ }
57
+
58
+ async authenticate(io: AuthIO): Promise<void> {
59
+ const credManager = new WebexCredentialManager()
60
+ const { clientId, clientSecret } = getWebexAppCredentials()
61
+
62
+ io.print('Starting Webex OAuth Device Grant flow...')
63
+ const device = await credManager.requestDeviceCode(clientId)
64
+
65
+ io.print(`\nOpen this URL in your browser:\n ${device.verificationUriComplete}`)
66
+ io.print(`\nOr go to ${device.verificationUri} and enter code: ${device.userCode}`)
67
+ openBrowser(device.verificationUriComplete)
68
+ io.print('\nWaiting for authorization...')
69
+
70
+ const config = await credManager.pollDeviceToken(
71
+ device.deviceCode,
72
+ device.interval,
73
+ device.expiresIn,
74
+ clientId,
75
+ clientSecret,
76
+ )
77
+ await credManager.saveConfig(config)
78
+
79
+ const client = new WebexClient()
80
+ await client.login({ token: config.accessToken })
81
+ const me = await client.testAuth()
82
+ this.client = client
83
+ this.personEmail = me.emails[0] ?? null
84
+
85
+ io.print(`\nAuthenticated as ${me.displayName} (${this.personEmail})`)
86
+ }
87
+
88
+ private ensureClient(): void {
89
+ if (!this.client) {
90
+ throw new Error('Not logged in. Call login() first.')
91
+ }
92
+ }
93
+ }
94
+
95
+ function openBrowser(url: string): void {
96
+ const command =
97
+ process.platform === 'darwin'
98
+ ? `open "${url}"`
99
+ : process.platform === 'win32'
100
+ ? `start "" "${url}"`
101
+ : `xdg-open "${url}"`
102
+ exec(command)
103
+ }
package/src/tui/app.ts CHANGED
@@ -3,6 +3,7 @@ import blessed from 'blessed'
3
3
  import { SlackAdapter } from './adapters/slack-adapter'
4
4
  import { DiscordAdapter } from './adapters/discord-adapter'
5
5
  import { TeamsAdapter } from './adapters/teams-adapter'
6
+ import { WebexAdapter } from './adapters/webex-adapter'
6
7
  import { TelegramAdapter } from './adapters/telegram-adapter'
7
8
  import { WhatsAppAdapter } from './adapters/whatsapp-adapter'
8
9
  import { LineAdapter } from './adapters/line-adapter'
@@ -38,6 +39,7 @@ export async function createApp(): Promise<void> {
38
39
  { adapter: new SlackAdapter(), label: 'Slack', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
39
40
  { adapter: new DiscordAdapter(), label: 'Discord', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
40
41
  { adapter: new TeamsAdapter(), label: 'Teams', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
42
+ { adapter: new WebexAdapter(), label: 'Webex', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
41
43
  { adapter: new TelegramAdapter(), label: 'Telegram', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
42
44
  { adapter: new WhatsAppAdapter(), label: 'WhatsApp', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },
43
45
  { adapter: new LineAdapter(), label: 'LINE', enabled: false, channels: null, workspaces: null, listening: false, lastChannelId: null },