@elizaos/plugin-matrix 2.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.ts +16 -0
- package/dist/index.js +1045 -0
- package/package.json +34 -0
- package/src/__tests__/matrix.test.ts +550 -0
- package/src/actions/joinRoom.ts +147 -0
- package/src/actions/listRooms.ts +95 -0
- package/src/actions/sendMessage.ts +175 -0
- package/src/actions/sendReaction.ts +162 -0
- package/src/index.ts +105 -0
- package/src/providers/roomState.ts +95 -0
- package/src/providers/userContext.ts +79 -0
- package/src/service.ts +483 -0
- package/src/types.ts +334 -0
- package/tsconfig.json +21 -0
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elizaos/plugin-matrix",
|
|
3
|
+
"version": "2.0.0-alpha.3",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "bun run build.ts",
|
|
9
|
+
"test": "bun test"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"matrix-js-sdk": "^31.0.0",
|
|
13
|
+
"zod": "^4.3.6"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@elizaos/core": "2.0.0-alpha.3"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/bun": "^1.1.0",
|
|
20
|
+
"typescript": "^5.3.0"
|
|
21
|
+
},
|
|
22
|
+
"milaidy": {
|
|
23
|
+
"platforms": [
|
|
24
|
+
"node"
|
|
25
|
+
],
|
|
26
|
+
"runtime": "node",
|
|
27
|
+
"platformDetails": {
|
|
28
|
+
"node": "Node.js via main entry point"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
import type { IAgentRuntime, Memory, State } from "@elizaos/core";
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
// Mock matrix-js-sdk before importing
|
|
5
|
+
vi.mock("matrix-js-sdk", () => ({
|
|
6
|
+
createClient: vi.fn(() => ({
|
|
7
|
+
startClient: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
stopClient: vi.fn(),
|
|
9
|
+
on: vi.fn(),
|
|
10
|
+
removeListener: vi.fn(),
|
|
11
|
+
getRooms: vi.fn().mockReturnValue([]),
|
|
12
|
+
joinRoom: vi.fn().mockResolvedValue({ roomId: "!joined:matrix.org" }),
|
|
13
|
+
leave: vi.fn().mockResolvedValue(undefined),
|
|
14
|
+
sendMessage: vi.fn().mockResolvedValue({ event_id: "$sent_event" }),
|
|
15
|
+
sendEvent: vi.fn().mockResolvedValue({ event_id: "$reaction_event" }),
|
|
16
|
+
sendTyping: vi.fn().mockResolvedValue(undefined),
|
|
17
|
+
sendReadReceipt: vi.fn().mockResolvedValue(undefined),
|
|
18
|
+
getRoomIdForAlias: vi.fn().mockResolvedValue({ room_id: "!resolved:matrix.org" }),
|
|
19
|
+
getAccountData: vi.fn().mockReturnValue(null),
|
|
20
|
+
})),
|
|
21
|
+
ClientEvent: { Sync: "sync" },
|
|
22
|
+
RoomEvent: { Timeline: "Room.timeline" },
|
|
23
|
+
RoomMemberEvent: { Membership: "RoomMember.membership" },
|
|
24
|
+
MatrixEvent: vi.fn().mockImplementation((data: Record<string, string>) => data),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
vi.mock("@elizaos/core", async () => {
|
|
28
|
+
const actual = await vi.importActual("@elizaos/core");
|
|
29
|
+
return {
|
|
30
|
+
...actual,
|
|
31
|
+
Service: class MockService {
|
|
32
|
+
protected runtime: IAgentRuntime = {} as IAgentRuntime;
|
|
33
|
+
constructor(runtime?: IAgentRuntime) {
|
|
34
|
+
if (runtime) this.runtime = runtime;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
logger: {
|
|
38
|
+
info: vi.fn(),
|
|
39
|
+
debug: vi.fn(),
|
|
40
|
+
warn: vi.fn(),
|
|
41
|
+
error: vi.fn(),
|
|
42
|
+
},
|
|
43
|
+
composePromptFromState: vi.fn().mockResolvedValue("mock prompt"),
|
|
44
|
+
parseJSONObjectFromText: vi.fn(),
|
|
45
|
+
ModelType: { TEXT_SMALL: "TEXT_SMALL" },
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
import {
|
|
50
|
+
getMatrixLocalpart,
|
|
51
|
+
getMatrixServerpart,
|
|
52
|
+
getMatrixUserDisplayName,
|
|
53
|
+
isValidMatrixRoomAlias,
|
|
54
|
+
isValidMatrixRoomId,
|
|
55
|
+
isValidMatrixUserId,
|
|
56
|
+
MatrixApiError,
|
|
57
|
+
MatrixConfigurationError,
|
|
58
|
+
MatrixEventTypes,
|
|
59
|
+
MatrixNotConnectedError,
|
|
60
|
+
MatrixPluginError,
|
|
61
|
+
MatrixServiceNotInitializedError,
|
|
62
|
+
MATRIX_SERVICE_NAME,
|
|
63
|
+
MAX_MATRIX_MESSAGE_LENGTH,
|
|
64
|
+
matrixMxcToHttp,
|
|
65
|
+
type MatrixUserInfo,
|
|
66
|
+
} from "../types.js";
|
|
67
|
+
import { sendMessage } from "../actions/sendMessage.js";
|
|
68
|
+
import { sendReaction } from "../actions/sendReaction.js";
|
|
69
|
+
import { listRooms } from "../actions/listRooms.js";
|
|
70
|
+
import { joinRoom } from "../actions/joinRoom.js";
|
|
71
|
+
import { roomStateProvider } from "../providers/roomState.js";
|
|
72
|
+
import { userContextProvider } from "../providers/userContext.js";
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Constants
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
describe("Matrix Constants", () => {
|
|
79
|
+
it("MAX_MATRIX_MESSAGE_LENGTH is 4000", () => {
|
|
80
|
+
expect(MAX_MATRIX_MESSAGE_LENGTH).toBe(4000);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("MATRIX_SERVICE_NAME is 'matrix'", () => {
|
|
84
|
+
expect(MATRIX_SERVICE_NAME).toBe("matrix");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// Event Types
|
|
90
|
+
// ============================================================================
|
|
91
|
+
|
|
92
|
+
describe("MatrixEventTypes", () => {
|
|
93
|
+
it("has all event values", () => {
|
|
94
|
+
expect(MatrixEventTypes.MESSAGE_RECEIVED).toBe("MATRIX_MESSAGE_RECEIVED");
|
|
95
|
+
expect(MatrixEventTypes.MESSAGE_SENT).toBe("MATRIX_MESSAGE_SENT");
|
|
96
|
+
expect(MatrixEventTypes.ROOM_JOINED).toBe("MATRIX_ROOM_JOINED");
|
|
97
|
+
expect(MatrixEventTypes.ROOM_LEFT).toBe("MATRIX_ROOM_LEFT");
|
|
98
|
+
expect(MatrixEventTypes.INVITE_RECEIVED).toBe("MATRIX_INVITE_RECEIVED");
|
|
99
|
+
expect(MatrixEventTypes.REACTION_RECEIVED).toBe("MATRIX_REACTION_RECEIVED");
|
|
100
|
+
expect(MatrixEventTypes.TYPING_RECEIVED).toBe("MATRIX_TYPING_RECEIVED");
|
|
101
|
+
expect(MatrixEventTypes.SYNC_COMPLETE).toBe("MATRIX_SYNC_COMPLETE");
|
|
102
|
+
expect(MatrixEventTypes.CONNECTION_READY).toBe("MATRIX_CONNECTION_READY");
|
|
103
|
+
expect(MatrixEventTypes.CONNECTION_LOST).toBe("MATRIX_CONNECTION_LOST");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Utility Functions
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
describe("isValidMatrixUserId", () => {
|
|
112
|
+
it("returns true for valid user IDs", () => {
|
|
113
|
+
expect(isValidMatrixUserId("@alice:matrix.org")).toBe(true);
|
|
114
|
+
expect(isValidMatrixUserId("@bot:example.com")).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("returns false for invalid user IDs", () => {
|
|
118
|
+
expect(isValidMatrixUserId("alice:matrix.org")).toBe(false);
|
|
119
|
+
expect(isValidMatrixUserId("@alice")).toBe(false);
|
|
120
|
+
expect(isValidMatrixUserId("")).toBe(false);
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe("isValidMatrixRoomId", () => {
|
|
125
|
+
it("returns true for valid room IDs", () => {
|
|
126
|
+
expect(isValidMatrixRoomId("!abc123:matrix.org")).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("returns false for invalid room IDs", () => {
|
|
130
|
+
expect(isValidMatrixRoomId("#general:matrix.org")).toBe(false);
|
|
131
|
+
expect(isValidMatrixRoomId("abc:matrix.org")).toBe(false);
|
|
132
|
+
expect(isValidMatrixRoomId("!abc")).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
describe("isValidMatrixRoomAlias", () => {
|
|
137
|
+
it("returns true for valid room aliases", () => {
|
|
138
|
+
expect(isValidMatrixRoomAlias("#general:matrix.org")).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("returns false for invalid room aliases", () => {
|
|
142
|
+
expect(isValidMatrixRoomAlias("!room:matrix.org")).toBe(false);
|
|
143
|
+
expect(isValidMatrixRoomAlias("general:matrix.org")).toBe(false);
|
|
144
|
+
expect(isValidMatrixRoomAlias("#general")).toBe(false);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe("getMatrixLocalpart", () => {
|
|
149
|
+
it("extracts localpart from user ID", () => {
|
|
150
|
+
expect(getMatrixLocalpart("@alice:matrix.org")).toBe("alice");
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("extracts localpart from room ID", () => {
|
|
154
|
+
expect(getMatrixLocalpart("!abc:matrix.org")).toBe("abc");
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("extracts localpart from alias", () => {
|
|
158
|
+
expect(getMatrixLocalpart("#general:matrix.org")).toBe("general");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("returns input for plain string", () => {
|
|
162
|
+
expect(getMatrixLocalpart("plaintext")).toBe("plaintext");
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe("getMatrixServerpart", () => {
|
|
167
|
+
it("extracts server part", () => {
|
|
168
|
+
expect(getMatrixServerpart("@alice:matrix.org")).toBe("matrix.org");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("returns empty string for no colon", () => {
|
|
172
|
+
expect(getMatrixServerpart("plaintext")).toBe("");
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe("getMatrixUserDisplayName", () => {
|
|
177
|
+
it("uses display name when available", () => {
|
|
178
|
+
const user: MatrixUserInfo = {
|
|
179
|
+
userId: "@alice:matrix.org",
|
|
180
|
+
displayName: "Alice Wonderland",
|
|
181
|
+
};
|
|
182
|
+
expect(getMatrixUserDisplayName(user)).toBe("Alice Wonderland");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("falls back to localpart", () => {
|
|
186
|
+
const user: MatrixUserInfo = {
|
|
187
|
+
userId: "@alice:matrix.org",
|
|
188
|
+
};
|
|
189
|
+
expect(getMatrixUserDisplayName(user)).toBe("alice");
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe("matrixMxcToHttp", () => {
|
|
194
|
+
it("converts valid mxc URL", () => {
|
|
195
|
+
const result = matrixMxcToHttp("mxc://matrix.org/abc123", "https://matrix.org");
|
|
196
|
+
expect(result).toBe("https://matrix.org/_matrix/media/v3/download/matrix.org/abc123");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("handles trailing slash", () => {
|
|
200
|
+
const result = matrixMxcToHttp("mxc://matrix.org/abc123", "https://matrix.org/");
|
|
201
|
+
expect(result).toBe("https://matrix.org/_matrix/media/v3/download/matrix.org/abc123");
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("returns undefined for non-mxc URL", () => {
|
|
205
|
+
expect(matrixMxcToHttp("https://example.com/img.png", "https://matrix.org")).toBeUndefined();
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("returns undefined for malformed mxc", () => {
|
|
209
|
+
expect(matrixMxcToHttp("mxc://matrix.org", "https://matrix.org")).toBeUndefined();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// Error Types
|
|
215
|
+
// ============================================================================
|
|
216
|
+
|
|
217
|
+
describe("Error types", () => {
|
|
218
|
+
it("MatrixPluginError", () => {
|
|
219
|
+
const err = new MatrixPluginError("test");
|
|
220
|
+
expect(err.message).toBe("test");
|
|
221
|
+
expect(err.name).toBe("MatrixPluginError");
|
|
222
|
+
expect(err).toBeInstanceOf(Error);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it("MatrixServiceNotInitializedError", () => {
|
|
226
|
+
const err = new MatrixServiceNotInitializedError();
|
|
227
|
+
expect(err.message).toContain("not initialized");
|
|
228
|
+
expect(err).toBeInstanceOf(MatrixPluginError);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("MatrixNotConnectedError", () => {
|
|
232
|
+
const err = new MatrixNotConnectedError();
|
|
233
|
+
expect(err.message).toContain("not connected");
|
|
234
|
+
expect(err).toBeInstanceOf(MatrixPluginError);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it("MatrixConfigurationError with setting", () => {
|
|
238
|
+
const err = new MatrixConfigurationError("Missing homeserver", "MATRIX_HOMESERVER");
|
|
239
|
+
expect(err.settingName).toBe("MATRIX_HOMESERVER");
|
|
240
|
+
expect(err).toBeInstanceOf(MatrixPluginError);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("MatrixConfigurationError without setting", () => {
|
|
244
|
+
const err = new MatrixConfigurationError("Bad config");
|
|
245
|
+
expect(err.settingName).toBeUndefined();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("MatrixApiError with errcode", () => {
|
|
249
|
+
const err = new MatrixApiError("Rate limited", "M_LIMIT_EXCEEDED");
|
|
250
|
+
expect(err.errcode).toBe("M_LIMIT_EXCEEDED");
|
|
251
|
+
expect(err).toBeInstanceOf(MatrixPluginError);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it("MatrixApiError without errcode", () => {
|
|
255
|
+
const err = new MatrixApiError("Server error");
|
|
256
|
+
expect(err.errcode).toBeUndefined();
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// ============================================================================
|
|
261
|
+
// Actions
|
|
262
|
+
// ============================================================================
|
|
263
|
+
|
|
264
|
+
describe("sendMessage action", () => {
|
|
265
|
+
it("has correct name", () => {
|
|
266
|
+
expect(sendMessage.name).toBe("MATRIX_SEND_MESSAGE");
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("has description", () => {
|
|
270
|
+
expect(sendMessage.description.length).toBeGreaterThan(0);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("has similes", () => {
|
|
274
|
+
expect(sendMessage.similes).toContain("SEND_MATRIX_MESSAGE");
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it("has validate function", () => {
|
|
278
|
+
expect(typeof sendMessage.validate).toBe("function");
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
it("has handler function", () => {
|
|
282
|
+
expect(typeof sendMessage.handler).toBe("function");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("has examples", () => {
|
|
286
|
+
expect(sendMessage.examples).toBeDefined();
|
|
287
|
+
expect(sendMessage.examples!.length).toBeGreaterThan(0);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("validate returns true for matrix source", async () => {
|
|
291
|
+
const runtime = {} as IAgentRuntime;
|
|
292
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
293
|
+
const result = await sendMessage.validate(runtime, message);
|
|
294
|
+
expect(result).toBe(true);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it("validate returns false for non-matrix source", async () => {
|
|
298
|
+
const runtime = {} as IAgentRuntime;
|
|
299
|
+
const message = { content: { source: "discord" } } as Memory;
|
|
300
|
+
const result = await sendMessage.validate(runtime, message);
|
|
301
|
+
expect(result).toBe(false);
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
describe("sendReaction action", () => {
|
|
306
|
+
it("has correct name", () => {
|
|
307
|
+
expect(sendReaction.name).toBe("MATRIX_SEND_REACTION");
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("has description", () => {
|
|
311
|
+
expect(sendReaction.description.length).toBeGreaterThan(0);
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it("has similes", () => {
|
|
315
|
+
expect(sendReaction.similes!.length).toBeGreaterThan(0);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it("validate returns true for matrix source", async () => {
|
|
319
|
+
const runtime = {} as IAgentRuntime;
|
|
320
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
321
|
+
const result = await sendReaction.validate(runtime, message);
|
|
322
|
+
expect(result).toBe(true);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it("validate returns false for non-matrix source", async () => {
|
|
326
|
+
const runtime = {} as IAgentRuntime;
|
|
327
|
+
const message = { content: { source: "slack" } } as Memory;
|
|
328
|
+
const result = await sendReaction.validate(runtime, message);
|
|
329
|
+
expect(result).toBe(false);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe("listRooms action", () => {
|
|
334
|
+
it("has correct name", () => {
|
|
335
|
+
expect(listRooms.name).toBe("MATRIX_LIST_ROOMS");
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it("has description", () => {
|
|
339
|
+
expect(listRooms.description.length).toBeGreaterThan(0);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it("has similes including common variants", () => {
|
|
343
|
+
expect(listRooms.similes).toContain("LIST_MATRIX_ROOMS");
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it("validate returns true for matrix source", async () => {
|
|
347
|
+
const runtime = {} as IAgentRuntime;
|
|
348
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
349
|
+
const result = await listRooms.validate(runtime, message);
|
|
350
|
+
expect(result).toBe(true);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("joinRoom action", () => {
|
|
355
|
+
it("has correct name", () => {
|
|
356
|
+
expect(joinRoom.name).toBe("MATRIX_JOIN_ROOM");
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it("has description", () => {
|
|
360
|
+
expect(joinRoom.description.length).toBeGreaterThan(0);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("validate returns true for matrix source", async () => {
|
|
364
|
+
const runtime = {} as IAgentRuntime;
|
|
365
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
366
|
+
const result = await joinRoom.validate(runtime, message);
|
|
367
|
+
expect(result).toBe(true);
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
it("validate returns false for non-matrix source", async () => {
|
|
371
|
+
const runtime = {} as IAgentRuntime;
|
|
372
|
+
const message = { content: { source: "nostr" } } as Memory;
|
|
373
|
+
const result = await joinRoom.validate(runtime, message);
|
|
374
|
+
expect(result).toBe(false);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// ============================================================================
|
|
379
|
+
// Providers
|
|
380
|
+
// ============================================================================
|
|
381
|
+
|
|
382
|
+
describe("roomStateProvider", () => {
|
|
383
|
+
it("has correct name", () => {
|
|
384
|
+
expect(roomStateProvider.name).toBe("matrixRoomState");
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("has description mentioning room", () => {
|
|
388
|
+
expect(roomStateProvider.description!.toLowerCase()).toContain("room");
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it("returns empty for non-matrix source", async () => {
|
|
392
|
+
const runtime = {} as IAgentRuntime;
|
|
393
|
+
const message = { content: { source: "discord" } } as Memory;
|
|
394
|
+
const state = {} as State;
|
|
395
|
+
|
|
396
|
+
const result = await roomStateProvider.get(runtime, message, state);
|
|
397
|
+
|
|
398
|
+
expect(result.text).toBe("");
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
it("returns disconnected when no service", async () => {
|
|
402
|
+
const runtime = {
|
|
403
|
+
getService: vi.fn().mockReturnValue(null),
|
|
404
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
405
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
406
|
+
const state = {} as State;
|
|
407
|
+
|
|
408
|
+
const result = await roomStateProvider.get(runtime, message, state);
|
|
409
|
+
|
|
410
|
+
expect(result.data).toHaveProperty("connected", false);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it("returns room state when connected", async () => {
|
|
414
|
+
const mockService = {
|
|
415
|
+
isConnected: vi.fn().mockReturnValue(true),
|
|
416
|
+
getUserId: vi.fn().mockReturnValue("@bot:matrix.org"),
|
|
417
|
+
getHomeserver: vi.fn().mockReturnValue("https://matrix.org"),
|
|
418
|
+
};
|
|
419
|
+
const runtime = {
|
|
420
|
+
getService: vi.fn().mockReturnValue(mockService),
|
|
421
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
422
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
423
|
+
const state = {
|
|
424
|
+
agentName: "TestBot",
|
|
425
|
+
data: {
|
|
426
|
+
room: {
|
|
427
|
+
roomId: "!abc:matrix.org",
|
|
428
|
+
name: "General",
|
|
429
|
+
isEncrypted: true,
|
|
430
|
+
isDirect: false,
|
|
431
|
+
memberCount: 15,
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
} as State;
|
|
435
|
+
|
|
436
|
+
const result = await roomStateProvider.get(runtime, message, state);
|
|
437
|
+
|
|
438
|
+
expect(result.data).toHaveProperty("connected", true);
|
|
439
|
+
expect(result.data).toHaveProperty("roomId", "!abc:matrix.org");
|
|
440
|
+
expect(result.data).toHaveProperty("isEncrypted", true);
|
|
441
|
+
expect(result.data).toHaveProperty("userId", "@bot:matrix.org");
|
|
442
|
+
expect(result.text).toContain("TestBot");
|
|
443
|
+
expect(result.text).toContain("General");
|
|
444
|
+
expect(result.text).toContain("encryption");
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("returns DM text for direct message rooms", async () => {
|
|
448
|
+
const mockService = {
|
|
449
|
+
isConnected: vi.fn().mockReturnValue(true),
|
|
450
|
+
getUserId: vi.fn().mockReturnValue("@bot:m.org"),
|
|
451
|
+
getHomeserver: vi.fn().mockReturnValue("https://m.org"),
|
|
452
|
+
};
|
|
453
|
+
const runtime = {
|
|
454
|
+
getService: vi.fn().mockReturnValue(mockService),
|
|
455
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
456
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
457
|
+
const state = {
|
|
458
|
+
agentName: "Bot",
|
|
459
|
+
data: {
|
|
460
|
+
room: {
|
|
461
|
+
roomId: "!dm:m.org",
|
|
462
|
+
isDirect: true,
|
|
463
|
+
memberCount: 2,
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
} as State;
|
|
467
|
+
|
|
468
|
+
const result = await roomStateProvider.get(runtime, message, state);
|
|
469
|
+
|
|
470
|
+
expect(result.text).toContain("direct message");
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
describe("userContextProvider", () => {
|
|
475
|
+
it("has correct name", () => {
|
|
476
|
+
expect(userContextProvider.name).toBe("matrixUserContext");
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it("has description mentioning user", () => {
|
|
480
|
+
expect(userContextProvider.description!.toLowerCase()).toContain("user");
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it("returns empty for non-matrix source", async () => {
|
|
484
|
+
const runtime = {} as IAgentRuntime;
|
|
485
|
+
const message = { content: { source: "nostr" } } as Memory;
|
|
486
|
+
const state = {} as State;
|
|
487
|
+
|
|
488
|
+
const result = await userContextProvider.get(runtime, message, state);
|
|
489
|
+
|
|
490
|
+
expect(result.text).toBe("");
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
it("returns empty when no service", async () => {
|
|
494
|
+
const runtime = {
|
|
495
|
+
getService: vi.fn().mockReturnValue(null),
|
|
496
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
497
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
498
|
+
const state = {} as State;
|
|
499
|
+
|
|
500
|
+
const result = await userContextProvider.get(runtime, message, state);
|
|
501
|
+
|
|
502
|
+
expect(result.data).toEqual({});
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it("returns empty when no sender info", async () => {
|
|
506
|
+
const mockService = {
|
|
507
|
+
isConnected: vi.fn().mockReturnValue(true),
|
|
508
|
+
};
|
|
509
|
+
const runtime = {
|
|
510
|
+
getService: vi.fn().mockReturnValue(mockService),
|
|
511
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
512
|
+
const message = { content: { source: "matrix" } } as Memory;
|
|
513
|
+
const state = {} as State;
|
|
514
|
+
|
|
515
|
+
const result = await userContextProvider.get(runtime, message, state);
|
|
516
|
+
|
|
517
|
+
expect(result.data).toEqual({});
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
it("returns user context when sender info available", async () => {
|
|
521
|
+
const mockService = {
|
|
522
|
+
isConnected: vi.fn().mockReturnValue(true),
|
|
523
|
+
};
|
|
524
|
+
const runtime = {
|
|
525
|
+
getService: vi.fn().mockReturnValue(mockService),
|
|
526
|
+
} as Partial<IAgentRuntime> as IAgentRuntime;
|
|
527
|
+
const message = {
|
|
528
|
+
content: {
|
|
529
|
+
source: "matrix",
|
|
530
|
+
metadata: {
|
|
531
|
+
senderInfo: {
|
|
532
|
+
userId: "@alice:matrix.org",
|
|
533
|
+
displayName: "Alice",
|
|
534
|
+
avatarUrl: "mxc://matrix.org/avatar",
|
|
535
|
+
},
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
} as Memory;
|
|
539
|
+
const state = { agentName: "TestBot" } as State;
|
|
540
|
+
|
|
541
|
+
const result = await userContextProvider.get(runtime, message, state);
|
|
542
|
+
|
|
543
|
+
expect(result.data).toHaveProperty("userId", "@alice:matrix.org");
|
|
544
|
+
expect(result.data).toHaveProperty("displayName", "Alice");
|
|
545
|
+
expect(result.data).toHaveProperty("localpart", "alice");
|
|
546
|
+
expect(result.text).toContain("TestBot");
|
|
547
|
+
expect(result.text).toContain("Alice");
|
|
548
|
+
expect(result.text).toContain("Matrix");
|
|
549
|
+
});
|
|
550
|
+
});
|