@openclaw/matrix 2026.1.29 → 2026.2.2
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/CHANGELOG.md +28 -0
- package/index.ts +0 -1
- package/openclaw.plugin.json +1 -3
- package/package.json +12 -12
- package/src/actions.ts +16 -6
- package/src/channel.directory.test.ts +13 -5
- package/src/channel.ts +61 -39
- package/src/directory-live.ts +21 -8
- package/src/group-mentions.ts +10 -5
- package/src/matrix/accounts.test.ts +0 -1
- package/src/matrix/accounts.ts +4 -2
- package/src/matrix/actions/client.ts +8 -4
- package/src/matrix/actions/messages.ts +17 -9
- package/src/matrix/actions/pins.ts +12 -6
- package/src/matrix/actions/reactions.ts +24 -12
- package/src/matrix/actions/room.ts +10 -13
- package/src/matrix/actions/summary.ts +4 -6
- package/src/matrix/client/config.ts +4 -9
- package/src/matrix/client/create-client.ts +12 -16
- package/src/matrix/client/logging.ts +17 -16
- package/src/matrix/client/shared.ts +6 -5
- package/src/matrix/client/storage.ts +12 -12
- package/src/matrix/client.test.ts +0 -1
- package/src/matrix/client.ts +1 -5
- package/src/matrix/credentials.ts +7 -5
- package/src/matrix/deps.ts +8 -5
- package/src/matrix/format.test.ts +0 -1
- package/src/matrix/monitor/allowlist.test.ts +45 -0
- package/src/matrix/monitor/allowlist.ts +62 -17
- package/src/matrix/monitor/auto-join.ts +7 -4
- package/src/matrix/monitor/direct.ts +11 -12
- package/src/matrix/monitor/events.ts +1 -3
- package/src/matrix/monitor/handler.ts +69 -53
- package/src/matrix/monitor/index.ts +118 -59
- package/src/matrix/monitor/location.ts +27 -10
- package/src/matrix/monitor/media.test.ts +1 -2
- package/src/matrix/monitor/media.ts +8 -8
- package/src/matrix/monitor/replies.ts +4 -3
- package/src/matrix/monitor/room-info.ts +5 -8
- package/src/matrix/monitor/rooms.test.ts +39 -0
- package/src/matrix/monitor/rooms.ts +7 -3
- package/src/matrix/monitor/threads.ts +6 -2
- package/src/matrix/poll-types.test.ts +0 -1
- package/src/matrix/poll-types.ts +16 -7
- package/src/matrix/send/client.ts +7 -4
- package/src/matrix/send/formatting.ts +14 -17
- package/src/matrix/send/media.ts +17 -8
- package/src/matrix/send/targets.test.ts +7 -11
- package/src/matrix/send/targets.ts +19 -27
- package/src/matrix/send.test.ts +1 -2
- package/src/matrix/send.ts +9 -4
- package/src/onboarding.ts +24 -14
- package/src/outbound.ts +1 -2
- package/src/resolve-targets.test.ts +48 -0
- package/src/resolve-targets.ts +55 -9
- package/src/tool-actions.ts +15 -11
- package/src/types.ts +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,53 +1,81 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026.2.2
|
|
4
|
+
|
|
5
|
+
### Changes
|
|
6
|
+
|
|
7
|
+
- Version alignment with core OpenClaw release numbers.
|
|
8
|
+
|
|
9
|
+
## 2026.1.31
|
|
10
|
+
|
|
11
|
+
### Changes
|
|
12
|
+
|
|
13
|
+
- Version alignment with core OpenClaw release numbers.
|
|
14
|
+
|
|
15
|
+
## 2026.1.30
|
|
16
|
+
|
|
17
|
+
### Changes
|
|
18
|
+
|
|
19
|
+
- Version alignment with core OpenClaw release numbers.
|
|
20
|
+
|
|
3
21
|
## 2026.1.29
|
|
4
22
|
|
|
5
23
|
### Changes
|
|
24
|
+
|
|
6
25
|
- Version alignment with core OpenClaw release numbers.
|
|
7
26
|
|
|
8
27
|
## 2026.1.23
|
|
9
28
|
|
|
10
29
|
### Changes
|
|
30
|
+
|
|
11
31
|
- Version alignment with core OpenClaw release numbers.
|
|
12
32
|
|
|
13
33
|
## 2026.1.22
|
|
14
34
|
|
|
15
35
|
### Changes
|
|
36
|
+
|
|
16
37
|
- Version alignment with core OpenClaw release numbers.
|
|
17
38
|
|
|
18
39
|
## 2026.1.21
|
|
19
40
|
|
|
20
41
|
### Changes
|
|
42
|
+
|
|
21
43
|
- Version alignment with core OpenClaw release numbers.
|
|
22
44
|
|
|
23
45
|
## 2026.1.20
|
|
24
46
|
|
|
25
47
|
### Changes
|
|
48
|
+
|
|
26
49
|
- Version alignment with core OpenClaw release numbers.
|
|
27
50
|
|
|
28
51
|
## 2026.1.17-1
|
|
29
52
|
|
|
30
53
|
### Changes
|
|
54
|
+
|
|
31
55
|
- Version alignment with core OpenClaw release numbers.
|
|
32
56
|
|
|
33
57
|
## 2026.1.17
|
|
34
58
|
|
|
35
59
|
### Changes
|
|
60
|
+
|
|
36
61
|
- Version alignment with core OpenClaw release numbers.
|
|
37
62
|
|
|
38
63
|
## 2026.1.16
|
|
39
64
|
|
|
40
65
|
### Changes
|
|
66
|
+
|
|
41
67
|
- Version alignment with core OpenClaw release numbers.
|
|
42
68
|
|
|
43
69
|
## 2026.1.15
|
|
44
70
|
|
|
45
71
|
### Changes
|
|
72
|
+
|
|
46
73
|
- Version alignment with core OpenClaw release numbers.
|
|
47
74
|
|
|
48
75
|
## 2026.1.14
|
|
49
76
|
|
|
50
77
|
### Features
|
|
78
|
+
|
|
51
79
|
- Version alignment with core OpenClaw release numbers.
|
|
52
80
|
- Matrix channel plugin with homeserver + user ID auth (access token or password login with device name).
|
|
53
81
|
- Direct messages with pairing/allowlist/open/disabled policies and allowFrom support.
|
package/index.ts
CHANGED
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/matrix",
|
|
3
|
-
"version": "2026.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "2026.2.2",
|
|
5
4
|
"description": "OpenClaw Matrix channel plugin",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0",
|
|
8
|
+
"@vector-im/matrix-bot-sdk": "0.8.0-element.3",
|
|
9
|
+
"markdown-it": "14.1.0",
|
|
10
|
+
"music-metadata": "^11.11.2",
|
|
11
|
+
"zod": "^4.3.6"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"openclaw": "workspace:*"
|
|
15
|
+
},
|
|
6
16
|
"openclaw": {
|
|
7
17
|
"extensions": [
|
|
8
18
|
"./index.ts"
|
|
@@ -22,15 +32,5 @@
|
|
|
22
32
|
"localPath": "extensions/matrix",
|
|
23
33
|
"defaultChoice": "npm"
|
|
24
34
|
}
|
|
25
|
-
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0",
|
|
28
|
-
"markdown-it": "14.1.0",
|
|
29
|
-
"@vector-im/matrix-bot-sdk": "0.8.0-element.3",
|
|
30
|
-
"music-metadata": "^11.10.6",
|
|
31
|
-
"zod": "^4.3.6"
|
|
32
|
-
},
|
|
33
|
-
"devDependencies": {
|
|
34
|
-
"openclaw": "workspace:*"
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/actions.ts
CHANGED
|
@@ -7,14 +7,16 @@ import {
|
|
|
7
7
|
type ChannelMessageActionName,
|
|
8
8
|
type ChannelToolSend,
|
|
9
9
|
} from "openclaw/plugin-sdk";
|
|
10
|
+
import type { CoreConfig } from "./types.js";
|
|
10
11
|
import { resolveMatrixAccount } from "./matrix/accounts.js";
|
|
11
12
|
import { handleMatrixAction } from "./tool-actions.js";
|
|
12
|
-
import type { CoreConfig } from "./types.js";
|
|
13
13
|
|
|
14
14
|
export const matrixMessageActions: ChannelMessageActionAdapter = {
|
|
15
15
|
listActions: ({ cfg }) => {
|
|
16
16
|
const account = resolveMatrixAccount({ cfg: cfg as CoreConfig });
|
|
17
|
-
if (!account.enabled || !account.configured)
|
|
17
|
+
if (!account.enabled || !account.configured) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
18
20
|
const gate = createActionGate((cfg as CoreConfig).channels?.matrix?.actions);
|
|
19
21
|
const actions = new Set<ChannelMessageActionName>(["send", "poll"]);
|
|
20
22
|
if (gate("reactions")) {
|
|
@@ -31,16 +33,24 @@ export const matrixMessageActions: ChannelMessageActionAdapter = {
|
|
|
31
33
|
actions.add("unpin");
|
|
32
34
|
actions.add("list-pins");
|
|
33
35
|
}
|
|
34
|
-
if (gate("memberInfo"))
|
|
35
|
-
|
|
36
|
+
if (gate("memberInfo")) {
|
|
37
|
+
actions.add("member-info");
|
|
38
|
+
}
|
|
39
|
+
if (gate("channelInfo")) {
|
|
40
|
+
actions.add("channel-info");
|
|
41
|
+
}
|
|
36
42
|
return Array.from(actions);
|
|
37
43
|
},
|
|
38
44
|
supportsAction: ({ action }) => action !== "poll",
|
|
39
45
|
extractToolSend: ({ args }): ChannelToolSend | null => {
|
|
40
46
|
const action = typeof args.action === "string" ? args.action.trim() : "";
|
|
41
|
-
if (action !== "sendMessage")
|
|
47
|
+
if (action !== "sendMessage") {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
42
50
|
const to = typeof args.to === "string" ? args.to : undefined;
|
|
43
|
-
if (!to)
|
|
51
|
+
if (!to) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
44
54
|
return { to };
|
|
45
55
|
},
|
|
46
56
|
handleAction: async (ctx: ChannelMessageActionContext) => {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it } from "vitest";
|
|
2
|
-
|
|
3
1
|
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
|
2
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
3
|
import type { CoreConfig } from "./types.js";
|
|
5
|
-
|
|
6
4
|
import { matrixPlugin } from "./channel.js";
|
|
7
5
|
import { setMatrixRuntime } from "./runtime.js";
|
|
8
6
|
|
|
@@ -34,7 +32,12 @@ describe("matrix directory", () => {
|
|
|
34
32
|
expect(matrixPlugin.directory?.listGroups).toBeTruthy();
|
|
35
33
|
|
|
36
34
|
await expect(
|
|
37
|
-
matrixPlugin.directory!.listPeers({
|
|
35
|
+
matrixPlugin.directory!.listPeers({
|
|
36
|
+
cfg,
|
|
37
|
+
accountId: undefined,
|
|
38
|
+
query: undefined,
|
|
39
|
+
limit: undefined,
|
|
40
|
+
}),
|
|
38
41
|
).resolves.toEqual(
|
|
39
42
|
expect.arrayContaining([
|
|
40
43
|
{ kind: "user", id: "user:@alice:example.org" },
|
|
@@ -45,7 +48,12 @@ describe("matrix directory", () => {
|
|
|
45
48
|
);
|
|
46
49
|
|
|
47
50
|
await expect(
|
|
48
|
-
matrixPlugin.directory!.listGroups({
|
|
51
|
+
matrixPlugin.directory!.listGroups({
|
|
52
|
+
cfg,
|
|
53
|
+
accountId: undefined,
|
|
54
|
+
query: undefined,
|
|
55
|
+
limit: undefined,
|
|
56
|
+
}),
|
|
49
57
|
).resolves.toEqual(
|
|
50
58
|
expect.arrayContaining([
|
|
51
59
|
{ kind: "group", id: "room:!room1:example.org" },
|
package/src/channel.ts
CHANGED
|
@@ -9,11 +9,14 @@ import {
|
|
|
9
9
|
setAccountEnabledInConfigSection,
|
|
10
10
|
type ChannelPlugin,
|
|
11
11
|
} from "openclaw/plugin-sdk";
|
|
12
|
-
|
|
12
|
+
import type { CoreConfig } from "./types.js";
|
|
13
13
|
import { matrixMessageActions } from "./actions.js";
|
|
14
14
|
import { MatrixConfigSchema } from "./config-schema.js";
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
15
|
+
import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js";
|
|
16
|
+
import {
|
|
17
|
+
resolveMatrixGroupRequireMention,
|
|
18
|
+
resolveMatrixGroupToolPolicy,
|
|
19
|
+
} from "./group-mentions.js";
|
|
17
20
|
import {
|
|
18
21
|
listMatrixAccountIds,
|
|
19
22
|
resolveDefaultMatrixAccountId,
|
|
@@ -21,16 +24,12 @@ import {
|
|
|
21
24
|
type ResolvedMatrixAccount,
|
|
22
25
|
} from "./matrix/accounts.js";
|
|
23
26
|
import { resolveMatrixAuth } from "./matrix/client.js";
|
|
24
|
-
import {
|
|
27
|
+
import { normalizeMatrixAllowList, normalizeMatrixUserId } from "./matrix/monitor/allowlist.js";
|
|
25
28
|
import { probeMatrix } from "./matrix/probe.js";
|
|
26
29
|
import { sendMessageMatrix } from "./matrix/send.js";
|
|
27
30
|
import { matrixOnboardingAdapter } from "./onboarding.js";
|
|
28
31
|
import { matrixOutbound } from "./outbound.js";
|
|
29
32
|
import { resolveMatrixTargets } from "./resolve-targets.js";
|
|
30
|
-
import {
|
|
31
|
-
listMatrixDirectoryGroupsLive,
|
|
32
|
-
listMatrixDirectoryPeersLive,
|
|
33
|
-
} from "./directory-live.js";
|
|
34
33
|
|
|
35
34
|
const meta = {
|
|
36
35
|
id: "matrix",
|
|
@@ -45,7 +44,9 @@ const meta = {
|
|
|
45
44
|
|
|
46
45
|
function normalizeMatrixMessagingTarget(raw: string): string | undefined {
|
|
47
46
|
let normalized = raw.trim();
|
|
48
|
-
if (!normalized)
|
|
47
|
+
if (!normalized) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
49
50
|
const lowered = normalized.toLowerCase();
|
|
50
51
|
if (lowered.startsWith("matrix:")) {
|
|
51
52
|
normalized = normalized.slice("matrix:".length).trim();
|
|
@@ -108,8 +109,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
108
109
|
configSchema: buildChannelConfigSchema(MatrixConfigSchema),
|
|
109
110
|
config: {
|
|
110
111
|
listAccountIds: (cfg) => listMatrixAccountIds(cfg as CoreConfig),
|
|
111
|
-
resolveAccount: (cfg, accountId) =>
|
|
112
|
-
resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId }),
|
|
112
|
+
resolveAccount: (cfg, accountId) => resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId }),
|
|
113
113
|
defaultAccountId: (cfg) => resolveDefaultMatrixAccountId(cfg as CoreConfig),
|
|
114
114
|
setAccountEnabled: ({ cfg, accountId, enabled }) =>
|
|
115
115
|
setAccountEnabledInConfigSection({
|
|
@@ -144,7 +144,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
144
144
|
}),
|
|
145
145
|
resolveAllowFrom: ({ cfg }) =>
|
|
146
146
|
((cfg as CoreConfig).channels?.matrix?.dm?.allowFrom ?? []).map((entry) => String(entry)),
|
|
147
|
-
formatAllowFrom: ({ allowFrom }) =>
|
|
147
|
+
formatAllowFrom: ({ allowFrom }) => normalizeMatrixAllowList(allowFrom),
|
|
148
148
|
},
|
|
149
149
|
security: {
|
|
150
150
|
resolveDmPolicy: ({ account }) => ({
|
|
@@ -153,15 +153,16 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
153
153
|
policyPath: "channels.matrix.dm.policy",
|
|
154
154
|
allowFromPath: "channels.matrix.dm.allowFrom",
|
|
155
155
|
approveHint: formatPairingApproveHint("matrix"),
|
|
156
|
-
normalizeEntry: (raw) => raw
|
|
156
|
+
normalizeEntry: (raw) => normalizeMatrixUserId(raw),
|
|
157
157
|
}),
|
|
158
158
|
collectWarnings: ({ account, cfg }) => {
|
|
159
159
|
const defaultGroupPolicy = (cfg as CoreConfig).channels?.defaults?.groupPolicy;
|
|
160
|
-
const groupPolicy =
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
|
|
161
|
+
if (groupPolicy !== "open") {
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
163
164
|
return [
|
|
164
|
-
|
|
165
|
+
'- Matrix rooms: groupPolicy="open" allows any room to trigger (mention-gated). Set channels.matrix.groupPolicy="allowlist" + channels.matrix.groups (and optionally channels.matrix.groupAllowFrom) to restrict rooms.',
|
|
165
166
|
];
|
|
166
167
|
},
|
|
167
168
|
},
|
|
@@ -170,16 +171,13 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
170
171
|
resolveToolPolicy: resolveMatrixGroupToolPolicy,
|
|
171
172
|
},
|
|
172
173
|
threading: {
|
|
173
|
-
resolveReplyToMode: ({ cfg }) =>
|
|
174
|
-
(cfg as CoreConfig).channels?.matrix?.replyToMode ?? "off",
|
|
174
|
+
resolveReplyToMode: ({ cfg }) => (cfg as CoreConfig).channels?.matrix?.replyToMode ?? "off",
|
|
175
175
|
buildToolContext: ({ context, hasRepliedRef }) => {
|
|
176
176
|
const currentTarget = context.To;
|
|
177
177
|
return {
|
|
178
178
|
currentChannelId: currentTarget?.trim() || undefined,
|
|
179
179
|
currentThreadTs:
|
|
180
|
-
context.MessageThreadId != null
|
|
181
|
-
? String(context.MessageThreadId)
|
|
182
|
-
: context.ReplyToId,
|
|
180
|
+
context.MessageThreadId != null ? String(context.MessageThreadId) : context.ReplyToId,
|
|
183
181
|
hasRepliedRef,
|
|
184
182
|
};
|
|
185
183
|
},
|
|
@@ -189,8 +187,12 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
189
187
|
targetResolver: {
|
|
190
188
|
looksLikeId: (raw) => {
|
|
191
189
|
const trimmed = raw.trim();
|
|
192
|
-
if (!trimmed)
|
|
193
|
-
|
|
190
|
+
if (!trimmed) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
if (/^(matrix:)?[!#@]/i.test(trimmed)) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
194
196
|
return trimmed.includes(":");
|
|
195
197
|
},
|
|
196
198
|
hint: "<room|alias|user>",
|
|
@@ -205,13 +207,17 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
205
207
|
|
|
206
208
|
for (const entry of account.config.dm?.allowFrom ?? []) {
|
|
207
209
|
const raw = String(entry).trim();
|
|
208
|
-
if (!raw || raw === "*")
|
|
210
|
+
if (!raw || raw === "*") {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
209
213
|
ids.add(raw.replace(/^matrix:/i, ""));
|
|
210
214
|
}
|
|
211
215
|
|
|
212
216
|
for (const entry of account.config.groupAllowFrom ?? []) {
|
|
213
217
|
const raw = String(entry).trim();
|
|
214
|
-
if (!raw || raw === "*")
|
|
218
|
+
if (!raw || raw === "*") {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
215
221
|
ids.add(raw.replace(/^matrix:/i, ""));
|
|
216
222
|
}
|
|
217
223
|
|
|
@@ -219,7 +225,9 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
219
225
|
for (const room of Object.values(groups)) {
|
|
220
226
|
for (const entry of room.users ?? []) {
|
|
221
227
|
const raw = String(entry).trim();
|
|
222
|
-
if (!raw || raw === "*")
|
|
228
|
+
if (!raw || raw === "*") {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
223
231
|
ids.add(raw.replace(/^matrix:/i, ""));
|
|
224
232
|
}
|
|
225
233
|
}
|
|
@@ -230,7 +238,9 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
230
238
|
.map((raw) => {
|
|
231
239
|
const lowered = raw.toLowerCase();
|
|
232
240
|
const cleaned = lowered.startsWith("user:") ? raw.slice("user:".length).trim() : raw;
|
|
233
|
-
if (cleaned.startsWith("@"))
|
|
241
|
+
if (cleaned.startsWith("@")) {
|
|
242
|
+
return `user:${cleaned}`;
|
|
243
|
+
}
|
|
234
244
|
return cleaned;
|
|
235
245
|
})
|
|
236
246
|
.filter((id) => (q ? id.toLowerCase().includes(q) : true))
|
|
@@ -255,8 +265,12 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
255
265
|
.map((raw) => raw.replace(/^matrix:/i, ""))
|
|
256
266
|
.map((raw) => {
|
|
257
267
|
const lowered = raw.toLowerCase();
|
|
258
|
-
if (lowered.startsWith("room:") || lowered.startsWith("channel:"))
|
|
259
|
-
|
|
268
|
+
if (lowered.startsWith("room:") || lowered.startsWith("channel:")) {
|
|
269
|
+
return raw;
|
|
270
|
+
}
|
|
271
|
+
if (raw.startsWith("!")) {
|
|
272
|
+
return `room:${raw}`;
|
|
273
|
+
}
|
|
260
274
|
return raw;
|
|
261
275
|
})
|
|
262
276
|
.filter((id) => (q ? id.toLowerCase().includes(q) : true))
|
|
@@ -284,8 +298,12 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
284
298
|
name,
|
|
285
299
|
}),
|
|
286
300
|
validateInput: ({ input }) => {
|
|
287
|
-
if (input.useEnv)
|
|
288
|
-
|
|
301
|
+
if (input.useEnv) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
if (!input.homeserver?.trim()) {
|
|
305
|
+
return "Matrix requires --homeserver";
|
|
306
|
+
}
|
|
289
307
|
const accessToken = input.accessToken?.trim();
|
|
290
308
|
const password = input.password?.trim();
|
|
291
309
|
const userId = input.userId?.trim();
|
|
@@ -293,8 +311,12 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
293
311
|
return "Matrix requires --access-token or --password";
|
|
294
312
|
}
|
|
295
313
|
if (!accessToken) {
|
|
296
|
-
if (!userId)
|
|
297
|
-
|
|
314
|
+
if (!userId) {
|
|
315
|
+
return "Matrix requires --user-id when using --password";
|
|
316
|
+
}
|
|
317
|
+
if (!password) {
|
|
318
|
+
return "Matrix requires --password when using --user-id";
|
|
319
|
+
}
|
|
298
320
|
}
|
|
299
321
|
return null;
|
|
300
322
|
},
|
|
@@ -339,7 +361,9 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
339
361
|
collectStatusIssues: (accounts) =>
|
|
340
362
|
accounts.flatMap((account) => {
|
|
341
363
|
const lastError = typeof account.lastError === "string" ? account.lastError.trim() : "";
|
|
342
|
-
if (!lastError)
|
|
364
|
+
if (!lastError) {
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
343
367
|
return [
|
|
344
368
|
{
|
|
345
369
|
channel: "matrix",
|
|
@@ -359,7 +383,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
359
383
|
probe: snapshot.probe,
|
|
360
384
|
lastProbeAt: snapshot.lastProbeAt ?? null,
|
|
361
385
|
}),
|
|
362
|
-
probeAccount: async ({
|
|
386
|
+
probeAccount: async ({ timeoutMs, cfg }) => {
|
|
363
387
|
try {
|
|
364
388
|
const auth = await resolveMatrixAuth({ cfg: cfg as CoreConfig });
|
|
365
389
|
return await probeMatrix({
|
|
@@ -399,9 +423,7 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
|
|
|
399
423
|
accountId: account.accountId,
|
|
400
424
|
baseUrl: account.homeserver,
|
|
401
425
|
});
|
|
402
|
-
ctx.log?.info(
|
|
403
|
-
`[${account.accountId}] starting provider (${account.homeserver ?? "matrix"})`,
|
|
404
|
-
);
|
|
426
|
+
ctx.log?.info(`[${account.accountId}] starting provider (${account.homeserver ?? "matrix"})`);
|
|
405
427
|
// Lazy import: the monitor pulls the reply pipeline; avoid ESM init cycles.
|
|
406
428
|
const { monitorMatrixProvider } = await import("./matrix/index.js");
|
|
407
429
|
return monitorMatrixProvider({
|
package/src/directory-live.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ChannelDirectoryEntry } from "openclaw/plugin-sdk";
|
|
2
|
-
|
|
3
2
|
import { resolveMatrixAuth } from "./matrix/client.js";
|
|
4
3
|
|
|
5
4
|
type MatrixUserResult = {
|
|
@@ -55,7 +54,9 @@ export async function listMatrixDirectoryPeersLive(params: {
|
|
|
55
54
|
limit?: number | null;
|
|
56
55
|
}): Promise<ChannelDirectoryEntry[]> {
|
|
57
56
|
const query = normalizeQuery(params.query);
|
|
58
|
-
if (!query)
|
|
57
|
+
if (!query) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
59
60
|
const auth = await resolveMatrixAuth({ cfg: params.cfg as never });
|
|
60
61
|
const res = await fetchMatrixJson<MatrixUserDirectoryResponse>({
|
|
61
62
|
homeserver: auth.homeserver,
|
|
@@ -71,7 +72,9 @@ export async function listMatrixDirectoryPeersLive(params: {
|
|
|
71
72
|
return results
|
|
72
73
|
.map((entry) => {
|
|
73
74
|
const userId = entry.user_id?.trim();
|
|
74
|
-
if (!userId)
|
|
75
|
+
if (!userId) {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
75
78
|
return {
|
|
76
79
|
kind: "user",
|
|
77
80
|
id: userId,
|
|
@@ -123,13 +126,17 @@ export async function listMatrixDirectoryGroupsLive(params: {
|
|
|
123
126
|
limit?: number | null;
|
|
124
127
|
}): Promise<ChannelDirectoryEntry[]> {
|
|
125
128
|
const query = normalizeQuery(params.query);
|
|
126
|
-
if (!query)
|
|
129
|
+
if (!query) {
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
127
132
|
const auth = await resolveMatrixAuth({ cfg: params.cfg as never });
|
|
128
133
|
const limit = typeof params.limit === "number" && params.limit > 0 ? params.limit : 20;
|
|
129
134
|
|
|
130
135
|
if (query.startsWith("#")) {
|
|
131
136
|
const roomId = await resolveMatrixRoomAlias(auth.homeserver, auth.accessToken, query);
|
|
132
|
-
if (!roomId)
|
|
137
|
+
if (!roomId) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
133
140
|
return [
|
|
134
141
|
{
|
|
135
142
|
kind: "group",
|
|
@@ -160,15 +167,21 @@ export async function listMatrixDirectoryGroupsLive(params: {
|
|
|
160
167
|
|
|
161
168
|
for (const roomId of rooms) {
|
|
162
169
|
const name = await fetchMatrixRoomName(auth.homeserver, auth.accessToken, roomId);
|
|
163
|
-
if (!name)
|
|
164
|
-
|
|
170
|
+
if (!name) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (!name.toLowerCase().includes(query)) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
165
176
|
results.push({
|
|
166
177
|
kind: "group",
|
|
167
178
|
id: roomId,
|
|
168
179
|
name,
|
|
169
180
|
handle: `#${name}`,
|
|
170
181
|
});
|
|
171
|
-
if (results.length >= limit)
|
|
182
|
+
if (results.length >= limit) {
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
172
185
|
}
|
|
173
186
|
|
|
174
187
|
return results;
|
package/src/group-mentions.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ChannelGroupContext, GroupToolPolicyConfig } from "openclaw/plugin-sdk";
|
|
2
|
-
|
|
3
|
-
import { resolveMatrixRoomConfig } from "./matrix/monitor/rooms.js";
|
|
4
2
|
import type { CoreConfig } from "./types.js";
|
|
3
|
+
import { resolveMatrixRoomConfig } from "./matrix/monitor/rooms.js";
|
|
5
4
|
|
|
6
5
|
export function resolveMatrixGroupRequireMention(params: ChannelGroupContext): boolean {
|
|
7
6
|
const rawGroupId = params.groupId?.trim() ?? "";
|
|
@@ -26,9 +25,15 @@ export function resolveMatrixGroupRequireMention(params: ChannelGroupContext): b
|
|
|
26
25
|
name: groupChannel || undefined,
|
|
27
26
|
}).config;
|
|
28
27
|
if (resolved) {
|
|
29
|
-
if (resolved.autoReply === true)
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
if (resolved.autoReply === true) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
if (resolved.autoReply === false) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (typeof resolved.requireMention === "boolean") {
|
|
35
|
+
return resolved.requireMention;
|
|
36
|
+
}
|
|
32
37
|
}
|
|
33
38
|
return true;
|
|
34
39
|
}
|
package/src/matrix/accounts.ts
CHANGED
|
@@ -19,7 +19,9 @@ export function listMatrixAccountIds(_cfg: CoreConfig): string[] {
|
|
|
19
19
|
|
|
20
20
|
export function resolveDefaultMatrixAccountId(cfg: CoreConfig): string {
|
|
21
21
|
const ids = listMatrixAccountIds(cfg);
|
|
22
|
-
if (ids.includes(DEFAULT_ACCOUNT_ID))
|
|
22
|
+
if (ids.includes(DEFAULT_ACCOUNT_ID)) {
|
|
23
|
+
return DEFAULT_ACCOUNT_ID;
|
|
24
|
+
}
|
|
23
25
|
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -28,7 +30,7 @@ export function resolveMatrixAccount(params: {
|
|
|
28
30
|
accountId?: string | null;
|
|
29
31
|
}): ResolvedMatrixAccount {
|
|
30
32
|
const accountId = normalizeAccountId(params.accountId);
|
|
31
|
-
const base =
|
|
33
|
+
const base = params.cfg.channels?.matrix ?? {};
|
|
32
34
|
const enabled = base.enabled !== false;
|
|
33
35
|
const resolved = resolveMatrixConfig(params.cfg, process.env);
|
|
34
36
|
const hasHomeserver = Boolean(resolved.homeserver);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { getMatrixRuntime } from "../../runtime.js";
|
|
2
1
|
import type { CoreConfig } from "../types.js";
|
|
2
|
+
import type { MatrixActionClient, MatrixActionClientOpts } from "./types.js";
|
|
3
|
+
import { getMatrixRuntime } from "../../runtime.js";
|
|
3
4
|
import { getActiveMatrixClient } from "../active-client.js";
|
|
4
5
|
import {
|
|
5
6
|
createMatrixClient,
|
|
@@ -7,7 +8,6 @@ import {
|
|
|
7
8
|
resolveMatrixAuth,
|
|
8
9
|
resolveSharedMatrixClient,
|
|
9
10
|
} from "../client.js";
|
|
10
|
-
import type { MatrixActionClient, MatrixActionClientOpts } from "./types.js";
|
|
11
11
|
|
|
12
12
|
export function ensureNodeRuntime() {
|
|
13
13
|
if (isBunRuntime()) {
|
|
@@ -19,9 +19,13 @@ export async function resolveActionClient(
|
|
|
19
19
|
opts: MatrixActionClientOpts = {},
|
|
20
20
|
): Promise<MatrixActionClient> {
|
|
21
21
|
ensureNodeRuntime();
|
|
22
|
-
if (opts.client)
|
|
22
|
+
if (opts.client) {
|
|
23
|
+
return { client: opts.client, stopOnDone: false };
|
|
24
|
+
}
|
|
23
25
|
const active = getActiveMatrixClient();
|
|
24
|
-
if (active)
|
|
26
|
+
if (active) {
|
|
27
|
+
return { client: active, stopOnDone: false };
|
|
28
|
+
}
|
|
25
29
|
const shouldShareClient = Boolean(process.env.OPENCLAW_GATEWAY_PORT);
|
|
26
30
|
if (shouldShareClient) {
|
|
27
31
|
const client = await resolveSharedMatrixClient({
|