@elizaos/plugin-matrix 2.0.0-alpha.8 → 2.0.0-beta.1
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/README.md +155 -0
- package/auto-enable.ts +20 -0
- package/dist/accounts.d.ts +14 -0
- package/dist/accounts.d.ts.map +1 -0
- package/dist/connector-account-provider.d.ts +18 -0
- package/dist/connector-account-provider.d.ts.map +1 -0
- package/dist/index.d.ts +1 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +595 -645
- package/dist/index.js.map +9 -12
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/service.d.ts +15 -11
- package/dist/service.d.ts.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/workflow-credential-provider.d.ts +21 -0
- package/dist/workflow-credential-provider.d.ts.map +1 -0
- package/package.json +19 -10
- package/dist/actions/joinRoom.d.ts +0 -6
- package/dist/actions/joinRoom.d.ts.map +0 -1
- package/dist/actions/listRooms.d.ts +0 -6
- package/dist/actions/listRooms.d.ts.map +0 -1
- package/dist/actions/sendMessage.d.ts +0 -6
- package/dist/actions/sendMessage.d.ts.map +0 -1
- package/dist/actions/sendReaction.d.ts +0 -6
- package/dist/actions/sendReaction.d.ts.map +0 -1
- package/dist/providers/roomState.d.ts +0 -9
- package/dist/providers/roomState.d.ts.map +0 -1
- package/dist/providers/userContext.d.ts +0 -9
- package/dist/providers/userContext.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,119 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { logger as logger2 } from "@elizaos/core";
|
|
2
|
+
import { getConnectorAccountManager, logger as logger2 } from "@elizaos/core";
|
|
3
3
|
|
|
4
|
+
// src/accounts.ts
|
|
5
|
+
var DEFAULT_MATRIX_ACCOUNT_ID = "default";
|
|
6
|
+
function stringSetting(runtime, key) {
|
|
7
|
+
const value = runtime.getSetting(key);
|
|
8
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
9
|
+
}
|
|
10
|
+
function characterConfig(runtime) {
|
|
11
|
+
const settings = runtime.character?.settings;
|
|
12
|
+
const raw = settings?.matrix;
|
|
13
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
14
|
+
}
|
|
15
|
+
function parseAccountsJson(runtime) {
|
|
16
|
+
const raw = stringSetting(runtime, "MATRIX_ACCOUNTS");
|
|
17
|
+
if (!raw)
|
|
18
|
+
return {};
|
|
19
|
+
try {
|
|
20
|
+
const parsed = JSON.parse(raw);
|
|
21
|
+
if (Array.isArray(parsed)) {
|
|
22
|
+
return Object.fromEntries(parsed.filter((item) => Boolean(item) && typeof item === "object").map((item) => [normalizeMatrixAccountId(item.accountId ?? item.id), item]));
|
|
23
|
+
}
|
|
24
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
25
|
+
} catch {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function allAccountConfigs(runtime) {
|
|
30
|
+
return {
|
|
31
|
+
...characterConfig(runtime).accounts ?? {},
|
|
32
|
+
...parseAccountsJson(runtime)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function accountConfig(runtime, accountId) {
|
|
36
|
+
const accounts = allAccountConfigs(runtime);
|
|
37
|
+
return accounts[accountId] ?? accounts[normalizeMatrixAccountId(accountId)] ?? {};
|
|
38
|
+
}
|
|
39
|
+
function boolValue(value, fallback = false) {
|
|
40
|
+
if (typeof value === "boolean")
|
|
41
|
+
return value;
|
|
42
|
+
if (typeof value === "string")
|
|
43
|
+
return value.trim().toLowerCase() === "true";
|
|
44
|
+
return fallback;
|
|
45
|
+
}
|
|
46
|
+
function roomsValue(value) {
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
return value.map((room) => String(room).trim()).filter(Boolean);
|
|
49
|
+
}
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
return value.split(",").map((room) => room.trim()).filter(Boolean);
|
|
52
|
+
}
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
function normalizeMatrixAccountId(accountId) {
|
|
56
|
+
if (typeof accountId !== "string")
|
|
57
|
+
return DEFAULT_MATRIX_ACCOUNT_ID;
|
|
58
|
+
const trimmed = accountId.trim();
|
|
59
|
+
return trimmed || DEFAULT_MATRIX_ACCOUNT_ID;
|
|
60
|
+
}
|
|
61
|
+
function listMatrixAccountIds(runtime) {
|
|
62
|
+
const ids = new Set;
|
|
63
|
+
const config = characterConfig(runtime);
|
|
64
|
+
if (stringSetting(runtime, "MATRIX_ACCESS_TOKEN") || config.homeserver && config.userId && config.accessToken) {
|
|
65
|
+
ids.add(DEFAULT_MATRIX_ACCOUNT_ID);
|
|
66
|
+
}
|
|
67
|
+
for (const id of Object.keys(allAccountConfigs(runtime))) {
|
|
68
|
+
ids.add(normalizeMatrixAccountId(id));
|
|
69
|
+
}
|
|
70
|
+
return Array.from(ids.size ? ids : new Set([DEFAULT_MATRIX_ACCOUNT_ID])).sort((a, b) => a.localeCompare(b));
|
|
71
|
+
}
|
|
72
|
+
function resolveDefaultMatrixAccountId(runtime) {
|
|
73
|
+
const requested = stringSetting(runtime, "MATRIX_DEFAULT_ACCOUNT_ID") ?? stringSetting(runtime, "MATRIX_ACCOUNT_ID");
|
|
74
|
+
if (requested)
|
|
75
|
+
return normalizeMatrixAccountId(requested);
|
|
76
|
+
const ids = listMatrixAccountIds(runtime);
|
|
77
|
+
return ids.includes(DEFAULT_MATRIX_ACCOUNT_ID) ? DEFAULT_MATRIX_ACCOUNT_ID : ids[0];
|
|
78
|
+
}
|
|
79
|
+
function readMatrixAccountId(...sources) {
|
|
80
|
+
for (const source of sources) {
|
|
81
|
+
if (!source || typeof source !== "object")
|
|
82
|
+
continue;
|
|
83
|
+
const record = source;
|
|
84
|
+
const parameters = record.parameters && typeof record.parameters === "object" ? record.parameters : {};
|
|
85
|
+
const data = record.data && typeof record.data === "object" ? record.data : {};
|
|
86
|
+
const metadata = record.metadata && typeof record.metadata === "object" ? record.metadata : {};
|
|
87
|
+
const matrix = data.matrix && typeof data.matrix === "object" ? data.matrix : {};
|
|
88
|
+
const value = record.accountId ?? parameters.accountId ?? data.accountId ?? matrix.accountId ?? metadata.accountId;
|
|
89
|
+
if (typeof value === "string" && value.trim())
|
|
90
|
+
return normalizeMatrixAccountId(value);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
function resolveMatrixAccountSettings(runtime, requestedAccountId) {
|
|
95
|
+
const accountId = normalizeMatrixAccountId(requestedAccountId ?? resolveDefaultMatrixAccountId(runtime));
|
|
96
|
+
const base = characterConfig(runtime);
|
|
97
|
+
const account = accountConfig(runtime, accountId);
|
|
98
|
+
const allowEnv = accountId === DEFAULT_MATRIX_ACCOUNT_ID;
|
|
99
|
+
return {
|
|
100
|
+
accountId,
|
|
101
|
+
homeserver: account.homeserver ?? base.homeserver ?? (allowEnv ? stringSetting(runtime, "MATRIX_HOMESERVER") : undefined) ?? "",
|
|
102
|
+
userId: account.userId ?? base.userId ?? (allowEnv ? stringSetting(runtime, "MATRIX_USER_ID") : undefined) ?? "",
|
|
103
|
+
accessToken: account.accessToken ?? base.accessToken ?? (allowEnv ? stringSetting(runtime, "MATRIX_ACCESS_TOKEN") : undefined) ?? "",
|
|
104
|
+
deviceId: account.deviceId ?? base.deviceId ?? (allowEnv ? stringSetting(runtime, "MATRIX_DEVICE_ID") : undefined),
|
|
105
|
+
rooms: roomsValue(account.rooms ?? base.rooms ?? (allowEnv ? stringSetting(runtime, "MATRIX_ROOMS") : undefined)),
|
|
106
|
+
autoJoin: boolValue(account.autoJoin ?? base.autoJoin ?? (allowEnv ? stringSetting(runtime, "MATRIX_AUTO_JOIN") : undefined)),
|
|
107
|
+
encryption: boolValue(account.encryption ?? base.encryption ?? (allowEnv ? stringSetting(runtime, "MATRIX_ENCRYPTION") : undefined)),
|
|
108
|
+
requireMention: boolValue(account.requireMention ?? base.requireMention ?? (allowEnv ? stringSetting(runtime, "MATRIX_REQUIRE_MENTION") : undefined)),
|
|
109
|
+
enabled: boolValue(account.enabled ?? base.enabled, true)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
4
112
|
// src/service.ts
|
|
5
|
-
import {
|
|
113
|
+
import {
|
|
114
|
+
logger,
|
|
115
|
+
Service
|
|
116
|
+
} from "@elizaos/core";
|
|
6
117
|
import * as sdk from "matrix-js-sdk";
|
|
7
118
|
|
|
8
119
|
// src/types.ts
|
|
@@ -93,13 +204,94 @@ class MatrixApiError extends MatrixPluginError {
|
|
|
93
204
|
}
|
|
94
205
|
|
|
95
206
|
// src/service.ts
|
|
207
|
+
function normalizeSearchQuery(query) {
|
|
208
|
+
return query.trim().toLowerCase();
|
|
209
|
+
}
|
|
210
|
+
function matrixRoomSearchText(room) {
|
|
211
|
+
return [room.roomId, room.name, room.topic, room.canonicalAlias].filter((value) => typeof value === "string" && value.length > 0).join(" ").toLowerCase();
|
|
212
|
+
}
|
|
213
|
+
function scoreMatrixRoom(room, query) {
|
|
214
|
+
const normalized = normalizeSearchQuery(query);
|
|
215
|
+
if (!normalized) {
|
|
216
|
+
return 0.4;
|
|
217
|
+
}
|
|
218
|
+
const candidates = [room.roomId, room.canonicalAlias, room.name].filter((value) => typeof value === "string" && value.length > 0);
|
|
219
|
+
if (candidates.some((candidate) => candidate.toLowerCase() === normalized)) {
|
|
220
|
+
return 1;
|
|
221
|
+
}
|
|
222
|
+
if (candidates.some((candidate) => candidate.toLowerCase().includes(normalized))) {
|
|
223
|
+
return 0.85;
|
|
224
|
+
}
|
|
225
|
+
return matrixRoomSearchText(room).includes(normalized) ? 0.65 : 0;
|
|
226
|
+
}
|
|
227
|
+
function matrixRoomToConnectorTarget(room, score = 0.5, accountId = DEFAULT_MATRIX_ACCOUNT_ID) {
|
|
228
|
+
const label = room.name || room.canonicalAlias || room.roomId;
|
|
229
|
+
return {
|
|
230
|
+
target: {
|
|
231
|
+
source: MATRIX_SERVICE_NAME,
|
|
232
|
+
accountId,
|
|
233
|
+
channelId: room.roomId
|
|
234
|
+
},
|
|
235
|
+
label,
|
|
236
|
+
kind: room.isDirect ? "user" : "room",
|
|
237
|
+
description: room.topic || `${room.memberCount} Matrix member${room.memberCount === 1 ? "" : "s"}`,
|
|
238
|
+
score,
|
|
239
|
+
contexts: ["social", "connectors"],
|
|
240
|
+
metadata: {
|
|
241
|
+
accountId,
|
|
242
|
+
roomId: room.roomId,
|
|
243
|
+
canonicalAlias: room.canonicalAlias,
|
|
244
|
+
isEncrypted: room.isEncrypted,
|
|
245
|
+
isDirect: room.isDirect,
|
|
246
|
+
memberCount: room.memberCount
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function normalizeConnectorLimit(limit, fallback = 50) {
|
|
251
|
+
if (!Number.isFinite(limit) || !limit || limit <= 0) {
|
|
252
|
+
return fallback;
|
|
253
|
+
}
|
|
254
|
+
return Math.min(Math.floor(limit), 200);
|
|
255
|
+
}
|
|
256
|
+
async function readStoredMessageMemories(runtime, roomId, limit) {
|
|
257
|
+
return runtime.getMemories({
|
|
258
|
+
tableName: "messages",
|
|
259
|
+
roomId,
|
|
260
|
+
limit,
|
|
261
|
+
orderBy: "createdAt",
|
|
262
|
+
orderDirection: "desc"
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
async function readStoredMessagesForTargets(runtime, targets, limit) {
|
|
266
|
+
const roomIds = Array.from(new Set(targets.map((target) => target.target.roomId).filter((id) => Boolean(id))));
|
|
267
|
+
const chunks = await Promise.all(roomIds.map((roomId) => readStoredMessageMemories(runtime, roomId, limit)));
|
|
268
|
+
return chunks.flat().sort((left, right) => (right.createdAt ?? 0) - (left.createdAt ?? 0)).slice(0, limit);
|
|
269
|
+
}
|
|
270
|
+
function filterMemoriesByQuery(memories, query, limit) {
|
|
271
|
+
const normalized = query.trim().toLowerCase();
|
|
272
|
+
if (!normalized) {
|
|
273
|
+
return memories.slice(0, limit);
|
|
274
|
+
}
|
|
275
|
+
return memories.filter((memory) => {
|
|
276
|
+
const text = typeof memory.content?.text === "string" ? memory.content.text : "";
|
|
277
|
+
return text.toLowerCase().includes(normalized);
|
|
278
|
+
}).slice(0, limit);
|
|
279
|
+
}
|
|
280
|
+
function extractMatrixSendOptions(content, target) {
|
|
281
|
+
const data = content.data;
|
|
282
|
+
const matrixData = data?.matrix && typeof data.matrix === "object" ? data.matrix : data;
|
|
283
|
+
return {
|
|
284
|
+
threadId: target.threadId || (typeof matrixData?.threadId === "string" ? matrixData.threadId : undefined),
|
|
285
|
+
replyTo: typeof matrixData?.replyTo === "string" ? matrixData.replyTo : undefined,
|
|
286
|
+
formatted: matrixData?.formatted === true
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
96
290
|
class MatrixService extends Service {
|
|
97
291
|
static serviceType = MATRIX_SERVICE_NAME;
|
|
98
292
|
capabilityDescription = "Matrix messaging service for chat communication";
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
connected = false;
|
|
102
|
-
syncing = false;
|
|
293
|
+
states = new Map;
|
|
294
|
+
defaultAccountId = DEFAULT_MATRIX_ACCOUNT_ID;
|
|
103
295
|
static async start(runtime) {
|
|
104
296
|
const service = new MatrixService;
|
|
105
297
|
await service.initialize(runtime);
|
|
@@ -111,91 +303,216 @@ class MatrixService extends Service {
|
|
|
111
303
|
await service.stop();
|
|
112
304
|
}
|
|
113
305
|
}
|
|
306
|
+
static registerSendHandlers(runtime, service, accountId = service.getAccountId(runtime)) {
|
|
307
|
+
accountId = normalizeMatrixAccountId(accountId);
|
|
308
|
+
const sendHandler = async (handlerRuntime, target, content) => {
|
|
309
|
+
await service.handleSendMessage(handlerRuntime, target, content);
|
|
310
|
+
return;
|
|
311
|
+
};
|
|
312
|
+
if (typeof runtime.registerMessageConnector === "function") {
|
|
313
|
+
const registration = {
|
|
314
|
+
source: MATRIX_SERVICE_NAME,
|
|
315
|
+
accountId,
|
|
316
|
+
label: "Matrix",
|
|
317
|
+
capabilities: [
|
|
318
|
+
"send_message",
|
|
319
|
+
"send_thread_reply",
|
|
320
|
+
"send_formatted_message",
|
|
321
|
+
"react_to_message",
|
|
322
|
+
"list_rooms",
|
|
323
|
+
"join_room"
|
|
324
|
+
],
|
|
325
|
+
supportedTargetKinds: ["room", "channel", "thread", "user"],
|
|
326
|
+
contexts: ["social", "connectors"],
|
|
327
|
+
description: "Send messages to joined Matrix rooms, aliases, encrypted rooms, and known direct-message rooms.",
|
|
328
|
+
metadata: {
|
|
329
|
+
accountId,
|
|
330
|
+
service: MATRIX_SERVICE_NAME
|
|
331
|
+
},
|
|
332
|
+
sendHandler,
|
|
333
|
+
resolveTargets: async (query) => {
|
|
334
|
+
const rooms = await service.getJoinedRooms(accountId);
|
|
335
|
+
return rooms.map((room) => ({ room, score: scoreMatrixRoom(room, query) })).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score).slice(0, 10).map(({ room, score }) => matrixRoomToConnectorTarget(room, score, accountId));
|
|
336
|
+
},
|
|
337
|
+
listRecentTargets: async () => (await service.getJoinedRooms(accountId)).slice(0, 10).map((room) => matrixRoomToConnectorTarget(room, 0.5, accountId)),
|
|
338
|
+
listRooms: async () => (await service.getJoinedRooms(accountId)).map((room) => matrixRoomToConnectorTarget(room, 0.5, accountId)),
|
|
339
|
+
fetchMessages: async (context, params) => {
|
|
340
|
+
const limit = normalizeConnectorLimit(params?.limit);
|
|
341
|
+
const target = params?.target ?? context.target;
|
|
342
|
+
if (target?.roomId) {
|
|
343
|
+
return readStoredMessageMemories(context.runtime, target.roomId, limit);
|
|
344
|
+
}
|
|
345
|
+
const targets = (await service.getJoinedRooms(accountId)).slice(0, 10).map((room) => matrixRoomToConnectorTarget(room, 0.5, accountId));
|
|
346
|
+
return readStoredMessagesForTargets(context.runtime, targets, limit);
|
|
347
|
+
},
|
|
348
|
+
searchMessages: async (context, params) => {
|
|
349
|
+
const limit = normalizeConnectorLimit(params?.limit);
|
|
350
|
+
const target = params?.target ?? context.target;
|
|
351
|
+
const messages = target?.roomId ? await readStoredMessageMemories(context.runtime, target.roomId, Math.max(limit, 100)) : await readStoredMessagesForTargets(context.runtime, (await service.getJoinedRooms(accountId)).slice(0, 10).map((room) => matrixRoomToConnectorTarget(room, 0.5, accountId)), Math.max(limit, 100));
|
|
352
|
+
return filterMemoriesByQuery(messages, params.query, limit);
|
|
353
|
+
},
|
|
354
|
+
reactHandler: async (handlerRuntime, params) => {
|
|
355
|
+
const target = params.target ?? { source: MATRIX_SERVICE_NAME };
|
|
356
|
+
const room = target.roomId ? await handlerRuntime.getRoom(target.roomId) : null;
|
|
357
|
+
const roomId = String(target.channelId ?? room?.channelId ?? "").trim();
|
|
358
|
+
const mutationParams = params;
|
|
359
|
+
const eventId = String(mutationParams.eventId ?? params.messageId ?? "").trim();
|
|
360
|
+
const emoji = String(params.emoji ?? "").trim();
|
|
361
|
+
if (!roomId || !eventId || !emoji) {
|
|
362
|
+
throw new Error("Matrix reactHandler requires room, event id, and emoji");
|
|
363
|
+
}
|
|
364
|
+
const result = await service.sendReaction(roomId, eventId, emoji, accountId);
|
|
365
|
+
if (!result.success) {
|
|
366
|
+
throw new Error(result.error || "Matrix reaction failed");
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
joinHandler: async (_handlerRuntime, params) => {
|
|
370
|
+
const membershipParams = params;
|
|
371
|
+
const roomIdOrAlias = String(membershipParams.roomIdOrAlias ?? params.alias ?? params.invite ?? params.channelId ?? params.roomId ?? "").trim();
|
|
372
|
+
if (!roomIdOrAlias) {
|
|
373
|
+
throw new Error("Matrix joinHandler requires a room ID or alias");
|
|
374
|
+
}
|
|
375
|
+
await service.joinRoom(roomIdOrAlias, accountId);
|
|
376
|
+
},
|
|
377
|
+
leaveHandler: async (handlerRuntime, params) => {
|
|
378
|
+
const target = params.target ?? { source: MATRIX_SERVICE_NAME };
|
|
379
|
+
const room = target.roomId ? await handlerRuntime.getRoom(target.roomId) : null;
|
|
380
|
+
const roomId = String(params?.roomId ?? params?.channelId ?? target.channelId ?? room?.channelId ?? "");
|
|
381
|
+
if (!roomId) {
|
|
382
|
+
throw new Error("Matrix leaveHandler requires a room ID");
|
|
383
|
+
}
|
|
384
|
+
await service.leaveRoom(roomId, accountId);
|
|
385
|
+
},
|
|
386
|
+
getChatContext: async (target, context) => {
|
|
387
|
+
const room = target.roomId ? await context.runtime.getRoom(target.roomId) : null;
|
|
388
|
+
const channelId = String(target.channelId ?? room?.channelId ?? "").trim();
|
|
389
|
+
const joinedRoom = (await service.getJoinedRooms(accountId)).find((candidate) => candidate.roomId === channelId || candidate.canonicalAlias === channelId);
|
|
390
|
+
if (!joinedRoom) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
target: {
|
|
395
|
+
source: MATRIX_SERVICE_NAME,
|
|
396
|
+
accountId,
|
|
397
|
+
channelId: joinedRoom.roomId,
|
|
398
|
+
roomId: target.roomId
|
|
399
|
+
},
|
|
400
|
+
label: joinedRoom.name || joinedRoom.canonicalAlias || joinedRoom.roomId,
|
|
401
|
+
summary: joinedRoom.topic,
|
|
402
|
+
metadata: {
|
|
403
|
+
accountId,
|
|
404
|
+
roomId: joinedRoom.roomId,
|
|
405
|
+
canonicalAlias: joinedRoom.canonicalAlias,
|
|
406
|
+
isEncrypted: joinedRoom.isEncrypted,
|
|
407
|
+
isDirect: joinedRoom.isDirect,
|
|
408
|
+
memberCount: joinedRoom.memberCount
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
},
|
|
412
|
+
getUserContext: async (entityId, context) => {
|
|
413
|
+
if (typeof context.runtime.getEntityById !== "function") {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
const entity = await context.runtime.getEntityById(String(entityId));
|
|
417
|
+
if (!entity) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
entityId,
|
|
422
|
+
label: entity.names?.[0],
|
|
423
|
+
aliases: entity.names,
|
|
424
|
+
handles: {},
|
|
425
|
+
metadata: entity.metadata
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
runtime.registerMessageConnector(registration);
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
runtime.registerSendHandler(MATRIX_SERVICE_NAME, sendHandler);
|
|
433
|
+
}
|
|
114
434
|
async initialize(runtime) {
|
|
115
435
|
this.runtime = runtime;
|
|
116
|
-
this.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
436
|
+
this.defaultAccountId = normalizeMatrixAccountId(resolveDefaultMatrixAccountId(runtime));
|
|
437
|
+
const accountIds = listMatrixAccountIds(runtime);
|
|
438
|
+
for (const accountId of accountIds) {
|
|
439
|
+
const settings = this.loadSettings(accountId);
|
|
440
|
+
if (settings.enabled === false) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
this.validateSettings(settings);
|
|
444
|
+
const state = {
|
|
445
|
+
accountId: normalizeMatrixAccountId(settings.accountId),
|
|
446
|
+
settings,
|
|
447
|
+
client: sdk.createClient({
|
|
448
|
+
baseUrl: settings.homeserver,
|
|
449
|
+
userId: settings.userId,
|
|
450
|
+
accessToken: settings.accessToken,
|
|
451
|
+
deviceId: settings.deviceId
|
|
452
|
+
}),
|
|
453
|
+
connected: false,
|
|
454
|
+
syncing: false
|
|
455
|
+
};
|
|
456
|
+
this.states.set(state.accountId, state);
|
|
457
|
+
this.setupEventHandlers(state);
|
|
458
|
+
await this.connect(state);
|
|
459
|
+
MatrixService.registerSendHandlers(runtime, this, state.accountId);
|
|
460
|
+
logger.info(`Matrix service initialized for ${settings.userId} on ${settings.homeserver}`);
|
|
461
|
+
}
|
|
462
|
+
if (this.states.size === 0) {
|
|
463
|
+
const settings = this.loadSettings(this.defaultAccountId);
|
|
464
|
+
this.validateSettings(settings);
|
|
465
|
+
}
|
|
127
466
|
}
|
|
128
|
-
loadSettings() {
|
|
129
|
-
|
|
130
|
-
const value = this.runtime.getSetting(key);
|
|
131
|
-
return typeof value === "string" ? value : undefined;
|
|
132
|
-
};
|
|
133
|
-
const homeserver = getStringSetting("MATRIX_HOMESERVER");
|
|
134
|
-
const userId = getStringSetting("MATRIX_USER_ID");
|
|
135
|
-
const accessToken = getStringSetting("MATRIX_ACCESS_TOKEN");
|
|
136
|
-
const deviceId = getStringSetting("MATRIX_DEVICE_ID");
|
|
137
|
-
const roomsStr = getStringSetting("MATRIX_ROOMS");
|
|
138
|
-
const autoJoinStr = getStringSetting("MATRIX_AUTO_JOIN");
|
|
139
|
-
const encryptionStr = getStringSetting("MATRIX_ENCRYPTION");
|
|
140
|
-
const requireMentionStr = getStringSetting("MATRIX_REQUIRE_MENTION");
|
|
141
|
-
const rooms = roomsStr ? roomsStr.split(",").map((r) => r.trim()).filter(Boolean) : [];
|
|
142
|
-
return {
|
|
143
|
-
homeserver: homeserver || "",
|
|
144
|
-
userId: userId || "",
|
|
145
|
-
accessToken: accessToken || "",
|
|
146
|
-
deviceId,
|
|
147
|
-
rooms,
|
|
148
|
-
autoJoin: autoJoinStr === "true",
|
|
149
|
-
encryption: encryptionStr === "true",
|
|
150
|
-
requireMention: requireMentionStr === "true",
|
|
151
|
-
enabled: true
|
|
152
|
-
};
|
|
467
|
+
loadSettings(accountId) {
|
|
468
|
+
return resolveMatrixAccountSettings(this.runtime, accountId);
|
|
153
469
|
}
|
|
154
|
-
validateSettings() {
|
|
155
|
-
if (!
|
|
470
|
+
validateSettings(settings) {
|
|
471
|
+
if (!settings.homeserver) {
|
|
156
472
|
throw new MatrixConfigurationError("MATRIX_HOMESERVER is required", "MATRIX_HOMESERVER");
|
|
157
473
|
}
|
|
158
|
-
if (!
|
|
474
|
+
if (!settings.userId) {
|
|
159
475
|
throw new MatrixConfigurationError("MATRIX_USER_ID is required", "MATRIX_USER_ID");
|
|
160
476
|
}
|
|
161
|
-
if (!
|
|
477
|
+
if (!settings.accessToken) {
|
|
162
478
|
throw new MatrixConfigurationError("MATRIX_ACCESS_TOKEN is required", "MATRIX_ACCESS_TOKEN");
|
|
163
479
|
}
|
|
164
480
|
}
|
|
165
|
-
setupEventHandlers() {
|
|
166
|
-
|
|
167
|
-
if (
|
|
168
|
-
|
|
481
|
+
setupEventHandlers(state) {
|
|
482
|
+
state.client.on(sdk.ClientEvent.Sync, (syncState) => {
|
|
483
|
+
if (syncState === "PREPARED") {
|
|
484
|
+
state.syncing = true;
|
|
169
485
|
logger.info("Matrix sync complete");
|
|
170
486
|
this.runtime.emitEvent("MATRIX_SYNC_COMPLETE" /* SYNC_COMPLETE */, {
|
|
171
|
-
runtime: this.runtime
|
|
487
|
+
runtime: this.runtime,
|
|
488
|
+
accountId: state.accountId
|
|
172
489
|
});
|
|
173
490
|
}
|
|
174
491
|
});
|
|
175
|
-
|
|
492
|
+
state.client.on(sdk.RoomEvent.Timeline, (event, room, toStartOfTimeline) => {
|
|
176
493
|
if (toStartOfTimeline)
|
|
177
494
|
return;
|
|
178
495
|
if (event.getType() !== "m.room.message")
|
|
179
496
|
return;
|
|
180
|
-
if (event.getSender() ===
|
|
497
|
+
if (event.getSender() === state.settings.userId)
|
|
181
498
|
return;
|
|
182
|
-
this.handleRoomMessage(event, room);
|
|
499
|
+
this.handleRoomMessage(state, event, room);
|
|
183
500
|
});
|
|
184
|
-
|
|
185
|
-
if (member.userId !==
|
|
501
|
+
state.client.on(sdk.RoomMemberEvent.Membership, (event, member) => {
|
|
502
|
+
if (member.userId !== state.settings.userId)
|
|
186
503
|
return;
|
|
187
|
-
if (member.membership === "invite" &&
|
|
504
|
+
if (member.membership === "invite" && state.settings.autoJoin) {
|
|
188
505
|
const roomId = event.getRoomId();
|
|
189
506
|
if (roomId) {
|
|
190
507
|
logger.info(`Auto-joining room ${roomId}`);
|
|
191
|
-
|
|
508
|
+
state.client.joinRoom(roomId).catch((err) => {
|
|
192
509
|
logger.error(`Failed to auto-join room: ${err.message}`);
|
|
193
510
|
});
|
|
194
511
|
}
|
|
195
512
|
}
|
|
196
513
|
});
|
|
197
514
|
}
|
|
198
|
-
handleRoomMessage(event, room) {
|
|
515
|
+
handleRoomMessage(state, event, room) {
|
|
199
516
|
const content = event.getContent();
|
|
200
517
|
const msgType = content.msgtype;
|
|
201
518
|
if (msgType !== "m.text")
|
|
@@ -203,9 +520,9 @@ class MatrixService extends Service {
|
|
|
203
520
|
const roomId = event.getRoomId();
|
|
204
521
|
if (!roomId || !room)
|
|
205
522
|
return;
|
|
206
|
-
if (
|
|
523
|
+
if (state.settings.requireMention) {
|
|
207
524
|
const body = content.body || "";
|
|
208
|
-
const localpart = getMatrixLocalpart(
|
|
525
|
+
const localpart = getMatrixLocalpart(state.settings.userId);
|
|
209
526
|
const mentionPattern = new RegExp(`@?${localpart}`, "i");
|
|
210
527
|
if (!mentionPattern.test(body)) {
|
|
211
528
|
return;
|
|
@@ -242,54 +559,70 @@ class MatrixService extends Service {
|
|
|
242
559
|
topic: room.currentState.getStateEvents("m.room.topic", "")?.getContent()?.topic,
|
|
243
560
|
canonicalAlias: room.getCanonicalAlias() || undefined,
|
|
244
561
|
isEncrypted: room.hasEncryptionStateEvent(),
|
|
245
|
-
isDirect:
|
|
562
|
+
isDirect: state.client.getAccountData(sdk.EventType.Direct)?.getContent()?.[sender || ""]?.includes(roomId) || false,
|
|
246
563
|
memberCount: room.getJoinedMemberCount()
|
|
247
564
|
};
|
|
248
565
|
logger.debug(`Matrix message from ${senderInfo.displayName || sender} in ${room.name || roomId}: ${message.content.slice(0, 50)}...`);
|
|
249
566
|
this.runtime.emitEvent("MATRIX_MESSAGE_RECEIVED" /* MESSAGE_RECEIVED */, {
|
|
250
567
|
message,
|
|
251
568
|
room: matrixRoom,
|
|
252
|
-
runtime: this.runtime
|
|
569
|
+
runtime: this.runtime,
|
|
570
|
+
accountId: state.accountId
|
|
253
571
|
});
|
|
254
572
|
}
|
|
255
|
-
async connect() {
|
|
256
|
-
await
|
|
257
|
-
|
|
573
|
+
async connect(state) {
|
|
574
|
+
await state.client.startClient({ initialSyncLimit: 10 });
|
|
575
|
+
state.connected = true;
|
|
258
576
|
await new Promise((resolve) => {
|
|
259
|
-
const listener = (
|
|
260
|
-
if (
|
|
261
|
-
|
|
577
|
+
const listener = (syncState) => {
|
|
578
|
+
if (syncState === "PREPARED") {
|
|
579
|
+
state.client.removeListener(sdk.ClientEvent.Sync, listener);
|
|
262
580
|
resolve();
|
|
263
581
|
}
|
|
264
582
|
};
|
|
265
|
-
|
|
583
|
+
state.client.on(sdk.ClientEvent.Sync, listener);
|
|
266
584
|
});
|
|
267
|
-
for (const room of
|
|
585
|
+
for (const room of state.settings.rooms) {
|
|
268
586
|
try {
|
|
269
|
-
await this.joinRoom(room);
|
|
587
|
+
await this.joinRoom(room, state.accountId);
|
|
270
588
|
} catch (err) {
|
|
271
589
|
logger.warn(`Failed to join room ${room}: ${err}`);
|
|
272
590
|
}
|
|
273
591
|
}
|
|
274
592
|
}
|
|
275
593
|
async stop() {
|
|
276
|
-
|
|
277
|
-
|
|
594
|
+
for (const state of this.states.values()) {
|
|
595
|
+
state.client.stopClient();
|
|
596
|
+
state.connected = false;
|
|
597
|
+
state.syncing = false;
|
|
278
598
|
}
|
|
279
|
-
this.connected = false;
|
|
280
599
|
logger.info("Matrix service stopped");
|
|
281
600
|
}
|
|
282
601
|
isConnected() {
|
|
283
|
-
|
|
602
|
+
const legacy = this;
|
|
603
|
+
const states = this.states ?? new Map;
|
|
604
|
+
if (states.size === 0 && typeof legacy.connected === "boolean") {
|
|
605
|
+
return legacy.connected && (legacy.syncing ?? true);
|
|
606
|
+
}
|
|
607
|
+
return Array.from(states.values()).some((state) => state.connected && state.syncing);
|
|
608
|
+
}
|
|
609
|
+
getAccountId(runtime) {
|
|
610
|
+
const legacy = this;
|
|
611
|
+
const states = this.states ?? new Map;
|
|
612
|
+
if (states.size === 0 && legacy.settings?.accountId) {
|
|
613
|
+
return normalizeMatrixAccountId(legacy.settings.accountId);
|
|
614
|
+
}
|
|
615
|
+
return normalizeMatrixAccountId(this.defaultAccountId !== DEFAULT_MATRIX_ACCOUNT_ID ? this.defaultAccountId : runtime ? resolveDefaultMatrixAccountId(runtime) : this.defaultAccountId);
|
|
284
616
|
}
|
|
285
617
|
getUserId() {
|
|
286
|
-
return this.settings.userId;
|
|
618
|
+
return this.getState().settings.userId;
|
|
287
619
|
}
|
|
288
620
|
getHomeserver() {
|
|
289
|
-
return this.settings.homeserver;
|
|
621
|
+
return this.getState().settings.homeserver;
|
|
290
622
|
}
|
|
291
|
-
async getJoinedRooms() {
|
|
292
|
-
const
|
|
623
|
+
async getJoinedRooms(accountId) {
|
|
624
|
+
const state = this.getState(accountId);
|
|
625
|
+
const rooms = state.client.getRooms();
|
|
293
626
|
return rooms.filter((room) => room.getMyMembership() === "join").map((room) => ({
|
|
294
627
|
roomId: room.roomId,
|
|
295
628
|
name: room.name,
|
|
@@ -301,7 +634,8 @@ class MatrixService extends Service {
|
|
|
301
634
|
}));
|
|
302
635
|
}
|
|
303
636
|
async sendMessage(text, options) {
|
|
304
|
-
|
|
637
|
+
const state = this.getState(options?.accountId);
|
|
638
|
+
if (!state.connected || !state.syncing) {
|
|
305
639
|
throw new MatrixNotConnectedError;
|
|
306
640
|
}
|
|
307
641
|
const roomId = options?.roomId;
|
|
@@ -310,11 +644,11 @@ class MatrixService extends Service {
|
|
|
310
644
|
}
|
|
311
645
|
let resolvedRoomId = roomId;
|
|
312
646
|
if (isValidMatrixRoomAlias(roomId)) {
|
|
313
|
-
const resolved = await
|
|
647
|
+
const resolved = await state.client.getRoomIdForAlias(roomId);
|
|
314
648
|
resolvedRoomId = resolved.room_id;
|
|
315
649
|
}
|
|
316
650
|
const content = {
|
|
317
|
-
msgtype:
|
|
651
|
+
msgtype: sdk.MsgType.Text,
|
|
318
652
|
body: text
|
|
319
653
|
};
|
|
320
654
|
if (options?.formatted) {
|
|
@@ -324,7 +658,7 @@ class MatrixService extends Service {
|
|
|
324
658
|
if (options?.threadId || options?.replyTo) {
|
|
325
659
|
content["m.relates_to"] = {};
|
|
326
660
|
if (options.threadId) {
|
|
327
|
-
content["m.relates_to"].rel_type =
|
|
661
|
+
content["m.relates_to"].rel_type = sdk.RelationType.Thread;
|
|
328
662
|
content["m.relates_to"].event_id = options.threadId;
|
|
329
663
|
}
|
|
330
664
|
if (options.replyTo) {
|
|
@@ -333,13 +667,14 @@ class MatrixService extends Service {
|
|
|
333
667
|
};
|
|
334
668
|
}
|
|
335
669
|
}
|
|
336
|
-
const response = await
|
|
670
|
+
const response = await state.client.sendMessage(resolvedRoomId, content);
|
|
337
671
|
const eventId = response.event_id;
|
|
338
672
|
this.runtime.emitEvent("MATRIX_MESSAGE_SENT" /* MESSAGE_SENT */, {
|
|
339
673
|
roomId: resolvedRoomId,
|
|
340
674
|
eventId,
|
|
341
675
|
content: text,
|
|
342
|
-
runtime: this.runtime
|
|
676
|
+
runtime: this.runtime,
|
|
677
|
+
accountId: state.accountId
|
|
343
678
|
});
|
|
344
679
|
return {
|
|
345
680
|
success: true,
|
|
@@ -347,618 +682,233 @@ class MatrixService extends Service {
|
|
|
347
682
|
roomId: resolvedRoomId
|
|
348
683
|
};
|
|
349
684
|
}
|
|
350
|
-
async sendReaction(roomId, eventId, emoji) {
|
|
351
|
-
|
|
685
|
+
async sendReaction(roomId, eventId, emoji, accountId) {
|
|
686
|
+
const state = this.getState(accountId);
|
|
687
|
+
if (!state.connected || !state.syncing) {
|
|
352
688
|
throw new MatrixNotConnectedError;
|
|
353
689
|
}
|
|
354
690
|
const content = {
|
|
355
691
|
"m.relates_to": {
|
|
356
|
-
rel_type:
|
|
692
|
+
rel_type: sdk.RelationType.Annotation,
|
|
357
693
|
event_id: eventId,
|
|
358
694
|
key: emoji
|
|
359
695
|
}
|
|
360
696
|
};
|
|
361
|
-
const response = await
|
|
697
|
+
const response = await state.client.sendEvent(roomId, sdk.EventType.Reaction, content);
|
|
362
698
|
return {
|
|
363
699
|
success: true,
|
|
364
700
|
eventId: response.event_id,
|
|
365
701
|
roomId
|
|
366
702
|
};
|
|
367
703
|
}
|
|
368
|
-
async joinRoom(roomIdOrAlias) {
|
|
369
|
-
|
|
704
|
+
async joinRoom(roomIdOrAlias, accountId) {
|
|
705
|
+
const state = this.getState(accountId);
|
|
706
|
+
if (!state.connected || !state.syncing) {
|
|
370
707
|
throw new MatrixNotConnectedError;
|
|
371
708
|
}
|
|
372
|
-
const response = await
|
|
709
|
+
const response = await state.client.joinRoom(roomIdOrAlias);
|
|
373
710
|
const roomId = response.roomId;
|
|
374
711
|
logger.info(`Joined room ${roomId}`);
|
|
375
712
|
this.runtime.emitEvent("MATRIX_ROOM_JOINED" /* ROOM_JOINED */, {
|
|
376
713
|
room: { roomId },
|
|
377
|
-
runtime: this.runtime
|
|
714
|
+
runtime: this.runtime,
|
|
715
|
+
accountId: state.accountId
|
|
378
716
|
});
|
|
379
717
|
return roomId;
|
|
380
718
|
}
|
|
381
|
-
async leaveRoom(roomId) {
|
|
382
|
-
|
|
719
|
+
async leaveRoom(roomId, accountId) {
|
|
720
|
+
const state = this.getState(accountId);
|
|
721
|
+
if (!state.connected || !state.syncing) {
|
|
383
722
|
throw new MatrixNotConnectedError;
|
|
384
723
|
}
|
|
385
|
-
await
|
|
724
|
+
await state.client.leave(roomId);
|
|
386
725
|
logger.info(`Left room ${roomId}`);
|
|
387
726
|
this.runtime.emitEvent("MATRIX_ROOM_LEFT" /* ROOM_LEFT */, {
|
|
388
727
|
roomId,
|
|
389
|
-
runtime: this.runtime
|
|
728
|
+
runtime: this.runtime,
|
|
729
|
+
accountId: state.accountId
|
|
390
730
|
});
|
|
391
731
|
}
|
|
392
|
-
async sendTyping(roomId, typing, timeout = 30000) {
|
|
393
|
-
|
|
732
|
+
async sendTyping(roomId, typing, timeout = 30000, accountId) {
|
|
733
|
+
const state = this.getState(accountId);
|
|
734
|
+
if (!state.connected || !state.syncing) {
|
|
394
735
|
return;
|
|
395
736
|
}
|
|
396
|
-
await
|
|
737
|
+
await state.client.sendTyping(roomId, typing, timeout);
|
|
397
738
|
}
|
|
398
|
-
async sendReadReceipt(roomId, eventId) {
|
|
399
|
-
|
|
739
|
+
async sendReadReceipt(roomId, eventId, accountId) {
|
|
740
|
+
const state = this.getState(accountId);
|
|
741
|
+
if (!state.connected || !state.syncing) {
|
|
400
742
|
return;
|
|
401
743
|
}
|
|
402
|
-
await
|
|
744
|
+
await state.client.sendReadReceipt(new sdk.MatrixEvent({ event_id: eventId, room_id: roomId }));
|
|
403
745
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
The user wants to join a Matrix room.
|
|
410
|
-
|
|
411
|
-
Recent conversation:
|
|
412
|
-
{{recentMessages}}
|
|
413
|
-
|
|
414
|
-
Extract the room ID (!room:server) or room alias (#alias:server) to join.
|
|
415
|
-
|
|
416
|
-
Respond with a JSON object like:
|
|
417
|
-
{
|
|
418
|
-
"room": "!room:matrix.org"
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
or:
|
|
422
|
-
|
|
423
|
-
{
|
|
424
|
-
"room": "#alias:matrix.org"
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
Only respond with the JSON object, no other text.`;
|
|
428
|
-
var joinRoom = {
|
|
429
|
-
name: "MATRIX_JOIN_ROOM",
|
|
430
|
-
similes: ["JOIN_MATRIX_ROOM", "ENTER_ROOM"],
|
|
431
|
-
description: "Join a Matrix room by ID or alias",
|
|
432
|
-
validate: async (_runtime, message, _state) => {
|
|
433
|
-
return message.content.source === "matrix";
|
|
434
|
-
},
|
|
435
|
-
handler: async (runtime, message, state, _options, callback) => {
|
|
436
|
-
const matrixService = runtime.getService(MATRIX_SERVICE_NAME);
|
|
437
|
-
if (!matrixService || !matrixService.isConnected()) {
|
|
438
|
-
if (callback) {
|
|
439
|
-
await callback({ text: "Matrix service is not available.", source: "matrix" });
|
|
440
|
-
}
|
|
441
|
-
return { success: false, error: "Matrix service not available" };
|
|
746
|
+
async sendRoomMessage(roomIdOrAlias, content) {
|
|
747
|
+
const text = typeof content.text === "string" ? content.text.trim() : "";
|
|
748
|
+
if (!text) {
|
|
749
|
+
return;
|
|
442
750
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
text: ""
|
|
447
|
-
};
|
|
448
|
-
const prompt = await composePromptFromState({
|
|
449
|
-
template: JOIN_ROOM_TEMPLATE,
|
|
450
|
-
state: composedState
|
|
751
|
+
await this.sendMessage(text, {
|
|
752
|
+
accountId: readMatrixAccountId(content) ?? this.getAccountId(),
|
|
753
|
+
roomId: roomIdOrAlias
|
|
451
754
|
});
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
break;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
755
|
+
}
|
|
756
|
+
async sendDirectMessage(roomIdOrAlias, content) {
|
|
757
|
+
await this.sendRoomMessage(roomIdOrAlias, content);
|
|
758
|
+
}
|
|
759
|
+
async handleSendMessage(runtime, target, content) {
|
|
760
|
+
const requestedAccountId = normalizeMatrixAccountId(target.accountId ?? readMatrixAccountId(content, target) ?? this.getAccountId());
|
|
761
|
+
this.getState(requestedAccountId);
|
|
762
|
+
const text = typeof content.text === "string" ? content.text.trim() : "";
|
|
763
|
+
if (!text) {
|
|
764
|
+
return;
|
|
465
765
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
source: "matrix"
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
return { success: false, error: "Could not extract room identifier" };
|
|
766
|
+
const room = target.roomId ? await runtime.getRoom(target.roomId) : null;
|
|
767
|
+
const roomIdOrAlias = String(target.channelId || room?.channelId || (typeof target.roomId === "string" && (isValidMatrixRoomId(target.roomId) || isValidMatrixRoomAlias(target.roomId)) ? target.roomId : "")).trim();
|
|
768
|
+
if (!roomIdOrAlias) {
|
|
769
|
+
throw new Error("Matrix target is missing a room ID or alias");
|
|
474
770
|
}
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
771
|
+
await this.sendMessage(text, {
|
|
772
|
+
accountId: requestedAccountId,
|
|
773
|
+
roomId: roomIdOrAlias,
|
|
774
|
+
...extractMatrixSendOptions(content, target)
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
getState(accountId = this.defaultAccountId) {
|
|
778
|
+
const normalized = normalizeMatrixAccountId(accountId);
|
|
779
|
+
const states = this.states ?? new Map;
|
|
780
|
+
const state = states.get(normalized);
|
|
781
|
+
if (state) {
|
|
782
|
+
return state;
|
|
783
|
+
}
|
|
784
|
+
const legacy = this;
|
|
785
|
+
if (legacy.settings) {
|
|
483
786
|
return {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
787
|
+
accountId: normalizeMatrixAccountId(legacy.settings.accountId ?? normalized),
|
|
788
|
+
settings: legacy.settings,
|
|
789
|
+
client: legacy.client ?? {},
|
|
790
|
+
connected: legacy.connected ?? true,
|
|
791
|
+
syncing: legacy.syncing ?? true
|
|
489
792
|
};
|
|
490
|
-
} catch (err) {
|
|
491
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
492
|
-
if (callback) {
|
|
493
|
-
await callback({
|
|
494
|
-
text: `Failed to join room: ${error}`,
|
|
495
|
-
source: "matrix"
|
|
496
|
-
});
|
|
497
|
-
}
|
|
498
|
-
return { success: false, error };
|
|
499
793
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
[
|
|
503
|
-
{
|
|
504
|
-
name: "{{user1}}",
|
|
505
|
-
content: { text: "Join #general:matrix.org" }
|
|
506
|
-
},
|
|
507
|
-
{
|
|
508
|
-
name: "{{agent}}",
|
|
509
|
-
content: {
|
|
510
|
-
text: "I'll join that room.",
|
|
511
|
-
actions: ["MATRIX_JOIN_ROOM"]
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
]
|
|
515
|
-
]
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
// src/actions/listRooms.ts
|
|
519
|
-
var listRooms = {
|
|
520
|
-
name: "MATRIX_LIST_ROOMS",
|
|
521
|
-
similes: ["LIST_MATRIX_ROOMS", "SHOW_ROOMS", "GET_ROOMS", "MY_ROOMS"],
|
|
522
|
-
description: "List all Matrix rooms the bot has joined",
|
|
523
|
-
validate: async (_runtime, message, _state) => {
|
|
524
|
-
return message.content.source === "matrix";
|
|
525
|
-
},
|
|
526
|
-
handler: async (runtime, message, _state, _options, callback) => {
|
|
527
|
-
const matrixService = runtime.getService(MATRIX_SERVICE_NAME);
|
|
528
|
-
if (!matrixService || !matrixService.isConnected()) {
|
|
529
|
-
if (callback) {
|
|
530
|
-
await callback({ text: "Matrix service is not available.", source: "matrix" });
|
|
531
|
-
}
|
|
532
|
-
return { success: false, error: "Matrix service not available" };
|
|
533
|
-
}
|
|
534
|
-
const rooms = await matrixService.getJoinedRooms();
|
|
535
|
-
const roomList = rooms.map((room) => {
|
|
536
|
-
const name = room.name || room.canonicalAlias || room.roomId;
|
|
537
|
-
const members = `${room.memberCount} members`;
|
|
538
|
-
const encrypted = room.isEncrypted ? " (encrypted)" : "";
|
|
539
|
-
return `- ${name} (${members})${encrypted}`;
|
|
540
|
-
});
|
|
541
|
-
const responseText = rooms.length > 0 ? `Joined ${rooms.length} room(s):
|
|
542
|
-
|
|
543
|
-
${roomList.join(`
|
|
544
|
-
`)}` : "Not currently in any rooms.";
|
|
545
|
-
if (callback) {
|
|
546
|
-
await callback({
|
|
547
|
-
text: responseText,
|
|
548
|
-
source: message.content.source
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
return {
|
|
552
|
-
success: true,
|
|
553
|
-
data: {
|
|
554
|
-
roomCount: rooms.length,
|
|
555
|
-
rooms: rooms.map((r) => ({
|
|
556
|
-
roomId: r.roomId,
|
|
557
|
-
name: r.name,
|
|
558
|
-
alias: r.canonicalAlias,
|
|
559
|
-
memberCount: r.memberCount,
|
|
560
|
-
isEncrypted: r.isEncrypted
|
|
561
|
-
}))
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
},
|
|
565
|
-
examples: [
|
|
566
|
-
[
|
|
567
|
-
{
|
|
568
|
-
name: "{{user1}}",
|
|
569
|
-
content: { text: "What rooms are you in?" }
|
|
570
|
-
},
|
|
571
|
-
{
|
|
572
|
-
name: "{{agent}}",
|
|
573
|
-
content: {
|
|
574
|
-
text: "I'll list the rooms I've joined.",
|
|
575
|
-
actions: ["MATRIX_LIST_ROOMS"]
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
]
|
|
579
|
-
]
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
// src/actions/sendMessage.ts
|
|
583
|
-
import { composePromptFromState as composePromptFromState2, ModelType as ModelType2, parseJSONObjectFromText as parseJSONObjectFromText2 } from "@elizaos/core";
|
|
584
|
-
var SEND_MESSAGE_TEMPLATE = `You are helping to extract send message parameters for Matrix.
|
|
585
|
-
|
|
586
|
-
The user wants to send a message to a Matrix room.
|
|
587
|
-
|
|
588
|
-
Recent conversation:
|
|
589
|
-
{{recentMessages}}
|
|
590
|
-
|
|
591
|
-
Extract the following:
|
|
592
|
-
1. text: The message text to send
|
|
593
|
-
2. roomId: The room ID (!room:server) or alias (#alias:server), or "current" for the current room
|
|
594
|
-
|
|
595
|
-
Respond with a JSON object like:
|
|
596
|
-
{
|
|
597
|
-
"text": "The message to send",
|
|
598
|
-
"roomId": "current"
|
|
794
|
+
throw new Error(`Matrix account '${normalized}' is not available in this service instance`);
|
|
795
|
+
}
|
|
599
796
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
return message.content.source === "matrix";
|
|
608
|
-
},
|
|
609
|
-
handler: async (runtime, message, state, _options, callback) => {
|
|
610
|
-
const matrixService = runtime.getService(MATRIX_SERVICE_NAME);
|
|
611
|
-
if (!matrixService || !matrixService.isConnected()) {
|
|
612
|
-
if (callback) {
|
|
613
|
-
await callback({ text: "Matrix service is not available.", source: "matrix" });
|
|
614
|
-
}
|
|
615
|
-
return { success: false, error: "Matrix service not available" };
|
|
616
|
-
}
|
|
617
|
-
const composedState = state ?? {
|
|
618
|
-
values: {},
|
|
619
|
-
data: {},
|
|
620
|
-
text: ""
|
|
621
|
-
};
|
|
622
|
-
const prompt = await composePromptFromState2({
|
|
623
|
-
template: SEND_MESSAGE_TEMPLATE,
|
|
624
|
-
state: composedState
|
|
625
|
-
});
|
|
626
|
-
let messageInfo = null;
|
|
627
|
-
for (let attempt = 0;attempt < 3; attempt++) {
|
|
628
|
-
const response = await runtime.useModel(ModelType2.TEXT_SMALL, {
|
|
629
|
-
prompt
|
|
630
|
-
});
|
|
631
|
-
const parsed = parseJSONObjectFromText2(response);
|
|
632
|
-
if (parsed?.text) {
|
|
633
|
-
messageInfo = {
|
|
634
|
-
text: String(parsed.text),
|
|
635
|
-
roomId: String(parsed.roomId || "current")
|
|
636
|
-
};
|
|
637
|
-
break;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
if (!messageInfo || !messageInfo.text) {
|
|
641
|
-
if (callback) {
|
|
642
|
-
await callback({
|
|
643
|
-
text: "I couldn't understand what message you want me to send. Please try again.",
|
|
644
|
-
source: "matrix"
|
|
645
|
-
});
|
|
646
|
-
}
|
|
647
|
-
return { success: false, error: "Could not extract message parameters" };
|
|
648
|
-
}
|
|
649
|
-
let targetRoomId;
|
|
650
|
-
if (messageInfo.roomId && messageInfo.roomId !== "current") {
|
|
651
|
-
if (isValidMatrixRoomId(messageInfo.roomId) || isValidMatrixRoomAlias(messageInfo.roomId)) {
|
|
652
|
-
targetRoomId = messageInfo.roomId;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
const roomData = state?.data?.room;
|
|
656
|
-
if (!targetRoomId && roomData?.roomId) {
|
|
657
|
-
targetRoomId = roomData.roomId;
|
|
658
|
-
}
|
|
659
|
-
if (!targetRoomId) {
|
|
660
|
-
if (callback) {
|
|
661
|
-
await callback({
|
|
662
|
-
text: "I couldn't determine which room to send to. Please specify a room.",
|
|
663
|
-
source: "matrix"
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
return { success: false, error: "Could not determine target room" };
|
|
667
|
-
}
|
|
668
|
-
const result = await matrixService.sendMessage(messageInfo.text, {
|
|
669
|
-
roomId: targetRoomId
|
|
670
|
-
});
|
|
671
|
-
if (!result.success) {
|
|
672
|
-
if (callback) {
|
|
673
|
-
await callback({
|
|
674
|
-
text: `Failed to send message: ${result.error}`,
|
|
675
|
-
source: "matrix"
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
return { success: false, error: result.error };
|
|
679
|
-
}
|
|
680
|
-
if (callback) {
|
|
681
|
-
await callback({
|
|
682
|
-
text: "Message sent successfully.",
|
|
683
|
-
source: message.content.source
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
return {
|
|
687
|
-
success: true,
|
|
688
|
-
data: {
|
|
689
|
-
roomId: result.roomId,
|
|
690
|
-
eventId: result.eventId
|
|
691
|
-
}
|
|
692
|
-
};
|
|
693
|
-
},
|
|
694
|
-
examples: [
|
|
695
|
-
[
|
|
696
|
-
{
|
|
697
|
-
name: "{{user1}}",
|
|
698
|
-
content: { text: "Send a message saying 'Hello everyone!'" }
|
|
699
|
-
},
|
|
700
|
-
{
|
|
701
|
-
name: "{{agent}}",
|
|
702
|
-
content: {
|
|
703
|
-
text: "I'll send that message to the room.",
|
|
704
|
-
actions: ["MATRIX_SEND_MESSAGE"]
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
]
|
|
708
|
-
]
|
|
709
|
-
};
|
|
710
|
-
|
|
711
|
-
// src/actions/sendReaction.ts
|
|
712
|
-
import { composePromptFromState as composePromptFromState3, ModelType as ModelType3, parseJSONObjectFromText as parseJSONObjectFromText3 } from "@elizaos/core";
|
|
713
|
-
var SEND_REACTION_TEMPLATE = `You are helping to extract reaction parameters for Matrix.
|
|
714
|
-
|
|
715
|
-
The user wants to react to a Matrix message with an emoji.
|
|
716
|
-
|
|
717
|
-
Recent conversation:
|
|
718
|
-
{{recentMessages}}
|
|
719
|
-
|
|
720
|
-
Extract the following:
|
|
721
|
-
1. emoji: The emoji to react with (single emoji character)
|
|
722
|
-
2. eventId: The event ID of the message to react to (starts with $)
|
|
723
|
-
|
|
724
|
-
Respond with a JSON object like:
|
|
725
|
-
{
|
|
726
|
-
"emoji": "\uD83D\uDC4D",
|
|
727
|
-
"eventId": "$event123"
|
|
797
|
+
// src/connector-account-provider.ts
|
|
798
|
+
var MATRIX_PROVIDER_ID = "matrix";
|
|
799
|
+
function accountKey(settings) {
|
|
800
|
+
if (settings.homeserver && settings.userId) {
|
|
801
|
+
return `${settings.homeserver}/${settings.userId}`;
|
|
802
|
+
}
|
|
803
|
+
return normalizeMatrixAccountId(settings.accountId);
|
|
728
804
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
if (!reactionInfo) {
|
|
770
|
-
if (callback) {
|
|
771
|
-
await callback({
|
|
772
|
-
text: "I couldn't understand the reaction request. Please specify the emoji and message.",
|
|
773
|
-
source: "matrix"
|
|
774
|
-
});
|
|
775
|
-
}
|
|
776
|
-
return { success: false, error: "Could not extract reaction parameters" };
|
|
777
|
-
}
|
|
778
|
-
const roomData = state?.data?.room;
|
|
779
|
-
const roomId = roomData?.roomId;
|
|
780
|
-
if (!roomId) {
|
|
781
|
-
if (callback) {
|
|
782
|
-
await callback({
|
|
783
|
-
text: "I couldn't determine which room this is in.",
|
|
784
|
-
source: "matrix"
|
|
785
|
-
});
|
|
786
|
-
}
|
|
787
|
-
return { success: false, error: "Could not determine room" };
|
|
788
|
-
}
|
|
789
|
-
const result = await matrixService.sendReaction(roomId, reactionInfo.eventId, reactionInfo.emoji);
|
|
790
|
-
if (!result.success) {
|
|
791
|
-
if (callback) {
|
|
792
|
-
await callback({
|
|
793
|
-
text: `Failed to add reaction: ${result.error}`,
|
|
794
|
-
source: "matrix"
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
return { success: false, error: result.error };
|
|
798
|
-
}
|
|
799
|
-
if (callback) {
|
|
800
|
-
await callback({
|
|
801
|
-
text: `Added ${reactionInfo.emoji} reaction.`,
|
|
802
|
-
source: message.content.source
|
|
803
|
-
});
|
|
804
|
-
}
|
|
805
|
-
return {
|
|
806
|
-
success: true,
|
|
807
|
-
data: {
|
|
808
|
-
emoji: reactionInfo.emoji,
|
|
809
|
-
eventId: reactionInfo.eventId,
|
|
810
|
-
roomId
|
|
811
|
-
}
|
|
812
|
-
};
|
|
813
|
-
},
|
|
814
|
-
examples: [
|
|
815
|
-
[
|
|
816
|
-
{
|
|
817
|
-
name: "{{user1}}",
|
|
818
|
-
content: { text: "React to the last message with a thumbs up" }
|
|
819
|
-
},
|
|
820
|
-
{
|
|
821
|
-
name: "{{agent}}",
|
|
822
|
-
content: {
|
|
823
|
-
text: "I'll add a thumbs up reaction.",
|
|
824
|
-
actions: ["MATRIX_SEND_REACTION"]
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
]
|
|
828
|
-
]
|
|
829
|
-
};
|
|
830
|
-
|
|
831
|
-
// src/providers/roomState.ts
|
|
832
|
-
var roomStateProvider = {
|
|
833
|
-
name: "matrixRoomState",
|
|
834
|
-
description: "Provides information about the current Matrix room context",
|
|
835
|
-
dynamic: true,
|
|
836
|
-
get: async (runtime, message, state) => {
|
|
837
|
-
if (message.content.source !== "matrix") {
|
|
838
|
-
return {
|
|
839
|
-
data: {},
|
|
840
|
-
values: {},
|
|
841
|
-
text: ""
|
|
842
|
-
};
|
|
843
|
-
}
|
|
844
|
-
const matrixService = runtime.getService(MATRIX_SERVICE_NAME);
|
|
845
|
-
if (!matrixService || !matrixService.isConnected()) {
|
|
805
|
+
function toConnectorAccount(settings) {
|
|
806
|
+
const now = Date.now();
|
|
807
|
+
const configured = Boolean(settings.homeserver && settings.userId && settings.accessToken);
|
|
808
|
+
return {
|
|
809
|
+
id: normalizeMatrixAccountId(settings.accountId),
|
|
810
|
+
provider: MATRIX_PROVIDER_ID,
|
|
811
|
+
label: settings.userId || settings.accountId,
|
|
812
|
+
role: "OWNER",
|
|
813
|
+
purpose: ["messaging"],
|
|
814
|
+
accessGate: "open",
|
|
815
|
+
status: settings.enabled !== false && configured ? "connected" : "disabled",
|
|
816
|
+
externalId: accountKey(settings),
|
|
817
|
+
displayHandle: settings.userId || undefined,
|
|
818
|
+
createdAt: now,
|
|
819
|
+
updatedAt: now,
|
|
820
|
+
metadata: {
|
|
821
|
+
homeserver: settings.homeserver ?? "",
|
|
822
|
+
userId: settings.userId ?? "",
|
|
823
|
+
deviceId: settings.deviceId ?? "",
|
|
824
|
+
encryption: settings.encryption ?? false,
|
|
825
|
+
autoJoin: settings.autoJoin ?? false
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
function createMatrixConnectorAccountProvider(runtime) {
|
|
830
|
+
return {
|
|
831
|
+
provider: MATRIX_PROVIDER_ID,
|
|
832
|
+
label: "Matrix",
|
|
833
|
+
listAccounts: async (_manager) => {
|
|
834
|
+
const ids = listMatrixAccountIds(runtime);
|
|
835
|
+
if (ids.length === 0) {
|
|
836
|
+
return [
|
|
837
|
+
toConnectorAccount(resolveMatrixAccountSettings(runtime, DEFAULT_MATRIX_ACCOUNT_ID))
|
|
838
|
+
];
|
|
839
|
+
}
|
|
840
|
+
return ids.map((id) => toConnectorAccount(resolveMatrixAccountSettings(runtime, id)));
|
|
841
|
+
},
|
|
842
|
+
createAccount: async (input, _manager) => {
|
|
846
843
|
return {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
844
|
+
...input,
|
|
845
|
+
provider: MATRIX_PROVIDER_ID,
|
|
846
|
+
role: input.role ?? "OWNER",
|
|
847
|
+
purpose: input.purpose ?? ["messaging"],
|
|
848
|
+
accessGate: input.accessGate ?? "open",
|
|
849
|
+
status: input.status ?? "pending"
|
|
850
850
|
};
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
responseText = `${agentName} is in a direct message conversation on Matrix.`;
|
|
864
|
-
} else {
|
|
865
|
-
const roomLabel = roomName || roomId || "a Matrix room";
|
|
866
|
-
responseText = `${agentName} is currently in Matrix room "${roomLabel}".`;
|
|
867
|
-
if (memberCount) {
|
|
868
|
-
responseText += ` The room has ${memberCount} members.`;
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
if (isEncrypted) {
|
|
872
|
-
responseText += " This room has end-to-end encryption enabled.";
|
|
873
|
-
}
|
|
874
|
-
responseText += `
|
|
851
|
+
},
|
|
852
|
+
patchAccount: async (_accountId, patch, _manager) => {
|
|
853
|
+
return { ...patch, provider: MATRIX_PROVIDER_ID };
|
|
854
|
+
},
|
|
855
|
+
deleteAccount: async (_accountId, _manager) => {}
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// src/workflow-credential-provider.ts
|
|
860
|
+
import { Service as Service2 } from "@elizaos/core";
|
|
861
|
+
var WORKFLOW_CREDENTIAL_PROVIDER_TYPE = "workflow_credential_provider";
|
|
862
|
+
var SUPPORTED = ["matrixApi"];
|
|
875
863
|
|
|
876
|
-
|
|
864
|
+
class MatrixWorkflowCredentialProvider extends Service2 {
|
|
865
|
+
static serviceType = WORKFLOW_CREDENTIAL_PROVIDER_TYPE;
|
|
866
|
+
capabilityDescription = "Supplies Matrix credentials to the workflow plugin.";
|
|
867
|
+
static async start(runtime) {
|
|
868
|
+
return new MatrixWorkflowCredentialProvider(runtime);
|
|
869
|
+
}
|
|
870
|
+
async stop() {}
|
|
871
|
+
async resolve(_userId, credType) {
|
|
872
|
+
if (credType !== "matrixApi")
|
|
873
|
+
return null;
|
|
874
|
+
const accessToken = this.runtime.getSetting("MATRIX_ACCESS_TOKEN");
|
|
875
|
+
const homeserver = this.runtime.getSetting("MATRIX_HOMESERVER");
|
|
876
|
+
if (!accessToken?.trim() || !homeserver?.trim())
|
|
877
|
+
return null;
|
|
877
878
|
return {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
roomName,
|
|
881
|
-
isEncrypted: isEncrypted || false,
|
|
882
|
-
isDirect: isDirect || false,
|
|
883
|
-
memberCount: memberCount || 0,
|
|
884
|
-
userId,
|
|
885
|
-
displayName,
|
|
886
|
-
homeserver: matrixService.getHomeserver(),
|
|
887
|
-
connected: true
|
|
888
|
-
},
|
|
889
|
-
values: {
|
|
890
|
-
roomId,
|
|
891
|
-
roomName,
|
|
892
|
-
isEncrypted: isEncrypted || false,
|
|
893
|
-
isDirect: isDirect || false,
|
|
894
|
-
memberCount: memberCount || 0,
|
|
895
|
-
userId
|
|
896
|
-
},
|
|
897
|
-
text: responseText
|
|
879
|
+
status: "credential_data",
|
|
880
|
+
data: { accessToken: accessToken.trim(), homeserverUrl: homeserver.trim() }
|
|
898
881
|
};
|
|
899
882
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
// src/providers/userContext.ts
|
|
903
|
-
var userContextProvider = {
|
|
904
|
-
name: "matrixUserContext",
|
|
905
|
-
description: "Provides information about the Matrix user in the current conversation",
|
|
906
|
-
dynamic: true,
|
|
907
|
-
get: async (runtime, message, state) => {
|
|
908
|
-
if (message.content.source !== "matrix") {
|
|
909
|
-
return {
|
|
910
|
-
data: {},
|
|
911
|
-
values: {},
|
|
912
|
-
text: ""
|
|
913
|
-
};
|
|
914
|
-
}
|
|
915
|
-
const matrixService = runtime.getService(MATRIX_SERVICE_NAME);
|
|
916
|
-
if (!matrixService || !matrixService.isConnected()) {
|
|
917
|
-
return {
|
|
918
|
-
data: {},
|
|
919
|
-
values: {},
|
|
920
|
-
text: ""
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
const agentName = state?.agentName || "The agent";
|
|
924
|
-
const metadata = message.content.metadata;
|
|
925
|
-
const senderInfo = metadata?.senderInfo;
|
|
926
|
-
if (!senderInfo) {
|
|
927
|
-
return {
|
|
928
|
-
data: {},
|
|
929
|
-
values: {},
|
|
930
|
-
text: ""
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
const displayName = getMatrixUserDisplayName(senderInfo);
|
|
934
|
-
const localpart = getMatrixLocalpart(senderInfo.userId);
|
|
935
|
-
const responseText = `${agentName} is talking to ${displayName} (${senderInfo.userId}) on Matrix.`;
|
|
883
|
+
checkCredentialTypes(credTypes) {
|
|
936
884
|
return {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
displayName,
|
|
940
|
-
localpart,
|
|
941
|
-
avatarUrl: senderInfo.avatarUrl
|
|
942
|
-
},
|
|
943
|
-
values: {
|
|
944
|
-
userId: senderInfo.userId,
|
|
945
|
-
displayName,
|
|
946
|
-
localpart
|
|
947
|
-
},
|
|
948
|
-
text: responseText
|
|
885
|
+
supported: credTypes.filter((t) => SUPPORTED.includes(t)),
|
|
886
|
+
unsupported: credTypes.filter((t) => !SUPPORTED.includes(t))
|
|
949
887
|
};
|
|
950
888
|
}
|
|
951
|
-
}
|
|
889
|
+
}
|
|
952
890
|
|
|
953
891
|
// src/index.ts
|
|
954
892
|
var matrixPlugin = {
|
|
955
893
|
name: "matrix",
|
|
956
894
|
description: "Matrix messaging integration plugin for ElizaOS with E2EE support",
|
|
957
|
-
services: [MatrixService],
|
|
958
|
-
actions: [
|
|
959
|
-
providers: [
|
|
895
|
+
services: [MatrixService, MatrixWorkflowCredentialProvider],
|
|
896
|
+
actions: [],
|
|
897
|
+
providers: [],
|
|
960
898
|
tests: [],
|
|
899
|
+
autoEnable: {
|
|
900
|
+
connectorKeys: ["matrix"]
|
|
901
|
+
},
|
|
961
902
|
init: async (_config, runtime) => {
|
|
903
|
+
try {
|
|
904
|
+
const manager = getConnectorAccountManager(runtime);
|
|
905
|
+
manager.registerProvider(createMatrixConnectorAccountProvider(runtime));
|
|
906
|
+
} catch (err) {
|
|
907
|
+
logger2.warn({
|
|
908
|
+
src: "plugin:matrix",
|
|
909
|
+
err: err instanceof Error ? err.message : String(err)
|
|
910
|
+
}, "Failed to register Matrix provider with ConnectorAccountManager");
|
|
911
|
+
}
|
|
962
912
|
const homeserver = runtime.getSetting("MATRIX_HOMESERVER");
|
|
963
913
|
const userId = runtime.getSetting("MATRIX_USER_ID");
|
|
964
914
|
const accessToken = runtime.getSetting("MATRIX_ACCESS_TOKEN");
|
|
@@ -1003,13 +953,12 @@ var matrixPlugin = {
|
|
|
1003
953
|
};
|
|
1004
954
|
var src_default = matrixPlugin;
|
|
1005
955
|
export {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
956
|
+
resolveMatrixAccountSettings,
|
|
957
|
+
resolveDefaultMatrixAccountId,
|
|
958
|
+
readMatrixAccountId,
|
|
959
|
+
normalizeMatrixAccountId,
|
|
1010
960
|
matrixMxcToHttp,
|
|
1011
|
-
|
|
1012
|
-
joinRoom,
|
|
961
|
+
listMatrixAccountIds,
|
|
1013
962
|
isValidMatrixUserId,
|
|
1014
963
|
isValidMatrixRoomId,
|
|
1015
964
|
isValidMatrixRoomAlias,
|
|
@@ -1025,7 +974,8 @@ export {
|
|
|
1025
974
|
MatrixConfigurationError,
|
|
1026
975
|
MatrixApiError,
|
|
1027
976
|
MAX_MATRIX_MESSAGE_LENGTH,
|
|
1028
|
-
MATRIX_SERVICE_NAME
|
|
977
|
+
MATRIX_SERVICE_NAME,
|
|
978
|
+
DEFAULT_MATRIX_ACCOUNT_ID
|
|
1029
979
|
};
|
|
1030
980
|
|
|
1031
|
-
//# debugId=
|
|
981
|
+
//# debugId=2890053EB234064664756E2164756E21
|