agent-messenger 2.20.5 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +8 -5
- package/dist/package.json +9 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +3 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/platforms/webexbot/cli.d.ts +5 -0
- package/dist/src/platforms/webexbot/cli.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/cli.js +30 -0
- package/dist/src/platforms/webexbot/cli.js.map +1 -0
- package/dist/src/platforms/webexbot/client.d.ts +41 -0
- package/dist/src/platforms/webexbot/client.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/client.js +66 -0
- package/dist/src/platforms/webexbot/client.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/auth.d.ts +28 -0
- package/dist/src/platforms/webexbot/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/auth.js +166 -0
- package/dist/src/platforms/webexbot/commands/auth.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/index.d.ts +7 -0
- package/dist/src/platforms/webexbot/commands/index.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/index.js +7 -0
- package/dist/src/platforms/webexbot/commands/index.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/listen.d.ts +12 -0
- package/dist/src/platforms/webexbot/commands/listen.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/listen.js +85 -0
- package/dist/src/platforms/webexbot/commands/listen.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/member.d.ts +19 -0
- package/dist/src/platforms/webexbot/commands/member.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/member.js +33 -0
- package/dist/src/platforms/webexbot/commands/member.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/message.d.ts +37 -0
- package/dist/src/platforms/webexbot/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/message.js +142 -0
- package/dist/src/platforms/webexbot/commands/message.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/shared.d.ts +9 -0
- package/dist/src/platforms/webexbot/commands/shared.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/shared.js +13 -0
- package/dist/src/platforms/webexbot/commands/shared.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/space.d.ts +28 -0
- package/dist/src/platforms/webexbot/commands/space.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/space.js +61 -0
- package/dist/src/platforms/webexbot/commands/space.js.map +1 -0
- package/dist/src/platforms/webexbot/commands/whoami.d.ts +16 -0
- package/dist/src/platforms/webexbot/commands/whoami.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/commands/whoami.js +29 -0
- package/dist/src/platforms/webexbot/commands/whoami.js.map +1 -0
- package/dist/src/platforms/webexbot/credential-manager.d.ts +17 -0
- package/dist/src/platforms/webexbot/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/credential-manager.js +120 -0
- package/dist/src/platforms/webexbot/credential-manager.js.map +1 -0
- package/dist/src/platforms/webexbot/index.d.ts +9 -0
- package/dist/src/platforms/webexbot/index.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/index.js +6 -0
- package/dist/src/platforms/webexbot/index.js.map +1 -0
- package/dist/src/platforms/webexbot/listener.d.ts +44 -0
- package/dist/src/platforms/webexbot/listener.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/listener.js +214 -0
- package/dist/src/platforms/webexbot/listener.js.map +1 -0
- package/dist/src/platforms/webexbot/types.d.ts +60 -0
- package/dist/src/platforms/webexbot/types.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/types.js +28 -0
- package/dist/src/platforms/webexbot/types.js.map +1 -0
- package/dist/src/platforms/webexbot/wdm-discovery.d.ts +4 -0
- package/dist/src/platforms/webexbot/wdm-discovery.d.ts.map +1 -0
- package/dist/src/platforms/webexbot/wdm-discovery.js +36 -0
- package/dist/src/platforms/webexbot/wdm-discovery.js.map +1 -0
- package/docs/content/docs/cli/meta.json +1 -0
- package/docs/content/docs/cli/webexbot.mdx +290 -0
- package/docs/content/docs/sdk/meta.json +1 -0
- package/docs/content/docs/sdk/webexbot.mdx +340 -0
- package/docs/src/app/page.tsx +115 -19
- package/package.json +9 -1
- package/skills/agent-channeltalk/SKILL.md +1 -1
- package/skills/agent-channeltalkbot/SKILL.md +1 -1
- package/skills/agent-discord/SKILL.md +1 -1
- package/skills/agent-discordbot/SKILL.md +1 -1
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +1 -1
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +1 -1
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-telegrambot/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +1 -1
- package/skills/agent-webexbot/SKILL.md +361 -0
- package/skills/agent-webexbot/references/authentication.md +225 -0
- package/skills/agent-webexbot/references/common-patterns.md +590 -0
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/cli.ts +4 -0
- package/src/platforms/webex/typings/webex-message-handler.d.ts +360 -29
- package/src/platforms/webexbot/cli.ts +42 -0
- package/src/platforms/webexbot/client.ts +87 -0
- package/src/platforms/webexbot/commands/auth.test.ts +185 -0
- package/src/platforms/webexbot/commands/auth.ts +210 -0
- package/src/platforms/webexbot/commands/index.ts +6 -0
- package/src/platforms/webexbot/commands/listen.test.ts +20 -0
- package/src/platforms/webexbot/commands/listen.ts +104 -0
- package/src/platforms/webexbot/commands/member.ts +51 -0
- package/src/platforms/webexbot/commands/message.ts +197 -0
- package/src/platforms/webexbot/commands/shared.ts +22 -0
- package/src/platforms/webexbot/commands/space.ts +88 -0
- package/src/platforms/webexbot/commands/whoami.ts +43 -0
- package/src/platforms/webexbot/credential-manager.test.ts +182 -0
- package/src/platforms/webexbot/credential-manager.ts +149 -0
- package/src/platforms/webexbot/index.ts +8 -0
- package/src/platforms/webexbot/listener.test.ts +234 -0
- package/src/platforms/webexbot/listener.ts +255 -0
- package/src/platforms/webexbot/types.test.ts +87 -0
- package/src/platforms/webexbot/types.ts +72 -0
- package/src/platforms/webexbot/wdm-discovery.test.ts +97 -0
- package/src/platforms/webexbot/wdm-discovery.ts +43 -0
|
@@ -1,45 +1,376 @@
|
|
|
1
1
|
export {}
|
|
2
2
|
|
|
3
3
|
declare module 'webex-message-handler' {
|
|
4
|
-
import
|
|
4
|
+
import { EventEmitter } from 'events'
|
|
5
5
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import type { JWK } from 'node-jose'
|
|
7
|
+
|
|
8
|
+
export interface Logger {
|
|
9
|
+
debug(message: string, ...args: unknown[]): void
|
|
10
|
+
info(message: string, ...args: unknown[]): void
|
|
11
|
+
warn(message: string, ...args: unknown[]): void
|
|
12
|
+
error(message: string, ...args: unknown[]): void
|
|
13
|
+
}
|
|
10
14
|
|
|
11
15
|
export const noopLogger: Logger
|
|
12
16
|
export const consoleLogger: Logger
|
|
13
17
|
|
|
18
|
+
export type NetworkMode = 'native' | 'injected'
|
|
19
|
+
|
|
20
|
+
export interface FetchRequest {
|
|
21
|
+
url: string
|
|
22
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
|
23
|
+
headers: Record<string, string>
|
|
24
|
+
body?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface FetchResponse {
|
|
28
|
+
status: number
|
|
29
|
+
ok: boolean
|
|
30
|
+
json(): Promise<unknown>
|
|
31
|
+
text(): Promise<string>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type FetchFunction = (request: FetchRequest) => Promise<FetchResponse>
|
|
35
|
+
|
|
36
|
+
export interface InjectedWebSocket {
|
|
37
|
+
send(data: string): void
|
|
38
|
+
close(code?: number): void
|
|
39
|
+
readonly readyState: number
|
|
40
|
+
on(event: 'message', listener: (data: string) => void): void
|
|
41
|
+
on(event: 'open', listener: () => void): void
|
|
42
|
+
on(event: 'close', listener: (code: number, reason: string) => void): void
|
|
43
|
+
on(event: 'error', listener: (error: Error) => void): void
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type WebSocketFactory = (url: string) => InjectedWebSocket
|
|
47
|
+
|
|
48
|
+
export interface WebexMessageHandlerConfig {
|
|
49
|
+
token: string
|
|
50
|
+
logger?: Logger
|
|
51
|
+
/** Networking mode: 'native' uses built-in fetch/WebSocket, 'injected' uses provided functions */
|
|
52
|
+
mode?: NetworkMode
|
|
53
|
+
/**
|
|
54
|
+
* Optional undici Dispatcher for native mode proxy support (HTTP + WebSocket).
|
|
55
|
+
* A single `ProxyAgent` proxies both `fetch()` and the native `WebSocket`.
|
|
56
|
+
* Example: `new ProxyAgent('http://proxy:8080')`
|
|
57
|
+
*/
|
|
58
|
+
dispatcher?: object
|
|
59
|
+
/** Custom fetch function for all HTTP requests (injected mode) */
|
|
60
|
+
fetch?: FetchFunction
|
|
61
|
+
/** Custom WebSocket factory (injected mode) */
|
|
62
|
+
webSocketFactory?: WebSocketFactory
|
|
63
|
+
/** Automatically filter out messages sent by this bot to prevent loops (default: true) */
|
|
64
|
+
ignoreSelfMessages?: boolean
|
|
65
|
+
/** Ping interval in ms (default: 15000) */
|
|
66
|
+
pingInterval?: number
|
|
67
|
+
/** Pong timeout in ms (default: 14000) */
|
|
68
|
+
pongTimeout?: number
|
|
69
|
+
/** Max reconnect backoff in ms (default: 32000) */
|
|
70
|
+
reconnectBackoffMax?: number
|
|
71
|
+
/** Max reconnect attempts before giving up (default: 10) */
|
|
72
|
+
maxReconnectAttempts?: number
|
|
73
|
+
/** Optional metrics callback for timing events (no overhead if not set) */
|
|
74
|
+
metricsCallback?: MetricsCallback
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface PersonInfo {
|
|
78
|
+
/** Person's unique ID */
|
|
79
|
+
id: string
|
|
80
|
+
/** Person's email address */
|
|
81
|
+
emails: string[]
|
|
82
|
+
/** Person's display name */
|
|
83
|
+
displayName: string
|
|
84
|
+
/** Person type (person or bot) */
|
|
85
|
+
type: 'person' | 'bot'
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface DeviceRegistration {
|
|
89
|
+
/** The Mercury WebSocket URL */
|
|
90
|
+
webSocketUrl: string
|
|
91
|
+
/** The device URL (used as clientId for KMS) */
|
|
92
|
+
deviceUrl: string
|
|
93
|
+
/** The bot's user ID */
|
|
94
|
+
userId: string
|
|
95
|
+
/** Service catalog from WDM */
|
|
96
|
+
services: Record<string, string>
|
|
97
|
+
/** Encryption service URL extracted from services */
|
|
98
|
+
encryptionServiceUrl: string
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface MercuryActor {
|
|
102
|
+
id: string
|
|
103
|
+
objectType: string
|
|
104
|
+
emailAddress?: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface MercuryObject {
|
|
108
|
+
id: string
|
|
109
|
+
objectType: string
|
|
110
|
+
displayName?: string
|
|
111
|
+
content?: string
|
|
112
|
+
encryptionKeyUrl?: string
|
|
113
|
+
/** Card form input values (present on cardAction/submit activities). */
|
|
114
|
+
inputs?: Record<string, unknown>
|
|
115
|
+
/** File URLs attached to the message (present on file-share messages). */
|
|
116
|
+
files?: string[]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface MercuryTarget {
|
|
120
|
+
id: string
|
|
121
|
+
objectType: string
|
|
122
|
+
encryptionKeyUrl?: string
|
|
123
|
+
tags?: string[]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface MercuryParent {
|
|
127
|
+
id: string
|
|
128
|
+
type: string
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface MercuryActivity {
|
|
132
|
+
id: string
|
|
133
|
+
/** Full Conversation-service activity URL, when present on the raw activity. */
|
|
134
|
+
url?: string
|
|
135
|
+
verb: string
|
|
136
|
+
actor: MercuryActor
|
|
137
|
+
object: MercuryObject
|
|
138
|
+
target: MercuryTarget
|
|
139
|
+
published: string
|
|
140
|
+
encryptionKeyUrl?: string
|
|
141
|
+
parent?: MercuryParent
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface MercuryEnvelope {
|
|
145
|
+
id: string
|
|
146
|
+
data: {
|
|
147
|
+
eventType: string
|
|
148
|
+
activity: MercuryActivity
|
|
149
|
+
}
|
|
150
|
+
timestamp: number
|
|
151
|
+
trackingId: string
|
|
152
|
+
sequenceNumber?: number
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface DecryptedMessage {
|
|
156
|
+
/** Mercury activity UUID. Works as parentId for threaded replies. */
|
|
157
|
+
id: string
|
|
158
|
+
/**
|
|
159
|
+
* Full Conversation-service activity URL, when present on the raw Mercury
|
|
160
|
+
* activity (e.g. for an outbound "acknowledge" read-receipt). Undefined if
|
|
161
|
+
* Mercury did not include it.
|
|
162
|
+
*/
|
|
163
|
+
url?: string
|
|
164
|
+
/** Parent activity UUID for threaded replies. Undefined if not a thread reply. */
|
|
165
|
+
parentId?: string
|
|
166
|
+
roomId: string
|
|
167
|
+
personId: string
|
|
168
|
+
personEmail: string
|
|
169
|
+
text: string
|
|
170
|
+
html?: string
|
|
171
|
+
created: string
|
|
172
|
+
roomType?: string
|
|
173
|
+
/** Person UUIDs mentioned via @mention in the message. */
|
|
174
|
+
mentionedPeople: string[]
|
|
175
|
+
/** Group mention types (e.g. "all") in the message. */
|
|
176
|
+
mentionedGroups: string[]
|
|
177
|
+
/** File URLs attached to the message. Empty if no files. */
|
|
178
|
+
files: string[]
|
|
179
|
+
raw: MercuryActivity
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface DeletedMessage {
|
|
183
|
+
messageId: string
|
|
184
|
+
roomId: string
|
|
185
|
+
personId: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface MembershipActivity {
|
|
189
|
+
/** Activity ID. */
|
|
190
|
+
id: string
|
|
191
|
+
/** ID of the person who performed the action. */
|
|
192
|
+
actorId: string
|
|
193
|
+
/** ID of the member affected. */
|
|
194
|
+
personId: string
|
|
195
|
+
/** Conversation/space ID. */
|
|
196
|
+
roomId: string
|
|
197
|
+
/** Membership action: "add", "leave", "assignModerator", or "unassignModerator". */
|
|
198
|
+
action: string
|
|
199
|
+
/** ISO 8601 timestamp. */
|
|
200
|
+
created: string
|
|
201
|
+
/** "direct", "group", or undefined. */
|
|
202
|
+
roomType?: string
|
|
203
|
+
/** Full raw activity for advanced use. */
|
|
204
|
+
raw: MercuryActivity
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface AttachmentAction {
|
|
208
|
+
/** Activity ID. */
|
|
209
|
+
id: string
|
|
210
|
+
/** ID of the message the card was attached to. */
|
|
211
|
+
messageId: string
|
|
212
|
+
/** ID of the person who submitted the card. */
|
|
213
|
+
personId: string
|
|
214
|
+
/** Email of the person who submitted the card. */
|
|
215
|
+
personEmail: string
|
|
216
|
+
/** Conversation/space ID. */
|
|
217
|
+
roomId: string
|
|
218
|
+
/** Card form input values. */
|
|
219
|
+
inputs: Record<string, unknown>
|
|
220
|
+
/** ISO 8601 timestamp. */
|
|
221
|
+
created: string
|
|
222
|
+
/** Full raw activity for advanced use. */
|
|
223
|
+
raw: MercuryActivity
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface RoomActivity {
|
|
227
|
+
/** Activity ID. */
|
|
228
|
+
id: string
|
|
229
|
+
/** Conversation/space ID. */
|
|
230
|
+
roomId: string
|
|
231
|
+
/** ID of the person who performed the action. */
|
|
232
|
+
actorId: string
|
|
233
|
+
/** Room action: "created" or "updated". */
|
|
234
|
+
action: string
|
|
235
|
+
/** ISO 8601 timestamp. */
|
|
236
|
+
created: string
|
|
237
|
+
/** Full raw activity for advanced use. */
|
|
238
|
+
raw: MercuryActivity
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export type ConnectionStatus = 'connected' | 'connecting' | 'reconnecting' | 'disconnected'
|
|
242
|
+
|
|
243
|
+
export interface HandlerStatus {
|
|
244
|
+
/** Overall connection state. */
|
|
245
|
+
status: ConnectionStatus
|
|
246
|
+
/** Whether the WebSocket is currently open. */
|
|
247
|
+
webSocketOpen: boolean
|
|
248
|
+
/** Whether the KMS encryption context is initialized. */
|
|
249
|
+
kmsInitialized: boolean
|
|
250
|
+
/** Whether the device is registered with WDM. */
|
|
251
|
+
deviceRegistered: boolean
|
|
252
|
+
/** Current auto-reconnect attempt number (0 if not reconnecting). */
|
|
253
|
+
reconnectAttempt: number
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export interface MetricsEvent {
|
|
257
|
+
/** Metric name: "connect", "kms_fetch", or "decrypt". */
|
|
258
|
+
name: string
|
|
259
|
+
/** Duration in milliseconds. */
|
|
260
|
+
durationMs: number
|
|
261
|
+
/** Whether the operation succeeded. */
|
|
262
|
+
success: boolean
|
|
263
|
+
/** Optional context metadata (e.g., key URI for kms_fetch). */
|
|
264
|
+
metadata?: Record<string, string>
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export type MetricsCallback = (event: MetricsEvent) => void
|
|
268
|
+
|
|
269
|
+
export interface WebexMessageHandlerEvents {
|
|
270
|
+
'message:created': (msg: DecryptedMessage) => void
|
|
271
|
+
'message:updated': (msg: DecryptedMessage) => void
|
|
272
|
+
'message:deleted': (data: DeletedMessage) => void
|
|
273
|
+
'membership:created': (activity: MembershipActivity) => void
|
|
274
|
+
'attachmentAction:created': (action: AttachmentAction) => void
|
|
275
|
+
'room:created': (activity: RoomActivity) => void
|
|
276
|
+
'room:updated': (activity: RoomActivity) => void
|
|
277
|
+
connected: () => void
|
|
278
|
+
disconnected: (reason: string) => void
|
|
279
|
+
reconnecting: (attempt: number) => void
|
|
280
|
+
error: (err: Error) => void
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
interface TypedEventEmitter<T> {
|
|
284
|
+
on<K extends keyof T>(event: K, listener: T[K]): this
|
|
285
|
+
emit<K extends keyof T>(
|
|
286
|
+
event: K,
|
|
287
|
+
...args: Parameters<T[K] extends (...a: infer P) => unknown ? (...a: P) => unknown : never>
|
|
288
|
+
): boolean
|
|
289
|
+
off<K extends keyof T>(event: K, listener: T[K]): this
|
|
290
|
+
once<K extends keyof T>(event: K, listener: T[K]): this
|
|
291
|
+
removeAllListeners<K extends keyof T>(event?: K): this
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export class WebexMessageHandler extends EventEmitter implements TypedEventEmitter<WebexMessageHandlerEvents> {
|
|
295
|
+
constructor(config: WebexMessageHandlerConfig)
|
|
296
|
+
connect(): Promise<void>
|
|
297
|
+
disconnect(): Promise<void>
|
|
298
|
+
reconnect(newToken: string): Promise<void>
|
|
299
|
+
get connected(): boolean
|
|
300
|
+
status(): HandlerStatus
|
|
301
|
+
deviceRegistration(): DeviceRegistration | null
|
|
302
|
+
serviceUrl(name: string): string | undefined
|
|
303
|
+
on<K extends keyof WebexMessageHandlerEvents>(event: K, listener: WebexMessageHandlerEvents[K]): this
|
|
304
|
+
emit<K extends keyof WebexMessageHandlerEvents>(
|
|
305
|
+
event: K,
|
|
306
|
+
...args: Parameters<
|
|
307
|
+
WebexMessageHandlerEvents[K] extends (...a: infer P) => unknown ? (...a: P) => unknown : never
|
|
308
|
+
>
|
|
309
|
+
): boolean
|
|
310
|
+
off<K extends keyof WebexMessageHandlerEvents>(event: K, listener: WebexMessageHandlerEvents[K]): this
|
|
311
|
+
once<K extends keyof WebexMessageHandlerEvents>(event: K, listener: WebexMessageHandlerEvents[K]): this
|
|
312
|
+
removeAllListeners<K extends keyof WebexMessageHandlerEvents>(event?: K): this
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
type HttpDoFn = (request: FetchRequest) => Promise<FetchResponse>
|
|
316
|
+
|
|
317
|
+
export interface DeviceManagerOptions {
|
|
318
|
+
logger?: Logger
|
|
319
|
+
httpDo: HttpDoFn
|
|
320
|
+
}
|
|
321
|
+
|
|
14
322
|
export class DeviceManager {
|
|
15
|
-
constructor(options:
|
|
16
|
-
register(token: string): Promise<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
323
|
+
constructor(options: DeviceManagerOptions)
|
|
324
|
+
register(token: string): Promise<DeviceRegistration>
|
|
325
|
+
refresh(token: string): Promise<DeviceRegistration>
|
|
326
|
+
unregister(token: string): Promise<void>
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export interface MercurySocketOptions {
|
|
330
|
+
logger?: Logger
|
|
331
|
+
wsFactory: WebSocketFactory
|
|
332
|
+
pingInterval?: number
|
|
333
|
+
pongTimeout?: number
|
|
334
|
+
reconnectBackoffMax?: number
|
|
335
|
+
maxReconnectAttempts?: number
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export class MercurySocket extends EventEmitter {
|
|
339
|
+
constructor(options: MercurySocketOptions)
|
|
340
|
+
connect(url: string, token: string): Promise<void>
|
|
29
341
|
disconnect(): Promise<void>
|
|
342
|
+
get connected(): boolean
|
|
343
|
+
get currentReconnectAttempts(): number
|
|
344
|
+
on(event: 'kms:response', handler: (data: unknown) => void): this
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export interface KmsClientConfig {
|
|
348
|
+
token: string
|
|
349
|
+
deviceUrl: string
|
|
350
|
+
userId: string
|
|
351
|
+
encryptionServiceUrl: string
|
|
352
|
+
logger?: Logger
|
|
353
|
+
httpDo: HttpDoFn
|
|
30
354
|
}
|
|
31
355
|
|
|
32
356
|
export class KmsClient {
|
|
33
|
-
constructor(
|
|
34
|
-
token: string
|
|
35
|
-
deviceUrl: string
|
|
36
|
-
userId: string
|
|
37
|
-
encryptionServiceUrl: string
|
|
38
|
-
logger: Logger
|
|
39
|
-
httpDo: HttpDo
|
|
40
|
-
})
|
|
41
|
-
initialize(): Promise<void>
|
|
42
|
-
getKey(keyUri: string): Promise<jose.JWK.Key | null>
|
|
357
|
+
constructor(config: KmsClientConfig)
|
|
43
358
|
handleKmsMessage(data: unknown): void
|
|
359
|
+
initialize(): Promise<void>
|
|
360
|
+
getKey(keyUri: string): Promise<JWK.Key>
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export class MessageDecryptor {
|
|
364
|
+
constructor({ kmsClient, logger }: { kmsClient: KmsClient; logger?: Logger })
|
|
365
|
+
decryptActivity(activity: MercuryActivity): Promise<MercuryActivity>
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface ParsedMentions {
|
|
369
|
+
mentionedPeople: string[]
|
|
370
|
+
mentionedGroups: string[]
|
|
44
371
|
}
|
|
372
|
+
|
|
373
|
+
export function parseMentions(html: string | undefined | null): ParsedMentions
|
|
374
|
+
export function toRestId(uuid: string, type: 'MESSAGE' | 'PEOPLE' | 'ROOM'): string
|
|
375
|
+
export function fromRestId(restId: string): string
|
|
45
376
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander'
|
|
4
|
+
|
|
5
|
+
import pkg from '../../../package.json' with { type: 'json' }
|
|
6
|
+
import {
|
|
7
|
+
authCommand,
|
|
8
|
+
listenCommand,
|
|
9
|
+
memberCommand,
|
|
10
|
+
messageCommand,
|
|
11
|
+
spaceCommand,
|
|
12
|
+
whoamiCommand,
|
|
13
|
+
} from './commands/index'
|
|
14
|
+
|
|
15
|
+
const program = new Command()
|
|
16
|
+
|
|
17
|
+
program
|
|
18
|
+
.name('agent-webexbot')
|
|
19
|
+
.description('CLI tool for Webex bot integration using bot tokens')
|
|
20
|
+
.version(pkg.version)
|
|
21
|
+
.option('--pretty', 'Pretty-print JSON output')
|
|
22
|
+
.option('--bot <id>', 'Bot ID to use')
|
|
23
|
+
.hook('preAction', (thisCmd, actionCmd) => {
|
|
24
|
+
for (const [key, value] of Object.entries(thisCmd.opts())) {
|
|
25
|
+
if (value === undefined) continue
|
|
26
|
+
const source = actionCmd.getOptionValueSource(key)
|
|
27
|
+
if (source === undefined || source === 'default') {
|
|
28
|
+
actionCmd.setOptionValue(key, value)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
program.addCommand(authCommand)
|
|
34
|
+
program.addCommand(whoamiCommand)
|
|
35
|
+
program.addCommand(messageCommand)
|
|
36
|
+
program.addCommand(spaceCommand)
|
|
37
|
+
program.addCommand(memberCommand)
|
|
38
|
+
program.addCommand(listenCommand)
|
|
39
|
+
|
|
40
|
+
program.parseAsync(process.argv)
|
|
41
|
+
|
|
42
|
+
export default program
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { WebexClient } from '../webex/client'
|
|
2
|
+
import type { WebexMembership, WebexMessage, WebexPerson, WebexSpace } from '../webex/types'
|
|
3
|
+
import { WebexBotError } from './types'
|
|
4
|
+
|
|
5
|
+
export class WebexBotClient {
|
|
6
|
+
private client = new WebexClient()
|
|
7
|
+
private token: string | null = null
|
|
8
|
+
|
|
9
|
+
async login(credentials?: { token: string }): Promise<this> {
|
|
10
|
+
if (credentials) {
|
|
11
|
+
if (!credentials.token) {
|
|
12
|
+
throw new WebexBotError('Token is required', 'missing_token')
|
|
13
|
+
}
|
|
14
|
+
this.token = credentials.token
|
|
15
|
+
await this.client.login({ token: credentials.token })
|
|
16
|
+
return this
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { WebexBotCredentialManager } = await import('./credential-manager')
|
|
20
|
+
const credManager = new WebexBotCredentialManager()
|
|
21
|
+
const creds = await credManager.getCredentials()
|
|
22
|
+
if (!creds?.token) {
|
|
23
|
+
throw new WebexBotError('No Webex bot credentials found. Run "auth set <token>" first.', 'no_credentials')
|
|
24
|
+
}
|
|
25
|
+
return this.login({ token: creds.token })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getToken(): string {
|
|
29
|
+
if (!this.token) {
|
|
30
|
+
throw new WebexBotError('Not authenticated. Call .login() first.', 'not_authenticated')
|
|
31
|
+
}
|
|
32
|
+
return this.token
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async testAuth(): Promise<WebexPerson> {
|
|
36
|
+
return this.client.testAuth()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async listSpaces(options?: { type?: string; max?: number }): Promise<WebexSpace[]> {
|
|
40
|
+
return this.client.listSpaces(options)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async getSpace(spaceId: string): Promise<WebexSpace> {
|
|
44
|
+
return this.client.getSpace(spaceId)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async sendMessage(roomId: string, text: string, options?: { markdown?: boolean }): Promise<WebexMessage> {
|
|
48
|
+
return this.client.sendMessage(roomId, text, options)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async sendDirectMessage(personEmail: string, text: string, options?: { markdown?: boolean }): Promise<WebexMessage> {
|
|
52
|
+
return this.client.sendDirectMessage(personEmail, text, options)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async listMessages(roomId: string, options?: { max?: number }): Promise<WebexMessage[]> {
|
|
56
|
+
return this.client.listMessages(roomId, options)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async getMessage(messageId: string): Promise<WebexMessage> {
|
|
60
|
+
return this.client.getMessage(messageId)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async deleteMessage(messageId: string): Promise<void> {
|
|
64
|
+
return this.client.deleteMessage(messageId)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async editMessage(
|
|
68
|
+
messageId: string,
|
|
69
|
+
roomId: string,
|
|
70
|
+
text: string,
|
|
71
|
+
options?: { markdown?: boolean },
|
|
72
|
+
): Promise<WebexMessage> {
|
|
73
|
+
return this.client.editMessage(messageId, roomId, text, options)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async listPeople(options?: { email?: string; displayName?: string; max?: number }): Promise<WebexPerson[]> {
|
|
77
|
+
return this.client.listPeople(options)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async listMyMemberships(options?: { max?: number }): Promise<WebexMembership[]> {
|
|
81
|
+
return this.client.listMyMemberships(options)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async listMemberships(roomId: string, options?: { max?: number }): Promise<WebexMembership[]> {
|
|
85
|
+
return this.client.listMemberships(roomId, options)
|
|
86
|
+
}
|
|
87
|
+
}
|