@undefineds.co/xpod 0.3.48 → 0.3.50
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/bin/xpod.js +0 -0
- package/dist/api/auth/MultiAuthenticator.js +2 -2
- package/dist/api/auth/MultiAuthenticator.js.map +1 -1
- package/dist/api/chatkit/pod-store.d.ts +16 -17
- package/dist/api/chatkit/pod-store.js +299 -231
- package/dist/api/chatkit/pod-store.js.map +1 -1
- package/dist/api/chatkit/schema.d.ts +1 -1
- package/dist/api/chatkit/service.js +13 -11
- package/dist/api/chatkit/service.js.map +1 -1
- package/dist/api/chatkit/store.d.ts +1 -0
- package/dist/api/chatkit/store.js +23 -11
- package/dist/api/chatkit/store.js.map +1 -1
- package/dist/api/chatkit/types.d.ts +17 -10
- package/dist/api/chatkit/types.js +97 -14
- package/dist/api/chatkit/types.js.map +1 -1
- package/dist/api/container/common.js +16 -2
- package/dist/api/container/common.js.map +1 -1
- package/dist/api/container/routes.js +3 -0
- package/dist/api/container/routes.js.map +1 -1
- package/dist/api/container/types.d.ts +3 -0
- package/dist/api/container/types.js.map +1 -1
- package/dist/api/handlers/ChatKitV1Handler.js +1 -2
- package/dist/api/handlers/ChatKitV1Handler.js.map +1 -1
- package/dist/api/handlers/CoordinationHandler.d.ts +6 -0
- package/dist/api/handlers/CoordinationHandler.js +115 -0
- package/dist/api/handlers/CoordinationHandler.js.map +1 -0
- package/dist/api/handlers/MatrixHandler.d.ts +11 -0
- package/dist/api/handlers/MatrixHandler.js +144 -2
- package/dist/api/handlers/MatrixHandler.js.map +1 -1
- package/dist/api/handlers/RunHandler.js +33 -15
- package/dist/api/handlers/RunHandler.js.map +1 -1
- package/dist/api/handlers/index.d.ts +1 -0
- package/dist/api/handlers/index.js +1 -0
- package/dist/api/handlers/index.js.map +1 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/matrix/PodMatrixStore.d.ts +25 -1
- package/dist/api/matrix/PodMatrixStore.js +253 -41
- package/dist/api/matrix/PodMatrixStore.js.map +1 -1
- package/dist/api/matrix/index.d.ts +1 -1
- package/dist/api/matrix/index.js.map +1 -1
- package/dist/api/matrix/types.d.ts +25 -2
- package/dist/api/matrix/types.js.map +1 -1
- package/dist/api/middleware/AuthMiddleware.d.ts +1 -0
- package/dist/api/middleware/AuthMiddleware.js +13 -1
- package/dist/api/middleware/AuthMiddleware.js.map +1 -1
- package/dist/api/protocol-metadata.d.ts +4 -0
- package/dist/api/protocol-metadata.js +64 -0
- package/dist/api/protocol-metadata.js.map +1 -0
- package/dist/api/reconciler/ClientReconcilerCoordinator.d.ts +42 -0
- package/dist/api/reconciler/ClientReconcilerCoordinator.js +250 -0
- package/dist/api/reconciler/ClientReconcilerCoordinator.js.map +1 -0
- package/dist/api/reconciler/ClientReconcilerCoordinator.jsonld +186 -0
- package/dist/api/reconciler/ServerGroupReconcilerService.d.ts +39 -0
- package/dist/api/reconciler/ServerGroupReconcilerService.js +91 -0
- package/dist/api/reconciler/ServerGroupReconcilerService.js.map +1 -0
- package/dist/api/reconciler/ServerGroupReconcilerService.jsonld +146 -0
- package/dist/api/reconciler/WakeAgentQueue.d.ts +23 -0
- package/dist/api/reconciler/WakeAgentQueue.js +123 -0
- package/dist/api/reconciler/WakeAgentQueue.js.map +1 -0
- package/dist/api/reconciler/WakeAgentQueue.jsonld +91 -0
- package/dist/api/reconciler/coordination.d.ts +61 -0
- package/dist/api/reconciler/coordination.js +109 -0
- package/dist/api/reconciler/coordination.js.map +1 -0
- package/dist/api/reconciler/coordination.jsonld +186 -0
- package/dist/api/reconciler/index.d.ts +4 -0
- package/dist/api/reconciler/index.js +21 -0
- package/dist/api/reconciler/index.js.map +1 -0
- package/dist/api/runs/ManagedRunWorker.js +0 -5
- package/dist/api/runs/ManagedRunWorker.js.map +1 -1
- package/dist/api/runs/RunStateCenter.d.ts +1 -1
- package/dist/api/runs/RunStateCenter.js +12 -28
- package/dist/api/runs/RunStateCenter.js.map +1 -1
- package/dist/api/runs/store.d.ts +12 -15
- package/dist/api/runs/store.js +24 -15
- package/dist/api/runs/store.js.map +1 -1
- package/dist/api/tasks/TaskMaterializer.d.ts +1 -0
- package/dist/api/tasks/TaskMaterializer.js +10 -13
- package/dist/api/tasks/TaskMaterializer.js.map +1 -1
- package/dist/api/tasks/TaskService.d.ts +0 -2
- package/dist/api/tasks/TaskService.js +6 -16
- package/dist/api/tasks/TaskService.js.map +1 -1
- package/dist/api/tasks/store.d.ts +0 -2
- package/dist/api/tasks/store.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +1 -1
- package/dist/cli/commands/auth.js +4 -5
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/backup.js +1 -1
- package/dist/cli/commands/backup.js.map +1 -1
- package/dist/cli/commands/login.js +1 -1
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/pod.js +1 -1
- package/dist/cli/commands/pod.js.map +1 -1
- package/dist/cli/lib/auth-context.js +10 -7
- package/dist/cli/lib/auth-context.js.map +1 -1
- package/dist/cli/lib/auth-helper.d.ts +10 -6
- package/dist/cli/lib/auth-helper.js +10 -6
- package/dist/cli/lib/auth-helper.js.map +1 -1
- package/dist/cli/lib/credentials-store.d.ts +22 -4
- package/dist/cli/lib/credentials-store.js +68 -51
- package/dist/cli/lib/credentials-store.js.map +1 -1
- package/dist/cli/lib/oidc-auth.d.ts +4 -0
- package/dist/cli/lib/oidc-auth.js +90 -0
- package/dist/cli/lib/oidc-auth.js.map +1 -0
- package/dist/cli/lib/oidc-session-storage.d.ts +3 -0
- package/dist/cli/lib/oidc-session-storage.js +41 -0
- package/dist/cli/lib/oidc-session-storage.js.map +1 -0
- package/dist/components/components.jsonld +5 -1
- package/dist/components/context.jsonld +103 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/dist/provision/LocalPodProvisioningService.d.ts +1 -0
- package/dist/provision/LocalPodProvisioningService.js +9 -0
- package/dist/provision/LocalPodProvisioningService.js.map +1 -1
- package/dist/provision/LocalPodProvisioningService.jsonld +4 -0
- package/dist/runtime/Proxy.d.ts +1 -0
- package/dist/runtime/Proxy.js +8 -1
- package/dist/runtime/Proxy.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/select-query-builder.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/select-query-builder.js +19 -9
- package/node_modules/@undefineds.co/drizzle-solid/dist/core/query-builders/select-query-builder.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/select-query-builder.d.ts.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/select-query-builder.js +19 -9
- package/node_modules/@undefineds.co/drizzle-solid/dist/esm/core/query-builders/select-query-builder.js.map +1 -1
- package/node_modules/@undefineds.co/drizzle-solid/package.json +1 -1
- package/package.json +5 -4
|
@@ -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.
|
|
43
|
+
author: context.webId,
|
|
29
44
|
status: 'active',
|
|
30
|
-
participants: [context.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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);
|
|
@@ -209,8 +289,15 @@ class PodMatrixStore {
|
|
|
209
289
|
}
|
|
210
290
|
const db = (0, drizzle_solid_1.drizzle)({
|
|
211
291
|
fetch: this.createAccessTokenFetch(auth.accessToken, auth.tokenType),
|
|
212
|
-
info: {
|
|
213
|
-
|
|
292
|
+
info: {
|
|
293
|
+
webId: auth.webId,
|
|
294
|
+
isLoggedIn: true,
|
|
295
|
+
podUrl: context.podUrl,
|
|
296
|
+
},
|
|
297
|
+
}, {
|
|
298
|
+
schema,
|
|
299
|
+
podUrl: context.podUrl,
|
|
300
|
+
});
|
|
214
301
|
await db.init(models_1.chatResource, models_1.threadResource, models_1.messageResource);
|
|
215
302
|
context._matrixDb = db;
|
|
216
303
|
return db;
|
|
@@ -235,12 +322,23 @@ class PodMatrixStore {
|
|
|
235
322
|
const eventId = this.generateEventId(context);
|
|
236
323
|
const depth = await this.nextEventDepth(db, input.roomId, context);
|
|
237
324
|
const originIso = new Date(input.originServerTs).toISOString();
|
|
325
|
+
const needsRoomMetadata = input.reconcilerOwner === undefined
|
|
326
|
+
|| (input.type === 'm.room.message' && this.serverGroupReconcilerService !== undefined);
|
|
327
|
+
const roomContext = needsRoomMetadata ? await this.getRoomContext(db, input.roomId) : undefined;
|
|
328
|
+
const roomMetadata = roomContext?.metadata;
|
|
329
|
+
const reconcilerOwner = input.reconcilerOwner ?? this.reconcilerOwnerFromRoomMetadata(roomMetadata);
|
|
330
|
+
const coordination = (0, reconciler_1.reconcilerCoordinationMetadata)(reconcilerOwner);
|
|
331
|
+
const messageResourceId = this.messageResourceIdFromEvent(input.roomId, eventId, input.originServerTs);
|
|
332
|
+
const thread = this.resolveDataResourceUriFromId(this.threadResourceIdFromRoomId(input.roomId), context);
|
|
333
|
+
const contentText = this.messageContentFromMatrixEvent(input.type, input.content);
|
|
334
|
+
const mentions = this.mentionsFromMatrixContent(input.content);
|
|
335
|
+
const routeTargetAgent = this.routeTargetAgentFromMatrixContent(input.content);
|
|
238
336
|
const record = {
|
|
239
337
|
eventId,
|
|
240
338
|
roomId: input.roomId,
|
|
241
339
|
type: input.type,
|
|
242
340
|
sender: input.sender,
|
|
243
|
-
senderWebId: context.
|
|
341
|
+
senderWebId: context.webId,
|
|
244
342
|
originServerTs: input.originServerTs,
|
|
245
343
|
depth,
|
|
246
344
|
txnId: input.txnId ?? undefined,
|
|
@@ -249,40 +347,93 @@ class PodMatrixStore {
|
|
|
249
347
|
createdAt: originIso,
|
|
250
348
|
};
|
|
251
349
|
await db.insert(models_1.messageResource).values({
|
|
252
|
-
id:
|
|
350
|
+
id: messageResourceId,
|
|
351
|
+
parent: this.resolveDataResourceUriFromId(this.messageParentResourceIdFromRoomId(input.roomId), context),
|
|
253
352
|
chat: this.chatResourceIdFromRoomId(input.roomId),
|
|
254
|
-
thread
|
|
255
|
-
maker: context.
|
|
353
|
+
thread,
|
|
354
|
+
maker: context.webId,
|
|
256
355
|
role: input.type === 'm.room.message' ? models_1.MessageRole.USER : models_1.MessageRole.SYSTEM,
|
|
257
|
-
content:
|
|
356
|
+
content: contentText,
|
|
258
357
|
status: models_1.MessageStatus.SENT,
|
|
259
|
-
|
|
358
|
+
mentions,
|
|
359
|
+
routeTargetAgent: routeTargetAgent ?? null,
|
|
360
|
+
metadata: (0, protocol_metadata_1.withProtocolMetadata)({
|
|
260
361
|
protocol: 'matrix',
|
|
362
|
+
commandKind: 'chat',
|
|
363
|
+
surface_id: this.surfaceIdFromRoomId(input.roomId),
|
|
364
|
+
...coordination,
|
|
365
|
+
}, 'matrix', {
|
|
261
366
|
eventId,
|
|
262
367
|
roomId: input.roomId,
|
|
263
368
|
eventType: input.type,
|
|
264
369
|
sender: input.sender,
|
|
265
|
-
senderWebId: context.
|
|
370
|
+
senderWebId: context.webId,
|
|
266
371
|
originServerTs: input.originServerTs,
|
|
267
372
|
depth,
|
|
268
373
|
txnId: input.txnId ?? null,
|
|
269
374
|
stateKey: input.stateKey ?? null,
|
|
270
375
|
content: input.content,
|
|
271
|
-
|
|
272
|
-
surface_id: this.surfaceIdFromRoomId(input.roomId),
|
|
273
|
-
chat_id: this.surfaceIdFromRoomId(input.roomId),
|
|
274
|
-
},
|
|
376
|
+
}),
|
|
275
377
|
createdAt: originIso,
|
|
276
378
|
updatedAt: originIso,
|
|
277
379
|
});
|
|
380
|
+
await this.reconcileGroupUserMessage({
|
|
381
|
+
thread,
|
|
382
|
+
triggerMessage: this.resolveDataResourceUriFromId(messageResourceId, context),
|
|
383
|
+
actor: context.webId,
|
|
384
|
+
role: input.type === 'm.room.message' ? models_1.MessageRole.USER : models_1.MessageRole.SYSTEM,
|
|
385
|
+
content: contentText,
|
|
386
|
+
reconcilerOwner,
|
|
387
|
+
mentions,
|
|
388
|
+
routeTargetAgent,
|
|
389
|
+
participants: roomContext?.participants,
|
|
390
|
+
});
|
|
278
391
|
return record;
|
|
279
392
|
}
|
|
393
|
+
async appendMembershipEvent(db, roomId, memberUserId, membership, context, options = {}) {
|
|
394
|
+
const sender = options.sender ?? this.getMatrixUserId(context);
|
|
395
|
+
return this.appendEvent(db, {
|
|
396
|
+
roomId,
|
|
397
|
+
reconcilerOwner: options.reconcilerOwner,
|
|
398
|
+
type: 'm.room.member',
|
|
399
|
+
sender,
|
|
400
|
+
originServerTs: Date.now(),
|
|
401
|
+
stateKey: memberUserId,
|
|
402
|
+
content: {
|
|
403
|
+
membership,
|
|
404
|
+
displayname: this.displayNameFromUserId(memberUserId),
|
|
405
|
+
},
|
|
406
|
+
}, context);
|
|
407
|
+
}
|
|
280
408
|
async listRooms(db) {
|
|
281
409
|
const rooms = await db.select().from(models_1.chatResource);
|
|
282
410
|
return rooms
|
|
283
411
|
.map((room) => this.chatSourceToRoomRecord(room))
|
|
284
412
|
.filter((room) => room !== undefined);
|
|
285
413
|
}
|
|
414
|
+
async listJoinedRoomRecords(db, context) {
|
|
415
|
+
const rooms = await this.listRooms(db);
|
|
416
|
+
const matrixUserId = this.getMatrixUserId(context);
|
|
417
|
+
const joined = [];
|
|
418
|
+
for (const room of rooms) {
|
|
419
|
+
const membership = await this.findLatestStateEvent(db, room.roomId, 'm.room.member', matrixUserId, context);
|
|
420
|
+
if (!membership || membership.content.membership === 'join' || membership.content.membership === 'invite') {
|
|
421
|
+
joined.push(room);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return joined;
|
|
425
|
+
}
|
|
426
|
+
async resolveRoomId(db, roomIdOrAlias) {
|
|
427
|
+
if (!roomIdOrAlias.startsWith('#')) {
|
|
428
|
+
return roomIdOrAlias;
|
|
429
|
+
}
|
|
430
|
+
const rooms = await this.listRooms(db);
|
|
431
|
+
const room = rooms.find((candidate) => candidate.canonicalAlias === roomIdOrAlias);
|
|
432
|
+
if (!room) {
|
|
433
|
+
throw new Error(`Matrix room alias not found: ${roomIdOrAlias}`);
|
|
434
|
+
}
|
|
435
|
+
return room.roomId;
|
|
436
|
+
}
|
|
286
437
|
async listEvents(db, roomId, context, options = {}) {
|
|
287
438
|
const conditions = [
|
|
288
439
|
(0, drizzle_solid_1.eq)(models_1.messageResource.thread, this.resolveDataResourceUriFromId(this.threadResourceIdFromRoomId(roomId), context)),
|
|
@@ -292,7 +443,7 @@ class PodMatrixStore {
|
|
|
292
443
|
let query = db.select().from(models_1.messageResource).where((0, drizzle_solid_1.and)(...conditions));
|
|
293
444
|
query = options.newestFirst
|
|
294
445
|
? query.orderBy((0, drizzle_solid_1.desc)(models_1.messageResource.createdAt))
|
|
295
|
-
: query.orderBy(models_1.messageResource.createdAt);
|
|
446
|
+
: query.orderBy((0, drizzle_solid_1.asc)(models_1.messageResource.createdAt));
|
|
296
447
|
if (options.limit && options.limit > 0) {
|
|
297
448
|
query = query.limit(options.limit);
|
|
298
449
|
}
|
|
@@ -317,20 +468,23 @@ class PodMatrixStore {
|
|
|
317
468
|
}
|
|
318
469
|
eventSourceToRecord(source) {
|
|
319
470
|
const metadata = this.parseJsonObject(source.metadata) ?? {};
|
|
320
|
-
const
|
|
471
|
+
const matrix = (0, protocol_metadata_1.getProtocolMetadata)(metadata, 'matrix') ?? {};
|
|
472
|
+
const content = this.parseJsonObject(matrix.content)
|
|
473
|
+
?? this.parseJsonObject(metadata.content)
|
|
321
474
|
?? this.parseJsonObject(source.content)
|
|
322
475
|
?? {};
|
|
323
|
-
const unsigned = this.parseJsonObject(
|
|
324
|
-
|
|
325
|
-
const
|
|
476
|
+
const unsigned = this.parseJsonObject(matrix.unsigned)
|
|
477
|
+
?? this.parseJsonObject(metadata.unsigned);
|
|
478
|
+
const stateKey = this.stringValue(matrix.stateKey ?? matrix.state_key ?? metadata.stateKey);
|
|
479
|
+
const txnId = this.stringValue(matrix.txnId ?? matrix.txn_id ?? metadata.txnId);
|
|
326
480
|
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),
|
|
481
|
+
eventId: this.stringValue(matrix.eventId ?? matrix.event_id ?? metadata.eventId) ?? source.id,
|
|
482
|
+
roomId: this.stringValue(matrix.roomId ?? matrix.room_id ?? metadata.roomId) ?? '',
|
|
483
|
+
type: this.stringValue(matrix.eventType ?? matrix.event_type ?? metadata.eventType) ?? 'm.room.message',
|
|
484
|
+
sender: this.stringValue(matrix.sender ?? metadata.sender) ?? '',
|
|
485
|
+
senderWebId: this.stringValue(matrix.senderWebId ?? matrix.sender_web_id ?? metadata.senderWebId) ?? source.maker ?? undefined,
|
|
486
|
+
originServerTs: this.numberValue(matrix.originServerTs ?? matrix.origin_server_ts ?? metadata.originServerTs) ?? this.isoToMillis(source.createdAt) ?? Date.now(),
|
|
487
|
+
depth: this.numberValue(matrix.depth ?? metadata.depth),
|
|
334
488
|
txnId: txnId ?? undefined,
|
|
335
489
|
content,
|
|
336
490
|
stateKey: stateKey ?? undefined,
|
|
@@ -342,15 +496,20 @@ class PodMatrixStore {
|
|
|
342
496
|
if (metadata.protocol !== 'matrix') {
|
|
343
497
|
return undefined;
|
|
344
498
|
}
|
|
345
|
-
const
|
|
499
|
+
const matrix = (0, protocol_metadata_1.getProtocolMetadata)(metadata, 'matrix') ?? {};
|
|
500
|
+
const roomId = this.stringValue(matrix.roomId ?? matrix.room_id ?? metadata.roomId);
|
|
346
501
|
if (!roomId) {
|
|
347
502
|
return undefined;
|
|
348
503
|
}
|
|
504
|
+
const reconcilerOwner = (0, reconciler_1.normalizeReconcilerOwner)(metadata.reconcilerOwner, 'server');
|
|
505
|
+
const coordination = (0, reconciler_1.reconcilerCoordinationMetadata)(reconcilerOwner);
|
|
349
506
|
return {
|
|
350
507
|
roomId,
|
|
508
|
+
canonicalAlias: this.stringValue(matrix.canonicalAlias ?? matrix.canonical_alias ?? metadata.canonicalAlias),
|
|
351
509
|
name: source.title ?? undefined,
|
|
352
510
|
topic: source.description ?? undefined,
|
|
353
511
|
creator: source.author ?? '',
|
|
512
|
+
reconcilerOwner: coordination.reconcilerOwner,
|
|
354
513
|
createdAt: this.isoToMillis(source.createdAt) ?? 0,
|
|
355
514
|
};
|
|
356
515
|
}
|
|
@@ -395,15 +554,59 @@ class PodMatrixStore {
|
|
|
395
554
|
}
|
|
396
555
|
return Number.isFinite(value) ? value : undefined;
|
|
397
556
|
}
|
|
557
|
+
async getRoomContext(db, roomId) {
|
|
558
|
+
const room = await db.findById(models_1.chatResource, this.chatResourceIdFromRoomId(roomId));
|
|
559
|
+
return {
|
|
560
|
+
metadata: this.parseJsonObject(room?.metadata),
|
|
561
|
+
participants: (0, reconciler_1.normalizeAgentUris)(room?.participants),
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
reconcilerOwnerFromRoomMetadata(metadata) {
|
|
565
|
+
return (0, reconciler_1.normalizeReconcilerOwner)(metadata?.reconcilerOwner, 'server');
|
|
566
|
+
}
|
|
567
|
+
async reconcileGroupUserMessage(input) {
|
|
568
|
+
if (!this.serverGroupReconcilerService || input.role !== models_1.MessageRole.USER) {
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
try {
|
|
572
|
+
await this.serverGroupReconcilerService.reconcileThreadMessage({
|
|
573
|
+
thread: input.thread,
|
|
574
|
+
triggerMessage: input.triggerMessage,
|
|
575
|
+
actor: input.actor,
|
|
576
|
+
role: 'user',
|
|
577
|
+
content: input.content,
|
|
578
|
+
reconcilerOwner: input.reconcilerOwner,
|
|
579
|
+
mentions: input.mentions,
|
|
580
|
+
routeTargetAgent: input.routeTargetAgent,
|
|
581
|
+
participants: input.participants,
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
catch (error) {
|
|
585
|
+
this.logger.warn(`Failed to enqueue Matrix group Reconciler wake: ${error}`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
398
588
|
messageContentFromMatrixEvent(eventType, content) {
|
|
399
589
|
if (eventType === 'm.room.message' && typeof content.body === 'string') {
|
|
400
590
|
return content.body;
|
|
401
591
|
}
|
|
402
592
|
return JSON.stringify(content);
|
|
403
593
|
}
|
|
594
|
+
mentionsFromMatrixContent(content) {
|
|
595
|
+
const matrixMentions = this.parseJsonObject(content['m.mentions']);
|
|
596
|
+
return (0, reconciler_1.normalizeAgentUris)([
|
|
597
|
+
...(0, reconciler_1.normalizeAgentUris)(content.mentions),
|
|
598
|
+
...(0, reconciler_1.normalizeAgentUris)(content['co.undefineds.mentions']),
|
|
599
|
+
...(0, reconciler_1.normalizeAgentUris)(matrixMentions?.agents),
|
|
600
|
+
]);
|
|
601
|
+
}
|
|
602
|
+
routeTargetAgentFromMatrixContent(content) {
|
|
603
|
+
return this.stringValue(content.routeTargetAgent)
|
|
604
|
+
?? this.stringValue(content['co.undefineds.routeTargetAgent'])
|
|
605
|
+
?? this.stringValue(content['co.undefineds.route_target_agent']);
|
|
606
|
+
}
|
|
404
607
|
getMatrixUserId(context) {
|
|
405
608
|
const serverName = this.getServerName(context);
|
|
406
|
-
const localpart = this.localpartFromUserId(context.
|
|
609
|
+
const localpart = this.localpartFromUserId(context.webId);
|
|
407
610
|
return `@${localpart}:${serverName}`;
|
|
408
611
|
}
|
|
409
612
|
getServerName(context) {
|
|
@@ -411,7 +614,7 @@ class PodMatrixStore {
|
|
|
411
614
|
return this.serverName;
|
|
412
615
|
}
|
|
413
616
|
try {
|
|
414
|
-
return new URL(context.
|
|
617
|
+
return new URL(context.webId).host || 'localhost';
|
|
415
618
|
}
|
|
416
619
|
catch {
|
|
417
620
|
return 'localhost';
|
|
@@ -436,6 +639,9 @@ class PodMatrixStore {
|
|
|
436
639
|
generateEventId(context) {
|
|
437
640
|
return `$${this.randomId(24)}:${this.getServerName(context)}`;
|
|
438
641
|
}
|
|
642
|
+
deviceIdFromUserId(userId) {
|
|
643
|
+
return `XPOD${(0, node_crypto_1.createHash)('sha256').update(userId).digest('hex').slice(0, 12).toUpperCase()}`;
|
|
644
|
+
}
|
|
439
645
|
randomId(size) {
|
|
440
646
|
return (0, node_crypto_1.randomBytes)(size).toString('base64url');
|
|
441
647
|
}
|
|
@@ -448,15 +654,21 @@ class PodMatrixStore {
|
|
|
448
654
|
chatResourceIdFromRoomId(roomId) {
|
|
449
655
|
return `${this.surfaceIdFromRoomId(roomId)}/index.ttl#this`;
|
|
450
656
|
}
|
|
657
|
+
messageParentResourceIdFromRoomId(roomId) {
|
|
658
|
+
return `chat/${this.surfaceIdFromRoomId(roomId)}/index.ttl#this`;
|
|
659
|
+
}
|
|
451
660
|
threadResourceIdFromRoomId(roomId) {
|
|
452
661
|
return `chat/${this.surfaceIdFromRoomId(roomId)}/index.ttl#thread`;
|
|
453
662
|
}
|
|
663
|
+
chatParentRefFromRoomId(roomId) {
|
|
664
|
+
return `/.data/chat/${this.chatResourceIdFromRoomId(roomId)}`;
|
|
665
|
+
}
|
|
454
666
|
messageResourceIdFromEvent(roomId, eventId, ts) {
|
|
455
667
|
const { yyyy, MM, dd } = this.dateParts(ts);
|
|
456
668
|
return `chat/${this.surfaceIdFromRoomId(roomId)}/${yyyy}/${MM}/${dd}/messages.ttl#${this.slug(eventId)}`;
|
|
457
669
|
}
|
|
458
670
|
resolveDataResourceUriFromId(resourceId, context) {
|
|
459
|
-
const podBaseUrl =
|
|
671
|
+
const podBaseUrl = context.podUrl ?? this.derivePodBaseUrl(context.webId);
|
|
460
672
|
if (!podBaseUrl) {
|
|
461
673
|
return resourceId;
|
|
462
674
|
}
|