agent-messenger 2.23.2 → 2.23.3
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 +4 -0
- 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/types.d.ts +20 -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/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 +92 -21
- package/src/platforms/webex/listener.test.ts +3 -0
- package/src/platforms/webex/types.test.ts +20 -0
- package/src/platforms/webex/types.ts +20 -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/tui/adapters/webex-adapter.ts +2 -2
|
@@ -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,8 @@ import type {
|
|
|
7
7
|
RoomActivity,
|
|
8
8
|
} from 'webex-message-handler'
|
|
9
9
|
|
|
10
|
+
import type { WebexMembership, WebexMessage, WebexPerson } from './types'
|
|
11
|
+
|
|
10
12
|
export { fromRestId }
|
|
11
13
|
|
|
12
14
|
// Superset of webex-message-handler's toRestId union, which omits ATTACHMENT_ACTION
|
|
@@ -20,7 +22,9 @@ export interface DecodedWebexId {
|
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export function toRef(id: string): string {
|
|
23
|
-
|
|
25
|
+
// fromRestId throws on values that are not base64-encoded ciscospark ids; fail
|
|
26
|
+
// open so a non-REST id (legacy/sentinel) yields the id itself instead of crashing.
|
|
27
|
+
if (!id || !decodeWebexId(id)) return id
|
|
24
28
|
return fromRestId(id)
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -48,50 +52,117 @@ export function toRestId(uuid: string, type: WebexRestIdType): string {
|
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
export function normalizeMessage(message: DecryptedMessage): DecryptedMessage {
|
|
55
|
+
const id = toRestId(message.id, 'MESSAGE')
|
|
56
|
+
const parentId = message.parentId ? toRestId(message.parentId, 'MESSAGE') : message.parentId
|
|
57
|
+
const roomId = toRestId(message.roomId, 'ROOM')
|
|
58
|
+
const personId = toRestId(message.personId, 'PEOPLE')
|
|
59
|
+
const mentionedPeople = message.mentionedPeople.map((person) => toRestId(person, 'PEOPLE'))
|
|
51
60
|
return {
|
|
52
61
|
...message,
|
|
53
|
-
id
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
id,
|
|
63
|
+
ref: toRef(id),
|
|
64
|
+
parentId,
|
|
65
|
+
parentRef: parentId ? toRef(parentId) : parentId,
|
|
66
|
+
roomId,
|
|
67
|
+
roomRef: toRef(roomId),
|
|
68
|
+
personId,
|
|
69
|
+
personRef: toRef(personId),
|
|
70
|
+
mentionedPeople,
|
|
71
|
+
mentionedPeopleRefs: mentionedPeople.map(toRef),
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
|
|
61
75
|
export function normalizeDeletedMessage(message: DeletedMessage): DeletedMessage {
|
|
76
|
+
const messageId = toRestId(message.messageId, 'MESSAGE')
|
|
77
|
+
const roomId = toRestId(message.roomId, 'ROOM')
|
|
78
|
+
const personId = toRestId(message.personId, 'PEOPLE')
|
|
62
79
|
return {
|
|
63
|
-
messageId
|
|
64
|
-
|
|
65
|
-
|
|
80
|
+
messageId,
|
|
81
|
+
messageRef: toRef(messageId),
|
|
82
|
+
roomId,
|
|
83
|
+
roomRef: toRef(roomId),
|
|
84
|
+
personId,
|
|
85
|
+
personRef: toRef(personId),
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
88
|
|
|
69
89
|
export function normalizeMembership(activity: MembershipActivity): MembershipActivity {
|
|
70
|
-
// `id` stays raw: it is a Mercury activity UUID, not a REST membership ID
|
|
90
|
+
// `id` stays raw: it is a Mercury activity UUID, not a REST membership ID, so
|
|
91
|
+
// its ref is the id itself rather than a decoded REST id.
|
|
92
|
+
const actorId = toRestId(activity.actorId, 'PEOPLE')
|
|
93
|
+
const personId = toRestId(activity.personId, 'PEOPLE')
|
|
94
|
+
const roomId = toRestId(activity.roomId, 'ROOM')
|
|
71
95
|
return {
|
|
72
96
|
...activity,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
97
|
+
ref: activity.id,
|
|
98
|
+
actorId,
|
|
99
|
+
actorRef: toRef(actorId),
|
|
100
|
+
personId,
|
|
101
|
+
personRef: toRef(personId),
|
|
102
|
+
roomId,
|
|
103
|
+
roomRef: toRef(roomId),
|
|
76
104
|
}
|
|
77
105
|
}
|
|
78
106
|
|
|
79
107
|
export function normalizeAttachmentAction(action: AttachmentAction): AttachmentAction {
|
|
108
|
+
const id = toRestId(action.id, 'ATTACHMENT_ACTION')
|
|
109
|
+
const messageId = action.messageId ? toRestId(action.messageId, 'MESSAGE') : action.messageId
|
|
110
|
+
const personId = toRestId(action.personId, 'PEOPLE')
|
|
111
|
+
const roomId = toRestId(action.roomId, 'ROOM')
|
|
80
112
|
return {
|
|
81
113
|
...action,
|
|
82
|
-
id
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
114
|
+
id,
|
|
115
|
+
ref: toRef(id),
|
|
116
|
+
messageId,
|
|
117
|
+
messageRef: toRef(messageId),
|
|
118
|
+
personId,
|
|
119
|
+
personRef: toRef(personId),
|
|
120
|
+
roomId,
|
|
121
|
+
roomRef: toRef(roomId),
|
|
86
122
|
}
|
|
87
123
|
}
|
|
88
124
|
|
|
89
125
|
export function normalizeRoomActivity(activity: RoomActivity): RoomActivity {
|
|
90
|
-
// `id` stays raw: the Mercury conversation activity UUID has no
|
|
91
|
-
//
|
|
126
|
+
// `id` stays raw: the Mercury conversation activity UUID has no consumer-facing
|
|
127
|
+
// REST resource, so its ref is the id itself (the comparable REST id is `roomId`).
|
|
128
|
+
const roomId = toRestId(activity.roomId, 'ROOM')
|
|
129
|
+
const actorId = toRestId(activity.actorId, 'PEOPLE')
|
|
92
130
|
return {
|
|
93
131
|
...activity,
|
|
94
|
-
|
|
95
|
-
|
|
132
|
+
ref: activity.id,
|
|
133
|
+
roomId,
|
|
134
|
+
roomRef: toRef(roomId),
|
|
135
|
+
actorId,
|
|
136
|
+
actorRef: toRef(actorId),
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// SDK REST responses (people/messages/memberships) already carry REST-encoded ids,
|
|
141
|
+
// so unlike the event normalizers above we only attach raw uuid refs — no re-encoding.
|
|
142
|
+
export function normalizeSdkPerson(person: WebexPerson): WebexPerson {
|
|
143
|
+
return {
|
|
144
|
+
...person,
|
|
145
|
+
ref: toRef(person.id),
|
|
146
|
+
orgRef: toRef(person.orgId),
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function normalizeSdkMessage(message: WebexMessage): WebexMessage {
|
|
151
|
+
return {
|
|
152
|
+
...message,
|
|
153
|
+
ref: toRef(message.id),
|
|
154
|
+
roomRef: toRef(message.roomId),
|
|
155
|
+
personRef: toRef(message.personId),
|
|
156
|
+
parentRef: message.parentId ? toRef(message.parentId) : message.parentId,
|
|
157
|
+
mentionedPeopleRefs: message.mentionedPeople?.map(toRef),
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function normalizeSdkMembership(membership: WebexMembership): WebexMembership {
|
|
162
|
+
return {
|
|
163
|
+
...membership,
|
|
164
|
+
ref: toRef(membership.id),
|
|
165
|
+
roomRef: toRef(membership.roomId),
|
|
166
|
+
personRef: toRef(membership.personId),
|
|
96
167
|
}
|
|
97
168
|
}
|
|
@@ -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,
|
|
@@ -73,10 +73,13 @@ it('WebexSpaceSchema rejects invalid type', () => {
|
|
|
73
73
|
it('WebexMessageSchema validates valid message', () => {
|
|
74
74
|
const result = WebexMessageSchema.safeParse({
|
|
75
75
|
id: 'Y2lzY29zcGFyazovL3VzL01FU1NBR0UvbXNn',
|
|
76
|
+
ref: 'msg',
|
|
76
77
|
roomId: 'Y2lzY29zcGFyazovL3VzL1JPT00vYWJj',
|
|
78
|
+
roomRef: 'abc',
|
|
77
79
|
roomType: 'group',
|
|
78
80
|
text: 'Hello world',
|
|
79
81
|
personId: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
82
|
+
personRef: 'abc',
|
|
80
83
|
personEmail: 'user@example.com',
|
|
81
84
|
created: '2024-01-15T10:30:00.000Z',
|
|
82
85
|
})
|
|
@@ -86,17 +89,22 @@ it('WebexMessageSchema validates valid message', () => {
|
|
|
86
89
|
it('WebexMessageSchema validates message with optional fields', () => {
|
|
87
90
|
const result = WebexMessageSchema.safeParse({
|
|
88
91
|
id: 'Y2lzY29zcGFyazovL3VzL01FU1NBR0UvbXNn',
|
|
92
|
+
ref: 'msg',
|
|
89
93
|
roomId: 'Y2lzY29zcGFyazovL3VzL1JPT00vYWJj',
|
|
94
|
+
roomRef: 'abc',
|
|
90
95
|
roomType: 'group',
|
|
91
96
|
text: 'Hello world',
|
|
92
97
|
markdown: '**Hello world**',
|
|
93
98
|
html: '<strong>Hello world</strong>',
|
|
94
99
|
files: ['https://webexapis.com/v1/contents/file1'],
|
|
95
100
|
personId: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
101
|
+
personRef: 'abc',
|
|
96
102
|
personEmail: 'user@example.com',
|
|
97
103
|
created: '2024-01-15T10:30:00.000Z',
|
|
98
104
|
parentId: 'Y2lzY29zcGFyazovL3VzL01FU1NBR0UvcGFyZW50',
|
|
105
|
+
parentRef: 'parent',
|
|
99
106
|
mentionedPeople: ['Y2lzY29zcGFyazovL3VzL1BFT1BMRS9tZW50aW9u'],
|
|
107
|
+
mentionedPeopleRefs: ['mention'],
|
|
100
108
|
})
|
|
101
109
|
expect(result.success).toBe(true)
|
|
102
110
|
})
|
|
@@ -125,9 +133,11 @@ it('WebexMessageSchema rejects invalid roomType', () => {
|
|
|
125
133
|
it('WebexPersonSchema validates valid person', () => {
|
|
126
134
|
const result = WebexPersonSchema.safeParse({
|
|
127
135
|
id: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
136
|
+
ref: 'abc',
|
|
128
137
|
emails: ['user@example.com'],
|
|
129
138
|
displayName: 'Test User',
|
|
130
139
|
orgId: 'Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVElPTi9vcmc',
|
|
140
|
+
orgRef: 'org',
|
|
131
141
|
type: 'person',
|
|
132
142
|
created: '2024-01-01T00:00:00.000Z',
|
|
133
143
|
})
|
|
@@ -137,6 +147,7 @@ it('WebexPersonSchema validates valid person', () => {
|
|
|
137
147
|
it('WebexPersonSchema validates person with optional fields', () => {
|
|
138
148
|
const result = WebexPersonSchema.safeParse({
|
|
139
149
|
id: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
150
|
+
ref: 'abc',
|
|
140
151
|
emails: ['user@example.com', 'user@work.com'],
|
|
141
152
|
displayName: 'Test User',
|
|
142
153
|
nickName: 'Tester',
|
|
@@ -144,6 +155,7 @@ it('WebexPersonSchema validates person with optional fields', () => {
|
|
|
144
155
|
lastName: 'User',
|
|
145
156
|
avatar: 'https://example.com/avatar.jpg',
|
|
146
157
|
orgId: 'Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVElPTi9vcmc',
|
|
158
|
+
orgRef: 'org',
|
|
147
159
|
type: 'person',
|
|
148
160
|
created: '2024-01-01T00:00:00.000Z',
|
|
149
161
|
})
|
|
@@ -153,9 +165,11 @@ it('WebexPersonSchema validates person with optional fields', () => {
|
|
|
153
165
|
it('WebexPersonSchema validates bot type', () => {
|
|
154
166
|
const result = WebexPersonSchema.safeParse({
|
|
155
167
|
id: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9ib3Q',
|
|
168
|
+
ref: 'bot',
|
|
156
169
|
emails: ['bot@webex.bot'],
|
|
157
170
|
displayName: 'My Bot',
|
|
158
171
|
orgId: 'Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVElPTi9vcmc',
|
|
172
|
+
orgRef: 'org',
|
|
159
173
|
type: 'bot',
|
|
160
174
|
created: '2024-01-01T00:00:00.000Z',
|
|
161
175
|
})
|
|
@@ -185,8 +199,11 @@ it('WebexPersonSchema rejects invalid type', () => {
|
|
|
185
199
|
it('WebexMembershipSchema validates valid membership', () => {
|
|
186
200
|
const result = WebexMembershipSchema.safeParse({
|
|
187
201
|
id: 'Y2lzY29zcGFyazovL3VzL01FTUJFUlNISVAvbWVt',
|
|
202
|
+
ref: 'mem',
|
|
188
203
|
roomId: 'Y2lzY29zcGFyazovL3VzL1JPT00vYWJj',
|
|
204
|
+
roomRef: 'abc',
|
|
189
205
|
personId: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
206
|
+
personRef: 'abc',
|
|
190
207
|
personEmail: 'user@example.com',
|
|
191
208
|
personDisplayName: 'Test User',
|
|
192
209
|
isModerator: false,
|
|
@@ -198,8 +215,11 @@ it('WebexMembershipSchema validates valid membership', () => {
|
|
|
198
215
|
it('WebexMembershipSchema validates moderator membership', () => {
|
|
199
216
|
const result = WebexMembershipSchema.safeParse({
|
|
200
217
|
id: 'Y2lzY29zcGFyazovL3VzL01FTUJFUlNISVAvbWVt',
|
|
218
|
+
ref: 'mem',
|
|
201
219
|
roomId: 'Y2lzY29zcGFyazovL3VzL1JPT00vYWJj',
|
|
220
|
+
roomRef: 'abc',
|
|
202
221
|
personId: 'Y2lzY29zcGFyazovL3VzL1BFT1BMRS9hYmM',
|
|
222
|
+
personRef: 'abc',
|
|
203
223
|
personEmail: 'moderator@example.com',
|
|
204
224
|
personDisplayName: 'Moderator User',
|
|
205
225
|
isModerator: true,
|
|
@@ -13,21 +13,27 @@ export interface WebexSpace {
|
|
|
13
13
|
|
|
14
14
|
export interface WebexMessage {
|
|
15
15
|
id: string
|
|
16
|
+
ref: string
|
|
16
17
|
roomId: string
|
|
18
|
+
roomRef: string
|
|
17
19
|
roomType: 'group' | 'direct'
|
|
18
20
|
text?: string
|
|
19
21
|
markdown?: string
|
|
20
22
|
html?: string
|
|
21
23
|
files?: string[]
|
|
22
24
|
personId: string
|
|
25
|
+
personRef: string
|
|
23
26
|
personEmail: string
|
|
24
27
|
created: string
|
|
25
28
|
parentId?: string
|
|
29
|
+
parentRef?: string
|
|
26
30
|
mentionedPeople?: string[]
|
|
31
|
+
mentionedPeopleRefs?: string[]
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
export interface WebexPerson {
|
|
30
35
|
id: string
|
|
36
|
+
ref: string
|
|
31
37
|
emails: string[]
|
|
32
38
|
displayName: string
|
|
33
39
|
nickName?: string
|
|
@@ -35,14 +41,18 @@ export interface WebexPerson {
|
|
|
35
41
|
lastName?: string
|
|
36
42
|
avatar?: string
|
|
37
43
|
orgId: string
|
|
44
|
+
orgRef: string
|
|
38
45
|
type: 'person' | 'bot'
|
|
39
46
|
created: string
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
export interface WebexMembership {
|
|
43
50
|
id: string
|
|
51
|
+
ref: string
|
|
44
52
|
roomId: string
|
|
53
|
+
roomRef: string
|
|
45
54
|
personId: string
|
|
55
|
+
personRef: string
|
|
46
56
|
personEmail: string
|
|
47
57
|
personDisplayName: string
|
|
48
58
|
isModerator: boolean
|
|
@@ -84,21 +94,27 @@ export const WebexSpaceSchema = z.object({
|
|
|
84
94
|
|
|
85
95
|
export const WebexMessageSchema = z.object({
|
|
86
96
|
id: z.string(),
|
|
97
|
+
ref: z.string(),
|
|
87
98
|
roomId: z.string(),
|
|
99
|
+
roomRef: z.string(),
|
|
88
100
|
roomType: z.enum(['group', 'direct']),
|
|
89
101
|
text: z.string().optional(),
|
|
90
102
|
markdown: z.string().optional(),
|
|
91
103
|
html: z.string().optional(),
|
|
92
104
|
files: z.array(z.string()).optional(),
|
|
93
105
|
personId: z.string(),
|
|
106
|
+
personRef: z.string(),
|
|
94
107
|
personEmail: z.string(),
|
|
95
108
|
created: z.string(),
|
|
96
109
|
parentId: z.string().optional(),
|
|
110
|
+
parentRef: z.string().optional(),
|
|
97
111
|
mentionedPeople: z.array(z.string()).optional(),
|
|
112
|
+
mentionedPeopleRefs: z.array(z.string()).optional(),
|
|
98
113
|
})
|
|
99
114
|
|
|
100
115
|
export const WebexPersonSchema = z.object({
|
|
101
116
|
id: z.string(),
|
|
117
|
+
ref: z.string(),
|
|
102
118
|
emails: z.array(z.string()),
|
|
103
119
|
displayName: z.string(),
|
|
104
120
|
nickName: z.string().optional(),
|
|
@@ -106,14 +122,18 @@ export const WebexPersonSchema = z.object({
|
|
|
106
122
|
lastName: z.string().optional(),
|
|
107
123
|
avatar: z.string().optional(),
|
|
108
124
|
orgId: z.string(),
|
|
125
|
+
orgRef: z.string(),
|
|
109
126
|
type: z.enum(['person', 'bot']),
|
|
110
127
|
created: z.string(),
|
|
111
128
|
})
|
|
112
129
|
|
|
113
130
|
export const WebexMembershipSchema = z.object({
|
|
114
131
|
id: z.string(),
|
|
132
|
+
ref: z.string(),
|
|
115
133
|
roomId: z.string(),
|
|
134
|
+
roomRef: z.string(),
|
|
116
135
|
personId: z.string(),
|
|
136
|
+
personRef: z.string(),
|
|
117
137
|
personEmail: z.string(),
|
|
118
138
|
personDisplayName: z.string(),
|
|
119
139
|
isModerator: z.boolean(),
|