agent-messenger 2.23.2 → 2.23.4
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/dist/package.json +1 -1
- package/dist/src/platforms/webex/client.d.ts.map +1 -1
- package/dist/src/platforms/webex/client.js +28 -16
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +1 -2
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/commands/member.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/member.js +2 -3
- package/dist/src/platforms/webex/commands/member.js.map +1 -1
- package/dist/src/platforms/webex/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/message.js +2 -3
- package/dist/src/platforms/webex/commands/message.js.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/whoami.js +2 -3
- package/dist/src/platforms/webex/commands/whoami.js.map +1 -1
- package/dist/src/platforms/webex/id-normalizer.d.ts +9 -5
- package/dist/src/platforms/webex/id-normalizer.d.ts.map +1 -1
- package/dist/src/platforms/webex/id-normalizer.js +87 -21
- package/dist/src/platforms/webex/id-normalizer.js.map +1 -1
- package/dist/src/platforms/webex/index.d.ts +1 -1
- package/dist/src/platforms/webex/index.d.ts.map +1 -1
- package/dist/src/platforms/webex/index.js.map +1 -1
- package/dist/src/platforms/webex/listener.d.ts +10 -9
- package/dist/src/platforms/webex/listener.d.ts.map +1 -1
- package/dist/src/platforms/webex/listener.js.map +1 -1
- package/dist/src/platforms/webex/types.d.ts +51 -0
- package/dist/src/platforms/webex/types.d.ts.map +1 -1
- package/dist/src/platforms/webex/types.js +10 -0
- package/dist/src/platforms/webex/types.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/file.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/commands/file.js +2 -3
- package/dist/src/platforms/webexbot/commands/file.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/member.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/commands/member.js +2 -3
- package/dist/src/platforms/webexbot/commands/member.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/commands/message.js +6 -7
- package/dist/src/platforms/webexbot/commands/message.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/snapshot.js +1 -1
- package/dist/src/platforms/webexbot/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/commands/user.js +3 -4
- package/dist/src/platforms/webexbot/commands/user.js.map +1 -1
- package/dist/src/platforms/webexbot/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/commands/whoami.js +2 -3
- package/dist/src/platforms/webexbot/commands/whoami.js.map +1 -1
- package/dist/src/platforms/webexbot/index.d.ts +1 -1
- package/dist/src/platforms/webexbot/index.d.ts.map +1 -1
- package/dist/src/platforms/webexbot/index.js.map +1 -1
- package/dist/src/tui/adapters/webex-adapter.js +2 -2
- package/dist/src/tui/adapters/webex-adapter.js.map +1 -1
- package/package.json +1 -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 +1 -1
- 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/platforms/webex/client.ts +36 -16
- package/src/platforms/webex/commands/auth.ts +3 -3
- package/src/platforms/webex/commands/member.test.ts +6 -0
- package/src/platforms/webex/commands/member.ts +2 -3
- package/src/platforms/webex/commands/message.test.ts +6 -0
- package/src/platforms/webex/commands/message.ts +2 -3
- package/src/platforms/webex/commands/whoami.test.ts +2 -0
- package/src/platforms/webex/commands/whoami.ts +2 -3
- package/src/platforms/webex/id-normalizer.test.ts +245 -2
- package/src/platforms/webex/id-normalizer.ts +106 -26
- package/src/platforms/webex/index.ts +13 -1
- package/src/platforms/webex/listener.test.ts +3 -0
- package/src/platforms/webex/listener.ts +16 -8
- package/src/platforms/webex/types.test.ts +20 -0
- package/src/platforms/webex/types.ts +68 -0
- package/src/platforms/webex/typings/webex-message-handler.d.ts +40 -2
- package/src/platforms/webexbot/commands/file.ts +2 -3
- package/src/platforms/webexbot/commands/member.ts +2 -3
- package/src/platforms/webexbot/commands/message.ts +6 -7
- package/src/platforms/webexbot/commands/snapshot.ts +1 -1
- package/src/platforms/webexbot/commands/user.test.ts +4 -0
- package/src/platforms/webexbot/commands/user.ts +3 -4
- package/src/platforms/webexbot/commands/whoami.ts +2 -3
- package/src/platforms/webexbot/index.ts +12 -1
- package/src/tui/adapters/webex-adapter.ts +2 -2
|
@@ -11,22 +11,28 @@ const personId = toRestId('person_789', 'PEOPLE')
|
|
|
11
11
|
|
|
12
12
|
const mockMessage = {
|
|
13
13
|
id: messageId,
|
|
14
|
+
ref: 'msg_123',
|
|
14
15
|
roomId,
|
|
16
|
+
roomRef: 'space_456',
|
|
15
17
|
roomType: 'group' as const,
|
|
16
18
|
text: 'Hello world',
|
|
17
19
|
html: '<p>Hello <a href="https://example.com">world</a></p>',
|
|
18
20
|
personId,
|
|
21
|
+
personRef: 'person_789',
|
|
19
22
|
personEmail: 'user@example.com',
|
|
20
23
|
created: '2025-01-29T10:00:00.000Z',
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
const mockMessage2 = {
|
|
24
27
|
id: message2Id,
|
|
28
|
+
ref: 'msg_124',
|
|
25
29
|
roomId,
|
|
30
|
+
roomRef: 'space_456',
|
|
26
31
|
roomType: 'group' as const,
|
|
27
32
|
text: 'Second message',
|
|
28
33
|
html: '<p>Second message</p>',
|
|
29
34
|
personId,
|
|
35
|
+
personRef: 'person_789',
|
|
30
36
|
personEmail: 'user@example.com',
|
|
31
37
|
created: '2025-01-29T10:01:00.000Z',
|
|
32
38
|
}
|
|
@@ -4,15 +4,14 @@ import { handleError } from '@/shared/utils/error-handler'
|
|
|
4
4
|
import { formatOutput } from '@/shared/utils/output'
|
|
5
5
|
|
|
6
6
|
import { WebexClient } from '../client'
|
|
7
|
-
import { toRef } from '../id-normalizer'
|
|
8
7
|
import type { WebexMessage } from '../types'
|
|
9
8
|
|
|
10
9
|
function formatMessageOutput(message: WebexMessage) {
|
|
11
10
|
return {
|
|
12
11
|
id: message.id,
|
|
13
|
-
ref:
|
|
12
|
+
ref: message.ref,
|
|
14
13
|
roomId: message.roomId,
|
|
15
|
-
roomRef:
|
|
14
|
+
roomRef: message.roomRef,
|
|
16
15
|
text: message.text,
|
|
17
16
|
html: message.html,
|
|
18
17
|
personEmail: message.personEmail,
|
|
@@ -10,6 +10,7 @@ const personId = toRestId('person-123', 'PEOPLE')
|
|
|
10
10
|
|
|
11
11
|
const mockUser = {
|
|
12
12
|
id: personId,
|
|
13
|
+
ref: 'person-123',
|
|
13
14
|
emails: ['test@example.com'],
|
|
14
15
|
displayName: 'Test User',
|
|
15
16
|
nickName: 'Testy',
|
|
@@ -17,6 +18,7 @@ const mockUser = {
|
|
|
17
18
|
lastName: 'User',
|
|
18
19
|
avatar: 'https://example.com/avatar.jpg',
|
|
19
20
|
orgId,
|
|
21
|
+
orgRef: 'org-123',
|
|
20
22
|
type: 'person' as const,
|
|
21
23
|
created: '2024-01-01T00:00:00.000Z',
|
|
22
24
|
}
|
|
@@ -4,7 +4,6 @@ import { handleError } from '@/shared/utils/error-handler'
|
|
|
4
4
|
import { formatOutput } from '@/shared/utils/output'
|
|
5
5
|
|
|
6
6
|
import { WebexClient } from '../client'
|
|
7
|
-
import { toRef } from '../id-normalizer'
|
|
8
7
|
|
|
9
8
|
export async function whoamiAction(options: { pretty?: boolean }): Promise<void> {
|
|
10
9
|
try {
|
|
@@ -13,7 +12,7 @@ export async function whoamiAction(options: { pretty?: boolean }): Promise<void>
|
|
|
13
12
|
|
|
14
13
|
const output = {
|
|
15
14
|
id: user.id,
|
|
16
|
-
ref:
|
|
15
|
+
ref: user.ref,
|
|
17
16
|
emails: user.emails,
|
|
18
17
|
displayName: user.displayName,
|
|
19
18
|
nickName: user.nickName,
|
|
@@ -21,7 +20,7 @@ export async function whoamiAction(options: { pretty?: boolean }): Promise<void>
|
|
|
21
20
|
lastName: user.lastName,
|
|
22
21
|
avatar: user.avatar,
|
|
23
22
|
orgId: user.orgId,
|
|
24
|
-
orgRef:
|
|
23
|
+
orgRef: user.orgRef,
|
|
25
24
|
type: user.type,
|
|
26
25
|
}
|
|
27
26
|
console.log(formatOutput(output, options.pretty))
|
|
@@ -16,9 +16,13 @@ import {
|
|
|
16
16
|
normalizeMembership,
|
|
17
17
|
normalizeMessage,
|
|
18
18
|
normalizeRoomActivity,
|
|
19
|
+
normalizeSdkMembership,
|
|
20
|
+
normalizeSdkMessage,
|
|
21
|
+
normalizeSdkPerson,
|
|
19
22
|
toRestId,
|
|
20
23
|
toRef,
|
|
21
24
|
} from './id-normalizer'
|
|
25
|
+
import type { WebexMembership, WebexMessage, WebexPerson } from './types'
|
|
22
26
|
|
|
23
27
|
const RAW: MercuryActivity = {
|
|
24
28
|
id: 'activity-uuid',
|
|
@@ -122,6 +126,23 @@ describe('normalizeMessage', () => {
|
|
|
122
126
|
expect(result.mentionedPeople).toEqual([toRestId('mention-uuid-1', 'PEOPLE'), toRestId('mention-uuid-2', 'PEOPLE')])
|
|
123
127
|
})
|
|
124
128
|
|
|
129
|
+
it('adds a raw uuid ref alongside every id', () => {
|
|
130
|
+
const result = normalizeMessage(message)
|
|
131
|
+
|
|
132
|
+
expect(result.ref).toBe('msg-uuid')
|
|
133
|
+
expect(result.parentRef).toBe('parent-uuid')
|
|
134
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
135
|
+
expect(result.personRef).toBe('person-uuid')
|
|
136
|
+
expect(result.mentionedPeopleRefs).toEqual(['mention-uuid-1', 'mention-uuid-2'])
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('omits parentRef when parentId is absent', () => {
|
|
140
|
+
const { parentId: _omit, ...withoutParent } = message
|
|
141
|
+
const result = normalizeMessage(withoutParent)
|
|
142
|
+
|
|
143
|
+
expect(result.parentRef).toBeUndefined()
|
|
144
|
+
})
|
|
145
|
+
|
|
125
146
|
it('leaves non-id fields and raw untouched', () => {
|
|
126
147
|
const result = normalizeMessage(message)
|
|
127
148
|
|
|
@@ -157,8 +178,11 @@ describe('normalizeDeletedMessage', () => {
|
|
|
157
178
|
|
|
158
179
|
expect(normalizeDeletedMessage(deleted)).toEqual({
|
|
159
180
|
messageId: toRestId('msg-uuid', 'MESSAGE'),
|
|
181
|
+
messageRef: 'msg-uuid',
|
|
160
182
|
roomId: toRestId('room-uuid', 'ROOM'),
|
|
183
|
+
roomRef: 'room-uuid',
|
|
161
184
|
personId: toRestId('person-uuid', 'PEOPLE'),
|
|
185
|
+
personRef: 'person-uuid',
|
|
162
186
|
})
|
|
163
187
|
})
|
|
164
188
|
})
|
|
@@ -183,6 +207,25 @@ describe('normalizeMembership', () => {
|
|
|
183
207
|
expect(result.roomId).toBe(toRestId('room-uuid', 'ROOM'))
|
|
184
208
|
expect(result.raw).toBe(RAW)
|
|
185
209
|
})
|
|
210
|
+
|
|
211
|
+
it('sets ref to the raw activity id and adds refs for the rest', () => {
|
|
212
|
+
const membership: MembershipActivity = {
|
|
213
|
+
id: 'activity-uuid',
|
|
214
|
+
actorId: 'actor-uuid',
|
|
215
|
+
personId: 'member-uuid',
|
|
216
|
+
roomId: 'room-uuid',
|
|
217
|
+
action: 'add',
|
|
218
|
+
created: '2024-01-01T00:00:00Z',
|
|
219
|
+
raw: RAW,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const result = normalizeMembership(membership)
|
|
223
|
+
|
|
224
|
+
expect(result.ref).toBe('activity-uuid')
|
|
225
|
+
expect(result.actorRef).toBe('actor-uuid')
|
|
226
|
+
expect(result.personRef).toBe('member-uuid')
|
|
227
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
228
|
+
})
|
|
186
229
|
})
|
|
187
230
|
|
|
188
231
|
describe('normalizeAttachmentAction', () => {
|
|
@@ -207,7 +250,27 @@ describe('normalizeAttachmentAction', () => {
|
|
|
207
250
|
expect(result.inputs).toEqual({ choice: 'yes' })
|
|
208
251
|
})
|
|
209
252
|
|
|
210
|
-
it('
|
|
253
|
+
it('adds a raw uuid ref alongside every id', () => {
|
|
254
|
+
const action: AttachmentAction = {
|
|
255
|
+
id: 'action-uuid',
|
|
256
|
+
messageId: 'msg-uuid',
|
|
257
|
+
personId: 'person-uuid',
|
|
258
|
+
personEmail: 'user@example.com',
|
|
259
|
+
roomId: 'room-uuid',
|
|
260
|
+
inputs: { choice: 'yes' },
|
|
261
|
+
created: '2024-01-01T00:00:00Z',
|
|
262
|
+
raw: RAW,
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const result = normalizeAttachmentAction(action)
|
|
266
|
+
|
|
267
|
+
expect(result.ref).toBe('action-uuid')
|
|
268
|
+
expect(result.messageRef).toBe('msg-uuid')
|
|
269
|
+
expect(result.personRef).toBe('person-uuid')
|
|
270
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('preserves an empty messageId and its ref', () => {
|
|
211
274
|
const action: AttachmentAction = {
|
|
212
275
|
id: 'action-uuid',
|
|
213
276
|
messageId: '',
|
|
@@ -219,7 +282,9 @@ describe('normalizeAttachmentAction', () => {
|
|
|
219
282
|
raw: RAW,
|
|
220
283
|
}
|
|
221
284
|
|
|
222
|
-
|
|
285
|
+
const result = normalizeAttachmentAction(action)
|
|
286
|
+
expect(result.messageId).toBe('')
|
|
287
|
+
expect(result.messageRef).toBe('')
|
|
223
288
|
})
|
|
224
289
|
})
|
|
225
290
|
|
|
@@ -241,4 +306,182 @@ describe('normalizeRoomActivity', () => {
|
|
|
241
306
|
expect(result.actorId).toBe(toRestId('actor-uuid', 'PEOPLE'))
|
|
242
307
|
expect(result.raw).toBe(RAW)
|
|
243
308
|
})
|
|
309
|
+
|
|
310
|
+
it('sets ref to the raw activity id and adds refs for the rest', () => {
|
|
311
|
+
const room: RoomActivity = {
|
|
312
|
+
id: 'activity-uuid',
|
|
313
|
+
roomId: 'room-uuid',
|
|
314
|
+
actorId: 'actor-uuid',
|
|
315
|
+
action: 'created',
|
|
316
|
+
created: '2024-01-01T00:00:00Z',
|
|
317
|
+
raw: RAW,
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const result = normalizeRoomActivity(room)
|
|
321
|
+
|
|
322
|
+
expect(result.ref).toBe('activity-uuid')
|
|
323
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
324
|
+
expect(result.actorRef).toBe('actor-uuid')
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
describe('normalizeSdkPerson', () => {
|
|
329
|
+
const person: WebexPerson = {
|
|
330
|
+
id: restId('PEOPLE', 'person-uuid'),
|
|
331
|
+
ref: '',
|
|
332
|
+
emails: ['user@example.com'],
|
|
333
|
+
displayName: 'User',
|
|
334
|
+
orgId: restId('ORGANIZATION', 'org-uuid'),
|
|
335
|
+
orgRef: '',
|
|
336
|
+
type: 'person',
|
|
337
|
+
created: '2024-01-01T00:00:00Z',
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
it('decodes the bot identity id and orgId into raw uuid refs', () => {
|
|
341
|
+
const result = normalizeSdkPerson(person)
|
|
342
|
+
|
|
343
|
+
expect(result.ref).toBe('person-uuid')
|
|
344
|
+
expect(result.orgRef).toBe('org-uuid')
|
|
345
|
+
})
|
|
346
|
+
|
|
347
|
+
it('does not re-encode the already-REST ids', () => {
|
|
348
|
+
const result = normalizeSdkPerson(person)
|
|
349
|
+
|
|
350
|
+
expect(result.id).toBe(restId('PEOPLE', 'person-uuid'))
|
|
351
|
+
expect(result.orgId).toBe(restId('ORGANIZATION', 'org-uuid'))
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('leaves empty ids and refs empty', () => {
|
|
355
|
+
const result = normalizeSdkPerson({ ...person, id: '', orgId: '' })
|
|
356
|
+
|
|
357
|
+
expect(result.ref).toBe('')
|
|
358
|
+
expect(result.orgRef).toBe('')
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('returns a new object without mutating the input', () => {
|
|
362
|
+
const result = normalizeSdkPerson(person)
|
|
363
|
+
|
|
364
|
+
expect(result).not.toBe(person)
|
|
365
|
+
expect(person.ref).toBe('')
|
|
366
|
+
})
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
describe('normalizeSdkMessage', () => {
|
|
370
|
+
const message: WebexMessage = {
|
|
371
|
+
id: restId('MESSAGE', 'msg-uuid'),
|
|
372
|
+
ref: '',
|
|
373
|
+
roomId: restId('ROOM', 'room-uuid'),
|
|
374
|
+
roomRef: '',
|
|
375
|
+
roomType: 'group',
|
|
376
|
+
text: 'hello',
|
|
377
|
+
personId: restId('PEOPLE', 'person-uuid'),
|
|
378
|
+
personRef: '',
|
|
379
|
+
personEmail: 'user@example.com',
|
|
380
|
+
created: '2024-01-01T00:00:00Z',
|
|
381
|
+
parentId: restId('MESSAGE', 'parent-uuid'),
|
|
382
|
+
mentionedPeople: [restId('PEOPLE', 'mention-1'), restId('PEOPLE', 'mention-2')],
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
it('decodes id, roomId, personId and parentId into raw uuid refs', () => {
|
|
386
|
+
const result = normalizeSdkMessage(message)
|
|
387
|
+
|
|
388
|
+
expect(result.ref).toBe('msg-uuid')
|
|
389
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
390
|
+
expect(result.personRef).toBe('person-uuid')
|
|
391
|
+
expect(result.parentRef).toBe('parent-uuid')
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
it('adds a mentionedPeopleRefs array of raw uuids', () => {
|
|
395
|
+
const result = normalizeSdkMessage(message)
|
|
396
|
+
|
|
397
|
+
expect(result.mentionedPeopleRefs).toEqual(['mention-1', 'mention-2'])
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
it('omits parentRef when parentId is absent', () => {
|
|
401
|
+
const { parentId: _omit, ...withoutParent } = message
|
|
402
|
+
const result = normalizeSdkMessage(withoutParent)
|
|
403
|
+
|
|
404
|
+
expect(result.parentRef).toBeUndefined()
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
it('omits mentionedPeopleRefs when mentionedPeople is absent', () => {
|
|
408
|
+
const { mentionedPeople: _omit, ...withoutMentions } = message
|
|
409
|
+
const result = normalizeSdkMessage(withoutMentions)
|
|
410
|
+
|
|
411
|
+
expect(result.mentionedPeopleRefs).toBeUndefined()
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
it('does not re-encode the already-REST ids', () => {
|
|
415
|
+
const result = normalizeSdkMessage(message)
|
|
416
|
+
|
|
417
|
+
expect(result.id).toBe(restId('MESSAGE', 'msg-uuid'))
|
|
418
|
+
expect(result.roomId).toBe(restId('ROOM', 'room-uuid'))
|
|
419
|
+
})
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
describe('normalizeSdkMembership', () => {
|
|
423
|
+
const membership: WebexMembership = {
|
|
424
|
+
id: restId('MEMBERSHIP', 'membership-uuid'),
|
|
425
|
+
ref: '',
|
|
426
|
+
roomId: restId('ROOM', 'room-uuid'),
|
|
427
|
+
roomRef: '',
|
|
428
|
+
personId: restId('PEOPLE', 'person-uuid'),
|
|
429
|
+
personRef: '',
|
|
430
|
+
personEmail: 'user@example.com',
|
|
431
|
+
personDisplayName: 'User',
|
|
432
|
+
isModerator: false,
|
|
433
|
+
created: '2024-01-01T00:00:00Z',
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
it('decodes id, roomId and personId into raw uuid refs', () => {
|
|
437
|
+
const result = normalizeSdkMembership(membership)
|
|
438
|
+
|
|
439
|
+
expect(result.ref).toBe('membership-uuid')
|
|
440
|
+
expect(result.roomRef).toBe('room-uuid')
|
|
441
|
+
expect(result.personRef).toBe('person-uuid')
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('does not re-encode the already-REST ids', () => {
|
|
445
|
+
const result = normalizeSdkMembership(membership)
|
|
446
|
+
|
|
447
|
+
expect(result.id).toBe(restId('MEMBERSHIP', 'membership-uuid'))
|
|
448
|
+
expect(result.personId).toBe(restId('PEOPLE', 'person-uuid'))
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
describe('SDK and event refs agree for the same person', () => {
|
|
453
|
+
it('matches the bot identity ref against an event mention ref so self/mention detection holds', () => {
|
|
454
|
+
const personUuid = 'bot-person-uuid'
|
|
455
|
+
|
|
456
|
+
// given: the bot identity from a REST response (testAuth path)
|
|
457
|
+
const bot = normalizeSdkPerson({
|
|
458
|
+
id: restId('PEOPLE', personUuid),
|
|
459
|
+
ref: '',
|
|
460
|
+
emails: ['bot@webex.bot'],
|
|
461
|
+
displayName: 'Bot',
|
|
462
|
+
orgId: restId('ORGANIZATION', 'org-uuid'),
|
|
463
|
+
orgRef: '',
|
|
464
|
+
type: 'bot',
|
|
465
|
+
created: '2024-01-01T00:00:00Z',
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
// when: an event carries the same person as a raw Mercury uuid
|
|
469
|
+
const event = normalizeMessage({
|
|
470
|
+
id: 'msg-uuid',
|
|
471
|
+
roomId: 'room-uuid',
|
|
472
|
+
personId: personUuid,
|
|
473
|
+
personEmail: 'bot@webex.bot',
|
|
474
|
+
text: 'hi',
|
|
475
|
+
created: '2024-01-01T00:00:00Z',
|
|
476
|
+
mentionedPeople: [personUuid],
|
|
477
|
+
mentionedGroups: [],
|
|
478
|
+
files: [],
|
|
479
|
+
raw: RAW,
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
// then: both paths decode to the same raw uuid ref
|
|
483
|
+
expect(bot.ref).toBe(personUuid)
|
|
484
|
+
expect(event.personRef).toBe(personUuid)
|
|
485
|
+
expect(event.mentionedPeopleRefs.includes(bot.ref)).toBe(true)
|
|
486
|
+
})
|
|
244
487
|
})
|
|
@@ -7,6 +7,17 @@ import type {
|
|
|
7
7
|
RoomActivity,
|
|
8
8
|
} from 'webex-message-handler'
|
|
9
9
|
|
|
10
|
+
import type {
|
|
11
|
+
WebexAttachmentActionEvent,
|
|
12
|
+
WebexDeletedMessageEvent,
|
|
13
|
+
WebexMembership,
|
|
14
|
+
WebexMembershipEvent,
|
|
15
|
+
WebexMessage,
|
|
16
|
+
WebexMessageEvent,
|
|
17
|
+
WebexPerson,
|
|
18
|
+
WebexRoomEvent,
|
|
19
|
+
} from './types'
|
|
20
|
+
|
|
10
21
|
export { fromRestId }
|
|
11
22
|
|
|
12
23
|
// Superset of webex-message-handler's toRestId union, which omits ATTACHMENT_ACTION
|
|
@@ -20,7 +31,9 @@ export interface DecodedWebexId {
|
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
export function toRef(id: string): string {
|
|
23
|
-
|
|
34
|
+
// fromRestId throws on values that are not base64-encoded ciscospark ids; fail
|
|
35
|
+
// open so a non-REST id (legacy/sentinel) yields the id itself instead of crashing.
|
|
36
|
+
if (!id || !decodeWebexId(id)) return id
|
|
24
37
|
return fromRestId(id)
|
|
25
38
|
}
|
|
26
39
|
|
|
@@ -47,51 +60,118 @@ export function toRestId(uuid: string, type: WebexRestIdType): string {
|
|
|
47
60
|
return Buffer.from(`ciscospark://us/${type}/${uuid}`).toString('base64url')
|
|
48
61
|
}
|
|
49
62
|
|
|
50
|
-
export function normalizeMessage(message: DecryptedMessage):
|
|
63
|
+
export function normalizeMessage(message: DecryptedMessage): WebexMessageEvent {
|
|
64
|
+
const id = toRestId(message.id, 'MESSAGE')
|
|
65
|
+
const parentId = message.parentId ? toRestId(message.parentId, 'MESSAGE') : message.parentId
|
|
66
|
+
const roomId = toRestId(message.roomId, 'ROOM')
|
|
67
|
+
const personId = toRestId(message.personId, 'PEOPLE')
|
|
68
|
+
const mentionedPeople = message.mentionedPeople.map((person) => toRestId(person, 'PEOPLE'))
|
|
51
69
|
return {
|
|
52
70
|
...message,
|
|
53
|
-
id
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
id,
|
|
72
|
+
ref: toRef(id),
|
|
73
|
+
parentId,
|
|
74
|
+
parentRef: parentId ? toRef(parentId) : parentId,
|
|
75
|
+
roomId,
|
|
76
|
+
roomRef: toRef(roomId),
|
|
77
|
+
personId,
|
|
78
|
+
personRef: toRef(personId),
|
|
79
|
+
mentionedPeople,
|
|
80
|
+
mentionedPeopleRefs: mentionedPeople.map(toRef),
|
|
58
81
|
}
|
|
59
82
|
}
|
|
60
83
|
|
|
61
|
-
export function normalizeDeletedMessage(message: DeletedMessage):
|
|
84
|
+
export function normalizeDeletedMessage(message: DeletedMessage): WebexDeletedMessageEvent {
|
|
85
|
+
const messageId = toRestId(message.messageId, 'MESSAGE')
|
|
86
|
+
const roomId = toRestId(message.roomId, 'ROOM')
|
|
87
|
+
const personId = toRestId(message.personId, 'PEOPLE')
|
|
62
88
|
return {
|
|
63
|
-
messageId
|
|
64
|
-
|
|
65
|
-
|
|
89
|
+
messageId,
|
|
90
|
+
messageRef: toRef(messageId),
|
|
91
|
+
roomId,
|
|
92
|
+
roomRef: toRef(roomId),
|
|
93
|
+
personId,
|
|
94
|
+
personRef: toRef(personId),
|
|
66
95
|
}
|
|
67
96
|
}
|
|
68
97
|
|
|
69
|
-
export function normalizeMembership(activity: MembershipActivity):
|
|
70
|
-
// `id` stays raw: it is a Mercury activity UUID, not a REST membership ID
|
|
98
|
+
export function normalizeMembership(activity: MembershipActivity): WebexMembershipEvent {
|
|
99
|
+
// `id` stays raw: it is a Mercury activity UUID, not a REST membership ID, so
|
|
100
|
+
// its ref is the id itself rather than a decoded REST id.
|
|
101
|
+
const actorId = toRestId(activity.actorId, 'PEOPLE')
|
|
102
|
+
const personId = toRestId(activity.personId, 'PEOPLE')
|
|
103
|
+
const roomId = toRestId(activity.roomId, 'ROOM')
|
|
71
104
|
return {
|
|
72
105
|
...activity,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
106
|
+
ref: activity.id,
|
|
107
|
+
actorId,
|
|
108
|
+
actorRef: toRef(actorId),
|
|
109
|
+
personId,
|
|
110
|
+
personRef: toRef(personId),
|
|
111
|
+
roomId,
|
|
112
|
+
roomRef: toRef(roomId),
|
|
76
113
|
}
|
|
77
114
|
}
|
|
78
115
|
|
|
79
|
-
export function normalizeAttachmentAction(action: AttachmentAction):
|
|
116
|
+
export function normalizeAttachmentAction(action: AttachmentAction): WebexAttachmentActionEvent {
|
|
117
|
+
const id = toRestId(action.id, 'ATTACHMENT_ACTION')
|
|
118
|
+
const messageId = action.messageId ? toRestId(action.messageId, 'MESSAGE') : action.messageId
|
|
119
|
+
const personId = toRestId(action.personId, 'PEOPLE')
|
|
120
|
+
const roomId = toRestId(action.roomId, 'ROOM')
|
|
80
121
|
return {
|
|
81
122
|
...action,
|
|
82
|
-
id
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
123
|
+
id,
|
|
124
|
+
ref: toRef(id),
|
|
125
|
+
messageId,
|
|
126
|
+
messageRef: toRef(messageId),
|
|
127
|
+
personId,
|
|
128
|
+
personRef: toRef(personId),
|
|
129
|
+
roomId,
|
|
130
|
+
roomRef: toRef(roomId),
|
|
86
131
|
}
|
|
87
132
|
}
|
|
88
133
|
|
|
89
|
-
export function normalizeRoomActivity(activity: RoomActivity):
|
|
90
|
-
// `id` stays raw: the Mercury conversation activity UUID has no
|
|
91
|
-
//
|
|
134
|
+
export function normalizeRoomActivity(activity: RoomActivity): WebexRoomEvent {
|
|
135
|
+
// `id` stays raw: the Mercury conversation activity UUID has no consumer-facing
|
|
136
|
+
// REST resource, so its ref is the id itself (the comparable REST id is `roomId`).
|
|
137
|
+
const roomId = toRestId(activity.roomId, 'ROOM')
|
|
138
|
+
const actorId = toRestId(activity.actorId, 'PEOPLE')
|
|
92
139
|
return {
|
|
93
140
|
...activity,
|
|
94
|
-
|
|
95
|
-
|
|
141
|
+
ref: activity.id,
|
|
142
|
+
roomId,
|
|
143
|
+
roomRef: toRef(roomId),
|
|
144
|
+
actorId,
|
|
145
|
+
actorRef: toRef(actorId),
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// SDK REST responses (people/messages/memberships) already carry REST-encoded ids,
|
|
150
|
+
// so unlike the event normalizers above we only attach raw uuid refs — no re-encoding.
|
|
151
|
+
export function normalizeSdkPerson(person: WebexPerson): WebexPerson {
|
|
152
|
+
return {
|
|
153
|
+
...person,
|
|
154
|
+
ref: toRef(person.id),
|
|
155
|
+
orgRef: toRef(person.orgId),
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function normalizeSdkMessage(message: WebexMessage): WebexMessage {
|
|
160
|
+
return {
|
|
161
|
+
...message,
|
|
162
|
+
ref: toRef(message.id),
|
|
163
|
+
roomRef: toRef(message.roomId),
|
|
164
|
+
personRef: toRef(message.personId),
|
|
165
|
+
parentRef: message.parentId ? toRef(message.parentId) : message.parentId,
|
|
166
|
+
mentionedPeopleRefs: message.mentionedPeople?.map(toRef),
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function normalizeSdkMembership(membership: WebexMembership): WebexMembership {
|
|
171
|
+
return {
|
|
172
|
+
...membership,
|
|
173
|
+
ref: toRef(membership.id),
|
|
174
|
+
roomRef: toRef(membership.roomId),
|
|
175
|
+
personRef: toRef(membership.personId),
|
|
96
176
|
}
|
|
97
177
|
}
|
|
@@ -9,7 +9,19 @@ export type { PasswordLoginOptions, PasswordLoginResult } from './password-login
|
|
|
9
9
|
export { WebexTokenExtractor } from './token-extractor'
|
|
10
10
|
export type { ExtractedWebexToken } from './token-extractor'
|
|
11
11
|
export { WebexError } from './types'
|
|
12
|
-
export type {
|
|
12
|
+
export type {
|
|
13
|
+
WebexAttachmentActionEvent,
|
|
14
|
+
WebexConfig,
|
|
15
|
+
WebexDeletedMessageEvent,
|
|
16
|
+
WebexMembership,
|
|
17
|
+
WebexMembershipEvent,
|
|
18
|
+
WebexMessage,
|
|
19
|
+
WebexMessageEvent,
|
|
20
|
+
WebexPerson,
|
|
21
|
+
WebexRealtimeEvent,
|
|
22
|
+
WebexRoomEvent,
|
|
23
|
+
WebexSpace,
|
|
24
|
+
} from './types'
|
|
13
25
|
export {
|
|
14
26
|
WebexConfigSchema,
|
|
15
27
|
WebexMembershipSchema,
|
|
@@ -81,8 +81,11 @@ describe('WebexListener', () => {
|
|
|
81
81
|
|
|
82
82
|
const expected = expect.objectContaining({
|
|
83
83
|
id: toRestId('message-123', 'MESSAGE'),
|
|
84
|
+
ref: 'message-123',
|
|
84
85
|
roomId: toRestId('room-123', 'ROOM'),
|
|
86
|
+
roomRef: 'room-123',
|
|
85
87
|
personId: toRestId('person-123', 'PEOPLE'),
|
|
88
|
+
personRef: 'person-123',
|
|
86
89
|
personEmail: 'user@example.com',
|
|
87
90
|
text: 'hello',
|
|
88
91
|
raw: RAW_ACTIVITY,
|
|
@@ -21,6 +21,14 @@ import {
|
|
|
21
21
|
normalizeMessage,
|
|
22
22
|
normalizeRoomActivity,
|
|
23
23
|
} from './id-normalizer'
|
|
24
|
+
import type {
|
|
25
|
+
WebexAttachmentActionEvent,
|
|
26
|
+
WebexDeletedMessageEvent,
|
|
27
|
+
WebexMembershipEvent,
|
|
28
|
+
WebexMessageEvent,
|
|
29
|
+
WebexRealtimeEvent,
|
|
30
|
+
WebexRoomEvent,
|
|
31
|
+
} from './types'
|
|
24
32
|
import { createWdmRewriteFetch, discoverWdmDevicesUrl } from './wdm-discovery'
|
|
25
33
|
|
|
26
34
|
type EventKey = keyof WebexListenerEventMap
|
|
@@ -49,14 +57,14 @@ export interface WebexListenerOptions {
|
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
export interface WebexListenerEventMap {
|
|
52
|
-
message_created: [event:
|
|
53
|
-
message_updated: [event:
|
|
54
|
-
message_deleted: [event:
|
|
55
|
-
membership_created: [event:
|
|
56
|
-
attachment_action: [event:
|
|
57
|
-
room_created: [event:
|
|
58
|
-
room_updated: [event:
|
|
59
|
-
webex_event: [event:
|
|
60
|
+
message_created: [event: WebexMessageEvent]
|
|
61
|
+
message_updated: [event: WebexMessageEvent]
|
|
62
|
+
message_deleted: [event: WebexDeletedMessageEvent]
|
|
63
|
+
membership_created: [event: WebexMembershipEvent]
|
|
64
|
+
attachment_action: [event: WebexAttachmentActionEvent]
|
|
65
|
+
room_created: [event: WebexRoomEvent]
|
|
66
|
+
room_updated: [event: WebexRoomEvent]
|
|
67
|
+
webex_event: [event: WebexRealtimeEvent]
|
|
60
68
|
connected: [info: { connected: boolean; status: HandlerStatus }]
|
|
61
69
|
reconnecting: [attempt: number]
|
|
62
70
|
disconnected: [reason: string]
|