@undefineds.co/xpod 0.3.48 → 0.3.49

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 (105) hide show
  1. package/bin/xpod.js +0 -0
  2. package/dist/api/chatkit/pod-store.d.ts +16 -17
  3. package/dist/api/chatkit/pod-store.js +299 -231
  4. package/dist/api/chatkit/pod-store.js.map +1 -1
  5. package/dist/api/chatkit/schema.d.ts +1 -1
  6. package/dist/api/chatkit/service.js +13 -11
  7. package/dist/api/chatkit/service.js.map +1 -1
  8. package/dist/api/chatkit/store.d.ts +1 -0
  9. package/dist/api/chatkit/store.js +23 -11
  10. package/dist/api/chatkit/store.js.map +1 -1
  11. package/dist/api/chatkit/types.d.ts +17 -10
  12. package/dist/api/chatkit/types.js +97 -14
  13. package/dist/api/chatkit/types.js.map +1 -1
  14. package/dist/api/container/common.js +16 -2
  15. package/dist/api/container/common.js.map +1 -1
  16. package/dist/api/container/routes.js +3 -0
  17. package/dist/api/container/routes.js.map +1 -1
  18. package/dist/api/container/types.d.ts +3 -0
  19. package/dist/api/container/types.js.map +1 -1
  20. package/dist/api/handlers/ChatKitV1Handler.js +1 -2
  21. package/dist/api/handlers/ChatKitV1Handler.js.map +1 -1
  22. package/dist/api/handlers/CoordinationHandler.d.ts +6 -0
  23. package/dist/api/handlers/CoordinationHandler.js +115 -0
  24. package/dist/api/handlers/CoordinationHandler.js.map +1 -0
  25. package/dist/api/handlers/MatrixHandler.d.ts +11 -0
  26. package/dist/api/handlers/MatrixHandler.js +120 -2
  27. package/dist/api/handlers/MatrixHandler.js.map +1 -1
  28. package/dist/api/handlers/RunHandler.js +33 -15
  29. package/dist/api/handlers/RunHandler.js.map +1 -1
  30. package/dist/api/handlers/index.d.ts +1 -0
  31. package/dist/api/handlers/index.js +1 -0
  32. package/dist/api/handlers/index.js.map +1 -1
  33. package/dist/api/index.d.ts +1 -0
  34. package/dist/api/index.js +1 -0
  35. package/dist/api/index.js.map +1 -1
  36. package/dist/api/matrix/PodMatrixStore.d.ts +25 -1
  37. package/dist/api/matrix/PodMatrixStore.js +243 -38
  38. package/dist/api/matrix/PodMatrixStore.js.map +1 -1
  39. package/dist/api/matrix/index.d.ts +1 -1
  40. package/dist/api/matrix/index.js.map +1 -1
  41. package/dist/api/matrix/types.d.ts +23 -2
  42. package/dist/api/matrix/types.js.map +1 -1
  43. package/dist/api/protocol-metadata.d.ts +4 -0
  44. package/dist/api/protocol-metadata.js +54 -0
  45. package/dist/api/protocol-metadata.js.map +1 -0
  46. package/dist/api/reconciler/ClientReconcilerCoordinator.d.ts +42 -0
  47. package/dist/api/reconciler/ClientReconcilerCoordinator.js +250 -0
  48. package/dist/api/reconciler/ClientReconcilerCoordinator.js.map +1 -0
  49. package/dist/api/reconciler/ClientReconcilerCoordinator.jsonld +186 -0
  50. package/dist/api/reconciler/ServerGroupReconcilerService.d.ts +39 -0
  51. package/dist/api/reconciler/ServerGroupReconcilerService.js +91 -0
  52. package/dist/api/reconciler/ServerGroupReconcilerService.js.map +1 -0
  53. package/dist/api/reconciler/ServerGroupReconcilerService.jsonld +146 -0
  54. package/dist/api/reconciler/WakeAgentQueue.d.ts +23 -0
  55. package/dist/api/reconciler/WakeAgentQueue.js +123 -0
  56. package/dist/api/reconciler/WakeAgentQueue.js.map +1 -0
  57. package/dist/api/reconciler/WakeAgentQueue.jsonld +91 -0
  58. package/dist/api/reconciler/coordination.d.ts +61 -0
  59. package/dist/api/reconciler/coordination.js +109 -0
  60. package/dist/api/reconciler/coordination.js.map +1 -0
  61. package/dist/api/reconciler/coordination.jsonld +186 -0
  62. package/dist/api/reconciler/index.d.ts +4 -0
  63. package/dist/api/reconciler/index.js +21 -0
  64. package/dist/api/reconciler/index.js.map +1 -0
  65. package/dist/api/runs/ManagedRunWorker.js +0 -5
  66. package/dist/api/runs/ManagedRunWorker.js.map +1 -1
  67. package/dist/api/runs/RunStateCenter.d.ts +1 -1
  68. package/dist/api/runs/RunStateCenter.js +12 -28
  69. package/dist/api/runs/RunStateCenter.js.map +1 -1
  70. package/dist/api/runs/store.d.ts +12 -15
  71. package/dist/api/runs/store.js +24 -15
  72. package/dist/api/runs/store.js.map +1 -1
  73. package/dist/api/tasks/TaskMaterializer.d.ts +1 -0
  74. package/dist/api/tasks/TaskMaterializer.js +10 -13
  75. package/dist/api/tasks/TaskMaterializer.js.map +1 -1
  76. package/dist/api/tasks/TaskService.d.ts +0 -2
  77. package/dist/api/tasks/TaskService.js +6 -16
  78. package/dist/api/tasks/TaskService.js.map +1 -1
  79. package/dist/api/tasks/store.d.ts +0 -2
  80. package/dist/api/tasks/store.js.map +1 -1
  81. package/dist/cli/commands/auth.d.ts +1 -1
  82. package/dist/cli/commands/auth.js +4 -5
  83. package/dist/cli/commands/auth.js.map +1 -1
  84. package/dist/cli/commands/backup.js +1 -1
  85. package/dist/cli/commands/backup.js.map +1 -1
  86. package/dist/cli/commands/login.js +1 -1
  87. package/dist/cli/commands/login.js.map +1 -1
  88. package/dist/cli/commands/pod.js +1 -1
  89. package/dist/cli/commands/pod.js.map +1 -1
  90. package/dist/cli/lib/auth-helper.d.ts +5 -3
  91. package/dist/cli/lib/auth-helper.js +5 -3
  92. package/dist/cli/lib/auth-helper.js.map +1 -1
  93. package/dist/cli/lib/credentials-store.d.ts +22 -4
  94. package/dist/cli/lib/credentials-store.js +68 -51
  95. package/dist/cli/lib/credentials-store.js.map +1 -1
  96. package/dist/components/components.jsonld +5 -1
  97. package/dist/components/context.jsonld +103 -0
  98. package/dist/index.d.ts +1 -0
  99. package/dist/index.js +15 -0
  100. package/dist/index.js.map +1 -1
  101. package/dist/provision/LocalPodProvisioningService.d.ts +1 -0
  102. package/dist/provision/LocalPodProvisioningService.js +9 -0
  103. package/dist/provision/LocalPodProvisioningService.js.map +1 -1
  104. package/dist/provision/LocalPodProvisioningService.jsonld +4 -0
  105. package/package.json +2 -2
@@ -2,8 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PodMatrixStore = void 0;
4
4
  const node_crypto_1 = require("node:crypto");
5
+ const global_logger_factory_1 = require("global-logger-factory");
5
6
  const drizzle_solid_1 = require("@undefineds.co/drizzle-solid");
6
7
  const models_1 = require("@undefineds.co/models");
8
+ const reconciler_1 = require("../reconciler");
9
+ const protocol_metadata_1 = require("../protocol-metadata");
7
10
  const AuthContext_1 = require("../auth/AuthContext");
8
11
  const schema = {
9
12
  chat: models_1.chatResource,
@@ -12,7 +15,17 @@ const schema = {
12
15
  };
13
16
  class PodMatrixStore {
14
17
  constructor(options) {
18
+ this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
15
19
  this.serverName = options.serverName;
20
+ this.serverGroupReconcilerService = options.serverGroupReconcilerService;
21
+ }
22
+ async getAccount(context) {
23
+ const matrixUserId = this.getMatrixUserId(context);
24
+ return {
25
+ userId: matrixUserId,
26
+ deviceId: this.deviceIdFromUserId(context.webId),
27
+ displayName: this.displayNameFromUserId(matrixUserId),
28
+ };
16
29
  }
17
30
  async createRoom(input, context) {
18
31
  const db = await this.getDb(context);
@@ -21,45 +34,48 @@ class PodMatrixStore {
21
34
  const roomId = this.generateRoomId(context);
22
35
  const chatId = this.chatResourceIdFromRoomId(roomId);
23
36
  const threadId = this.threadResourceIdFromRoomId(roomId);
37
+ const reconcilerOwner = 'server';
38
+ const coordination = (0, reconciler_1.reconcilerCoordinationMetadata)(reconcilerOwner);
24
39
  await db.insert(models_1.chatResource).values({
25
40
  id: chatId,
26
41
  title: input.name ?? roomId,
27
42
  description: input.topic ?? null,
28
- author: context.userId,
43
+ author: context.webId,
29
44
  status: 'active',
30
- participants: [context.userId],
31
- metadata: {
45
+ participants: [context.webId],
46
+ metadata: (0, protocol_metadata_1.withProtocolMetadata)({
32
47
  protocol: 'matrix',
48
+ ...coordination,
49
+ }, 'matrix', {
33
50
  roomId,
34
51
  canonicalAlias: input.room_alias_name ? `#${input.room_alias_name}:${this.getServerName(context)}` : null,
35
52
  visibility: input.visibility === 'public' ? 'public' : 'private',
36
53
  roomVersion: String(input.creation_content?.room_version ?? '11'),
37
54
  federate: input.creation_content?.['m.federate'] === true,
38
- members: [context.userId],
55
+ members: [context.webId],
39
56
  preset: input.preset,
40
- is_direct: input.is_direct,
41
57
  invite: input.invite ?? [],
42
- },
58
+ }),
43
59
  createdAt: new Date(now).toISOString(),
44
60
  updatedAt: new Date(now).toISOString(),
45
61
  });
46
62
  await db.insert(models_1.threadResource).values({
47
63
  id: threadId,
48
- chat: chatId,
64
+ parent: this.chatParentRefFromRoomId(roomId),
49
65
  title: input.name ?? roomId,
50
66
  status: 'active',
51
- metadata: {
67
+ metadata: (0, protocol_metadata_1.withProtocolMetadata)({
52
68
  protocol: 'matrix',
53
- roomId,
54
69
  commandKind: 'chat',
55
70
  surface_id: this.surfaceIdFromRoomId(roomId),
56
- chat_id: this.surfaceIdFromRoomId(roomId),
57
- },
71
+ ...coordination,
72
+ }, 'matrix', { roomId }),
58
73
  createdAt: new Date(now).toISOString(),
59
74
  updatedAt: new Date(now).toISOString(),
60
75
  });
61
76
  await this.appendEvent(db, {
62
77
  roomId,
78
+ reconcilerOwner,
63
79
  type: 'm.room.create',
64
80
  sender,
65
81
  originServerTs: now,
@@ -73,6 +89,7 @@ class PodMatrixStore {
73
89
  }, context);
74
90
  await this.appendEvent(db, {
75
91
  roomId,
92
+ reconcilerOwner,
76
93
  type: 'm.room.member',
77
94
  sender,
78
95
  originServerTs: now + 1,
@@ -85,6 +102,7 @@ class PodMatrixStore {
85
102
  if (input.name) {
86
103
  await this.appendEvent(db, {
87
104
  roomId,
105
+ reconcilerOwner,
88
106
  type: 'm.room.name',
89
107
  sender,
90
108
  originServerTs: now + 2,
@@ -95,6 +113,7 @@ class PodMatrixStore {
95
113
  if (input.topic) {
96
114
  await this.appendEvent(db, {
97
115
  roomId,
116
+ reconcilerOwner,
98
117
  type: 'm.room.topic',
99
118
  sender,
100
119
  originServerTs: now + 3,
@@ -105,6 +124,7 @@ class PodMatrixStore {
105
124
  for (const state of input.initial_state ?? []) {
106
125
  await this.appendEvent(db, {
107
126
  roomId,
127
+ reconcilerOwner,
108
128
  type: state.type,
109
129
  sender,
110
130
  originServerTs: Date.now(),
@@ -112,14 +132,40 @@ class PodMatrixStore {
112
132
  content: state.content ?? {},
113
133
  }, context);
114
134
  }
135
+ for (const invitee of input.invite ?? []) {
136
+ await this.appendMembershipEvent(db, roomId, invitee, 'invite', context, { sender, reconcilerOwner });
137
+ }
115
138
  return {
116
139
  roomId,
140
+ canonicalAlias: input.room_alias_name ? `#${input.room_alias_name}:${this.getServerName(context)}` : undefined,
117
141
  name: input.name,
118
142
  topic: input.topic,
119
143
  creator: sender,
144
+ reconcilerOwner: coordination.reconcilerOwner,
120
145
  createdAt: now,
121
146
  };
122
147
  }
148
+ async joinRoom(roomIdOrAlias, context) {
149
+ const db = await this.getDb(context);
150
+ const roomId = await this.resolveRoomId(db, roomIdOrAlias);
151
+ await this.ensureRoomExists(db, roomId);
152
+ const sender = this.getMatrixUserId(context);
153
+ const existing = await this.findLatestStateEvent(db, roomId, 'm.room.member', sender, context);
154
+ if (existing?.content.membership !== 'join') {
155
+ await this.appendMembershipEvent(db, roomId, sender, 'join', context);
156
+ }
157
+ return { roomId };
158
+ }
159
+ async inviteUser(roomId, userId, context) {
160
+ const db = await this.getDb(context);
161
+ await this.ensureRoomExists(db, roomId);
162
+ await this.appendMembershipEvent(db, roomId, userId, 'invite', context);
163
+ }
164
+ async leaveRoom(roomId, context) {
165
+ const db = await this.getDb(context);
166
+ await this.ensureRoomExists(db, roomId);
167
+ await this.appendMembershipEvent(db, roomId, this.getMatrixUserId(context), 'leave', context);
168
+ }
123
169
  async sendEvent(roomId, eventType, txnId, content, context) {
124
170
  const db = await this.getDb(context);
125
171
  await this.ensureRoomExists(db, roomId);
@@ -138,9 +184,21 @@ class PodMatrixStore {
138
184
  }, context);
139
185
  return event;
140
186
  }
187
+ async setState(roomId, eventType, stateKey, content, context) {
188
+ const db = await this.getDb(context);
189
+ await this.ensureRoomExists(db, roomId);
190
+ return this.appendEvent(db, {
191
+ roomId,
192
+ type: eventType,
193
+ sender: this.getMatrixUserId(context),
194
+ stateKey,
195
+ originServerTs: Date.now(),
196
+ content,
197
+ }, context);
198
+ }
141
199
  async sync(context, options = {}) {
142
200
  const db = await this.getDb(context);
143
- const rooms = await this.listRooms(db);
201
+ const rooms = await this.listJoinedRoomRecords(db, context);
144
202
  const sinceTs = this.parseSyncToken(options.since);
145
203
  const limit = options.limit && options.limit > 0 ? options.limit : 50;
146
204
  const join = {};
@@ -157,6 +215,9 @@ class PodMatrixStore {
157
215
  events: events.map((event) => this.toClientEvent(event)),
158
216
  limited: false,
159
217
  },
218
+ 'co.undefineds.coordination': {
219
+ reconcilerOwner: room.reconcilerOwner,
220
+ },
160
221
  };
161
222
  }
162
223
  return {
@@ -164,6 +225,25 @@ class PodMatrixStore {
164
225
  rooms: { join },
165
226
  };
166
227
  }
228
+ async listJoinedRooms(context) {
229
+ const db = await this.getDb(context);
230
+ return (await this.listJoinedRoomRecords(db, context)).map((room) => room.roomId);
231
+ }
232
+ async getMembers(roomId, context) {
233
+ const db = await this.getDb(context);
234
+ await this.ensureRoomExists(db, roomId);
235
+ const events = await this.listEvents(db, roomId, context, { newestFirst: true });
236
+ const latestByStateKey = new Map();
237
+ for (const event of events) {
238
+ if (event.type !== 'm.room.member' || event.stateKey === undefined || latestByStateKey.has(event.stateKey)) {
239
+ continue;
240
+ }
241
+ latestByStateKey.set(event.stateKey, event);
242
+ }
243
+ return Array.from(latestByStateKey.values())
244
+ .sort((left, right) => (left.originServerTs - right.originServerTs) || ((left.depth ?? 0) - (right.depth ?? 0)))
245
+ .map((event) => this.toClientEvent(event));
246
+ }
167
247
  async listMessages(roomId, context, options = {}) {
168
248
  const db = await this.getDb(context);
169
249
  await this.ensureRoomExists(db, roomId);
@@ -235,12 +315,23 @@ class PodMatrixStore {
235
315
  const eventId = this.generateEventId(context);
236
316
  const depth = await this.nextEventDepth(db, input.roomId, context);
237
317
  const originIso = new Date(input.originServerTs).toISOString();
318
+ const needsRoomMetadata = input.reconcilerOwner === undefined
319
+ || (input.type === 'm.room.message' && this.serverGroupReconcilerService !== undefined);
320
+ const roomContext = needsRoomMetadata ? await this.getRoomContext(db, input.roomId) : undefined;
321
+ const roomMetadata = roomContext?.metadata;
322
+ const reconcilerOwner = input.reconcilerOwner ?? this.reconcilerOwnerFromRoomMetadata(roomMetadata);
323
+ const coordination = (0, reconciler_1.reconcilerCoordinationMetadata)(reconcilerOwner);
324
+ const messageResourceId = this.messageResourceIdFromEvent(input.roomId, eventId, input.originServerTs);
325
+ const thread = this.resolveDataResourceUriFromId(this.threadResourceIdFromRoomId(input.roomId), context);
326
+ const contentText = this.messageContentFromMatrixEvent(input.type, input.content);
327
+ const mentions = this.mentionsFromMatrixContent(input.content);
328
+ const routeTargetAgent = this.routeTargetAgentFromMatrixContent(input.content);
238
329
  const record = {
239
330
  eventId,
240
331
  roomId: input.roomId,
241
332
  type: input.type,
242
333
  sender: input.sender,
243
- senderWebId: context.userId,
334
+ senderWebId: context.webId,
244
335
  originServerTs: input.originServerTs,
245
336
  depth,
246
337
  txnId: input.txnId ?? undefined,
@@ -249,40 +340,93 @@ class PodMatrixStore {
249
340
  createdAt: originIso,
250
341
  };
251
342
  await db.insert(models_1.messageResource).values({
252
- id: this.messageResourceIdFromEvent(input.roomId, eventId, input.originServerTs),
343
+ id: messageResourceId,
344
+ parent: this.resolveDataResourceUriFromId(this.messageParentResourceIdFromRoomId(input.roomId), context),
253
345
  chat: this.chatResourceIdFromRoomId(input.roomId),
254
- thread: this.resolveDataResourceUriFromId(this.threadResourceIdFromRoomId(input.roomId), context),
255
- maker: context.userId,
346
+ thread,
347
+ maker: context.webId,
256
348
  role: input.type === 'm.room.message' ? models_1.MessageRole.USER : models_1.MessageRole.SYSTEM,
257
- content: this.messageContentFromMatrixEvent(input.type, input.content),
349
+ content: contentText,
258
350
  status: models_1.MessageStatus.SENT,
259
- metadata: {
351
+ mentions,
352
+ routeTargetAgent: routeTargetAgent ?? null,
353
+ metadata: (0, protocol_metadata_1.withProtocolMetadata)({
260
354
  protocol: 'matrix',
355
+ commandKind: 'chat',
356
+ surface_id: this.surfaceIdFromRoomId(input.roomId),
357
+ ...coordination,
358
+ }, 'matrix', {
261
359
  eventId,
262
360
  roomId: input.roomId,
263
361
  eventType: input.type,
264
362
  sender: input.sender,
265
- senderWebId: context.userId,
363
+ senderWebId: context.webId,
266
364
  originServerTs: input.originServerTs,
267
365
  depth,
268
366
  txnId: input.txnId ?? null,
269
367
  stateKey: input.stateKey ?? null,
270
368
  content: input.content,
271
- commandKind: 'chat',
272
- surface_id: this.surfaceIdFromRoomId(input.roomId),
273
- chat_id: this.surfaceIdFromRoomId(input.roomId),
274
- },
369
+ }),
275
370
  createdAt: originIso,
276
371
  updatedAt: originIso,
277
372
  });
373
+ await this.reconcileGroupUserMessage({
374
+ thread,
375
+ triggerMessage: this.resolveDataResourceUriFromId(messageResourceId, context),
376
+ actor: context.webId,
377
+ role: input.type === 'm.room.message' ? models_1.MessageRole.USER : models_1.MessageRole.SYSTEM,
378
+ content: contentText,
379
+ reconcilerOwner,
380
+ mentions,
381
+ routeTargetAgent,
382
+ participants: roomContext?.participants,
383
+ });
278
384
  return record;
279
385
  }
386
+ async appendMembershipEvent(db, roomId, memberUserId, membership, context, options = {}) {
387
+ const sender = options.sender ?? this.getMatrixUserId(context);
388
+ return this.appendEvent(db, {
389
+ roomId,
390
+ reconcilerOwner: options.reconcilerOwner,
391
+ type: 'm.room.member',
392
+ sender,
393
+ originServerTs: Date.now(),
394
+ stateKey: memberUserId,
395
+ content: {
396
+ membership,
397
+ displayname: this.displayNameFromUserId(memberUserId),
398
+ },
399
+ }, context);
400
+ }
280
401
  async listRooms(db) {
281
402
  const rooms = await db.select().from(models_1.chatResource);
282
403
  return rooms
283
404
  .map((room) => this.chatSourceToRoomRecord(room))
284
405
  .filter((room) => room !== undefined);
285
406
  }
407
+ async listJoinedRoomRecords(db, context) {
408
+ const rooms = await this.listRooms(db);
409
+ const matrixUserId = this.getMatrixUserId(context);
410
+ const joined = [];
411
+ for (const room of rooms) {
412
+ const membership = await this.findLatestStateEvent(db, room.roomId, 'm.room.member', matrixUserId, context);
413
+ if (!membership || membership.content.membership === 'join' || membership.content.membership === 'invite') {
414
+ joined.push(room);
415
+ }
416
+ }
417
+ return joined;
418
+ }
419
+ async resolveRoomId(db, roomIdOrAlias) {
420
+ if (!roomIdOrAlias.startsWith('#')) {
421
+ return roomIdOrAlias;
422
+ }
423
+ const rooms = await this.listRooms(db);
424
+ const room = rooms.find((candidate) => candidate.canonicalAlias === roomIdOrAlias);
425
+ if (!room) {
426
+ throw new Error(`Matrix room alias not found: ${roomIdOrAlias}`);
427
+ }
428
+ return room.roomId;
429
+ }
286
430
  async listEvents(db, roomId, context, options = {}) {
287
431
  const conditions = [
288
432
  (0, drizzle_solid_1.eq)(models_1.messageResource.thread, this.resolveDataResourceUriFromId(this.threadResourceIdFromRoomId(roomId), context)),
@@ -317,20 +461,23 @@ class PodMatrixStore {
317
461
  }
318
462
  eventSourceToRecord(source) {
319
463
  const metadata = this.parseJsonObject(source.metadata) ?? {};
320
- const content = this.parseJsonObject(metadata.content)
464
+ const matrix = (0, protocol_metadata_1.getProtocolMetadata)(metadata, 'matrix') ?? {};
465
+ const content = this.parseJsonObject(matrix.content)
466
+ ?? this.parseJsonObject(metadata.content)
321
467
  ?? this.parseJsonObject(source.content)
322
468
  ?? {};
323
- const unsigned = this.parseJsonObject(metadata.unsigned);
324
- const stateKey = this.stringValue(metadata.stateKey);
325
- const txnId = this.stringValue(metadata.txnId);
469
+ const unsigned = this.parseJsonObject(matrix.unsigned)
470
+ ?? this.parseJsonObject(metadata.unsigned);
471
+ const stateKey = this.stringValue(matrix.stateKey ?? matrix.state_key ?? metadata.stateKey);
472
+ const txnId = this.stringValue(matrix.txnId ?? matrix.txn_id ?? metadata.txnId);
326
473
  return {
327
- eventId: this.stringValue(metadata.eventId) ?? source.id,
328
- roomId: this.stringValue(metadata.roomId) ?? '',
329
- type: this.stringValue(metadata.eventType) ?? 'm.room.message',
330
- sender: this.stringValue(metadata.sender) ?? '',
331
- senderWebId: this.stringValue(metadata.senderWebId) ?? source.maker ?? undefined,
332
- originServerTs: this.numberValue(metadata.originServerTs) ?? this.isoToMillis(source.createdAt) ?? Date.now(),
333
- depth: this.numberValue(metadata.depth),
474
+ eventId: this.stringValue(matrix.eventId ?? matrix.event_id ?? metadata.eventId) ?? source.id,
475
+ roomId: this.stringValue(matrix.roomId ?? matrix.room_id ?? metadata.roomId) ?? '',
476
+ type: this.stringValue(matrix.eventType ?? matrix.event_type ?? metadata.eventType) ?? 'm.room.message',
477
+ sender: this.stringValue(matrix.sender ?? metadata.sender) ?? '',
478
+ senderWebId: this.stringValue(matrix.senderWebId ?? matrix.sender_web_id ?? metadata.senderWebId) ?? source.maker ?? undefined,
479
+ originServerTs: this.numberValue(matrix.originServerTs ?? matrix.origin_server_ts ?? metadata.originServerTs) ?? this.isoToMillis(source.createdAt) ?? Date.now(),
480
+ depth: this.numberValue(matrix.depth ?? metadata.depth),
334
481
  txnId: txnId ?? undefined,
335
482
  content,
336
483
  stateKey: stateKey ?? undefined,
@@ -342,15 +489,20 @@ class PodMatrixStore {
342
489
  if (metadata.protocol !== 'matrix') {
343
490
  return undefined;
344
491
  }
345
- const roomId = this.stringValue(metadata.roomId);
492
+ const matrix = (0, protocol_metadata_1.getProtocolMetadata)(metadata, 'matrix') ?? {};
493
+ const roomId = this.stringValue(matrix.roomId ?? matrix.room_id ?? metadata.roomId);
346
494
  if (!roomId) {
347
495
  return undefined;
348
496
  }
497
+ const reconcilerOwner = (0, reconciler_1.normalizeReconcilerOwner)(metadata.reconcilerOwner, 'server');
498
+ const coordination = (0, reconciler_1.reconcilerCoordinationMetadata)(reconcilerOwner);
349
499
  return {
350
500
  roomId,
501
+ canonicalAlias: this.stringValue(matrix.canonicalAlias ?? matrix.canonical_alias ?? metadata.canonicalAlias),
351
502
  name: source.title ?? undefined,
352
503
  topic: source.description ?? undefined,
353
504
  creator: source.author ?? '',
505
+ reconcilerOwner: coordination.reconcilerOwner,
354
506
  createdAt: this.isoToMillis(source.createdAt) ?? 0,
355
507
  };
356
508
  }
@@ -395,15 +547,59 @@ class PodMatrixStore {
395
547
  }
396
548
  return Number.isFinite(value) ? value : undefined;
397
549
  }
550
+ async getRoomContext(db, roomId) {
551
+ const room = await db.findById(models_1.chatResource, this.chatResourceIdFromRoomId(roomId));
552
+ return {
553
+ metadata: this.parseJsonObject(room?.metadata),
554
+ participants: (0, reconciler_1.normalizeAgentUris)(room?.participants),
555
+ };
556
+ }
557
+ reconcilerOwnerFromRoomMetadata(metadata) {
558
+ return (0, reconciler_1.normalizeReconcilerOwner)(metadata?.reconcilerOwner, 'server');
559
+ }
560
+ async reconcileGroupUserMessage(input) {
561
+ if (!this.serverGroupReconcilerService || input.role !== models_1.MessageRole.USER) {
562
+ return;
563
+ }
564
+ try {
565
+ await this.serverGroupReconcilerService.reconcileThreadMessage({
566
+ thread: input.thread,
567
+ triggerMessage: input.triggerMessage,
568
+ actor: input.actor,
569
+ role: 'user',
570
+ content: input.content,
571
+ reconcilerOwner: input.reconcilerOwner,
572
+ mentions: input.mentions,
573
+ routeTargetAgent: input.routeTargetAgent,
574
+ participants: input.participants,
575
+ });
576
+ }
577
+ catch (error) {
578
+ this.logger.warn(`Failed to enqueue Matrix group Reconciler wake: ${error}`);
579
+ }
580
+ }
398
581
  messageContentFromMatrixEvent(eventType, content) {
399
582
  if (eventType === 'm.room.message' && typeof content.body === 'string') {
400
583
  return content.body;
401
584
  }
402
585
  return JSON.stringify(content);
403
586
  }
587
+ mentionsFromMatrixContent(content) {
588
+ const matrixMentions = this.parseJsonObject(content['m.mentions']);
589
+ return (0, reconciler_1.normalizeAgentUris)([
590
+ ...(0, reconciler_1.normalizeAgentUris)(content.mentions),
591
+ ...(0, reconciler_1.normalizeAgentUris)(content['co.undefineds.mentions']),
592
+ ...(0, reconciler_1.normalizeAgentUris)(matrixMentions?.agents),
593
+ ]);
594
+ }
595
+ routeTargetAgentFromMatrixContent(content) {
596
+ return this.stringValue(content.routeTargetAgent)
597
+ ?? this.stringValue(content['co.undefineds.routeTargetAgent'])
598
+ ?? this.stringValue(content['co.undefineds.route_target_agent']);
599
+ }
404
600
  getMatrixUserId(context) {
405
601
  const serverName = this.getServerName(context);
406
- const localpart = this.localpartFromUserId(context.userId);
602
+ const localpart = this.localpartFromUserId(context.webId);
407
603
  return `@${localpart}:${serverName}`;
408
604
  }
409
605
  getServerName(context) {
@@ -411,7 +607,7 @@ class PodMatrixStore {
411
607
  return this.serverName;
412
608
  }
413
609
  try {
414
- return new URL(context.userId).host || 'localhost';
610
+ return new URL(context.webId).host || 'localhost';
415
611
  }
416
612
  catch {
417
613
  return 'localhost';
@@ -436,6 +632,9 @@ class PodMatrixStore {
436
632
  generateEventId(context) {
437
633
  return `$${this.randomId(24)}:${this.getServerName(context)}`;
438
634
  }
635
+ deviceIdFromUserId(userId) {
636
+ return `XPOD${(0, node_crypto_1.createHash)('sha256').update(userId).digest('hex').slice(0, 12).toUpperCase()}`;
637
+ }
439
638
  randomId(size) {
440
639
  return (0, node_crypto_1.randomBytes)(size).toString('base64url');
441
640
  }
@@ -448,15 +647,21 @@ class PodMatrixStore {
448
647
  chatResourceIdFromRoomId(roomId) {
449
648
  return `${this.surfaceIdFromRoomId(roomId)}/index.ttl#this`;
450
649
  }
650
+ messageParentResourceIdFromRoomId(roomId) {
651
+ return `chat/${this.surfaceIdFromRoomId(roomId)}/index.ttl#this`;
652
+ }
451
653
  threadResourceIdFromRoomId(roomId) {
452
654
  return `chat/${this.surfaceIdFromRoomId(roomId)}/index.ttl#thread`;
453
655
  }
656
+ chatParentRefFromRoomId(roomId) {
657
+ return `/.data/chat/${this.chatResourceIdFromRoomId(roomId)}`;
658
+ }
454
659
  messageResourceIdFromEvent(roomId, eventId, ts) {
455
660
  const { yyyy, MM, dd } = this.dateParts(ts);
456
661
  return `chat/${this.surfaceIdFromRoomId(roomId)}/${yyyy}/${MM}/${dd}/messages.ttl#${this.slug(eventId)}`;
457
662
  }
458
663
  resolveDataResourceUriFromId(resourceId, context) {
459
- const podBaseUrl = this.derivePodBaseUrl((0, AuthContext_1.getWebId)(context.auth) ?? context.userId);
664
+ const podBaseUrl = this.derivePodBaseUrl(context.webId);
460
665
  if (!podBaseUrl) {
461
666
  return resourceId;
462
667
  }