@openclaw/matrix 2026.3.13 → 2026.5.9-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/dist/account-config-D2W-V1eQ.js +96 -0
- package/dist/account-selection-BWwIruri.js +158 -0
- package/dist/accounts-Bm90Rzvp.js +130 -0
- package/dist/active-client-uhlxdhEy.js +20 -0
- package/dist/allowlist-sTzpCn5d.js +68 -0
- package/dist/api.js +12 -0
- package/dist/approval-handler.runtime-DWTQfd4m.js +370 -0
- package/dist/approval-ids-DoC2z7tR.js +7 -0
- package/dist/approval-reaction-auth-DbcA1gGd.js +27 -0
- package/dist/approval-reactions-o2_tuH8D.js +162 -0
- package/dist/async-lock-uQfhfQIY.js +19 -0
- package/dist/auth-presence.js +26 -0
- package/dist/backup-health-Cabu_WQC.js +60 -0
- package/dist/channel-DJNir3Rb.js +1116 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-BQu0hTih.js +246 -0
- package/dist/cli-BmfTmg7x.js +1340 -0
- package/dist/cli-metadata-B-PCEzrA.js +22 -0
- package/dist/cli-metadata.js +2 -0
- package/dist/client-DkcXnm0X.js +25 -0
- package/dist/client-_hckQNGW.js +31 -0
- package/dist/client-bootstrap-Rb8oHvhH.js +114 -0
- package/dist/config--5-S2Akv.js +452 -0
- package/dist/config-paths-nsVaysCu.js +19 -0
- package/dist/config-schema-nPLpEgHl.js +200 -0
- package/dist/config-secret-input.runtime-DiKFehsE.js +2 -0
- package/dist/config-update-wZX-HLMn.js +143 -0
- package/dist/contract-api.js +9 -0
- package/dist/create-client-DCnqDaqd.js +64 -0
- package/dist/credentials-DV6fWXhC.js +56 -0
- package/dist/credentials-read-cmHgousK.js +112 -0
- package/dist/credentials-write.runtime-zniTq-Gr.js +17 -0
- package/dist/crypto-node.runtime-pihzdpY7.js +12 -0
- package/dist/crypto-runtime-ZI0zAtn3.js +1214 -0
- package/dist/deps-C6WqKY7m.js +235 -0
- package/dist/device-health-UVYpbA_W.js +16 -0
- package/dist/direct-management-DMMMgtTB.js +249 -0
- package/dist/direct-room-XkutHjES.js +76 -0
- package/dist/directory-live-DmOtMhyr.js +150 -0
- package/dist/doctor-C4__7c-U.js +153 -0
- package/dist/doctor-contract-D4-64QuJ.js +246 -0
- package/dist/doctor-contract-api.js +2 -0
- package/dist/draft-stream-BE2QevQQ.js +144 -0
- package/dist/encryption-guidance-BPi3A_m3.js +15 -0
- package/dist/env-auth-BJqGI8M6.js +63 -0
- package/dist/env-vars-C7uQCTKn.js +63 -0
- package/dist/errors-CTcpEDq-.js +17 -0
- package/dist/exec-approval-resolver-Bza9Dhlm.js +15 -0
- package/dist/exec-approvals-Crnh543m.js +196 -0
- package/dist/helper-api.js +4 -0
- package/dist/http-client-C7AeVJay.js +319 -0
- package/dist/index.js +46 -0
- package/dist/legacy-crypto-inspector-poDWldgy.js +41 -0
- package/dist/legacy-crypto-restore-Biw-w2ng.js +85 -0
- package/dist/logger-CnZRVrux.js +78 -0
- package/dist/logging-DZHSPP5N.js +99 -0
- package/dist/matrix-migration.runtime-WY6ffcrf.js +525 -0
- package/dist/media-text-DU6nWZuj.js +146 -0
- package/dist/messages-BpihMh82.js +140 -0
- package/dist/migration-snapshot-backup-DaCHTp8C.js +69 -0
- package/dist/migration-snapshot.runtime-CKHE3xF9.js +2 -0
- package/dist/monitor-C_81r_Ck.js +4125 -0
- package/dist/plugin-entry.handlers.runtime.js +51 -0
- package/dist/probe.runtime-BvAzYAIe.js +3 -0
- package/dist/profile-BlHu0wDX.js +111 -0
- package/dist/profile-update-DjeBNgIV.js +69 -0
- package/dist/reaction-common-ejrL19w-.js +71 -0
- package/dist/reaction-events-CiARZfjk.js +121 -0
- package/dist/record-shared-CHWJCTWf.js +2 -0
- package/dist/recovery-key-store-BTJ6jz5v.js +294 -0
- package/dist/resolve-targets-YtJnw1Tb.js +140 -0
- package/dist/resolver.runtime-D9piiGEl.js +5 -0
- package/dist/rolldown-runtime-DUslC3ob.js +14 -0
- package/dist/route-D6rg-iXN.js +161 -0
- package/dist/runtime-C6X4h_SJ.js +6 -0
- package/dist/runtime-Dog86njy.js +8 -0
- package/dist/runtime-api-BXWBFIqm.js +25 -0
- package/dist/runtime-api.js +25 -0
- package/dist/runtime-heavy-api.js +3 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/sdk-B2vZA27-.js +1416 -0
- package/dist/secret-contract-DcrJWCQI.js +120 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/send-Bo0DU1ca.js +1200 -0
- package/dist/session-store-metadata-DI5SCofx.js +77 -0
- package/dist/setup-bootstrap-ImenBsMt.js +62 -0
- package/dist/setup-core-CfZy05oW.js +116 -0
- package/dist/setup-dm-policy-2-r1FrQh.js +194 -0
- package/dist/setup-entry.js +19 -0
- package/dist/setup-plugin-api.js +44 -0
- package/dist/setup-surface-CqT_o61M.js +540 -0
- package/dist/shared-CpMoYKm1.js +195 -0
- package/dist/startup-abort-56edvmbM.js +32 -0
- package/dist/startup-verification-Demyp0bP.js +132 -0
- package/dist/storage-paths-BJLdnCjV.js +52 -0
- package/dist/storage-tC3ujLiW.js +281 -0
- package/dist/subagent-hooks-DQbyqq9V.js +149 -0
- package/dist/subagent-hooks-api.js +23 -0
- package/dist/sync-state-C_beeevA.js +12 -0
- package/dist/target-ids-80nQ2gql.js +77 -0
- package/dist/test-api.js +4 -0
- package/dist/thread-binding-api-Cq_E-E1K.js +17 -0
- package/dist/thread-binding-api.js +2 -0
- package/dist/thread-bindings-B9mesxXk.js +352 -0
- package/dist/thread-bindings-runtime.js +2 -0
- package/dist/thread-bindings-shared-DK-d-oYX.js +97 -0
- package/dist/timeout-abort-signal-CtaIaP1v.js +2 -0
- package/dist/tool-actions.runtime-BIH49vRr.js +532 -0
- package/dist/url-validation-DiK9j7jz.js +36 -0
- package/dist/verification-CZ2rDeHL.js +345 -0
- package/openclaw.plugin.json +788 -1
- package/package.json +82 -16
- package/CHANGELOG.md +0 -104
- package/index.ts +0 -22
- package/src/actions.ts +0 -195
- package/src/channel.directory.test.ts +0 -135
- package/src/channel.ts +0 -461
- package/src/config-schema.test.ts +0 -26
- package/src/config-schema.ts +0 -62
- package/src/directory-live.test.ts +0 -85
- package/src/directory-live.ts +0 -209
- package/src/group-mentions.ts +0 -52
- package/src/matrix/accounts.test.ts +0 -131
- package/src/matrix/accounts.ts +0 -114
- package/src/matrix/actions/client.ts +0 -47
- package/src/matrix/actions/limits.test.ts +0 -15
- package/src/matrix/actions/limits.ts +0 -6
- package/src/matrix/actions/messages.ts +0 -126
- package/src/matrix/actions/pins.test.ts +0 -74
- package/src/matrix/actions/pins.ts +0 -84
- package/src/matrix/actions/reactions.test.ts +0 -109
- package/src/matrix/actions/reactions.ts +0 -102
- package/src/matrix/actions/room.ts +0 -85
- package/src/matrix/actions/summary.ts +0 -75
- package/src/matrix/actions/types.ts +0 -85
- package/src/matrix/actions.ts +0 -15
- package/src/matrix/active-client.ts +0 -32
- package/src/matrix/client/config.ts +0 -245
- package/src/matrix/client/create-client.ts +0 -125
- package/src/matrix/client/logging.ts +0 -46
- package/src/matrix/client/runtime.ts +0 -4
- package/src/matrix/client/shared.test.ts +0 -85
- package/src/matrix/client/shared.ts +0 -210
- package/src/matrix/client/startup.test.ts +0 -49
- package/src/matrix/client/startup.ts +0 -29
- package/src/matrix/client/storage.ts +0 -131
- package/src/matrix/client/types.ts +0 -34
- package/src/matrix/client-bootstrap.ts +0 -47
- package/src/matrix/client.test.ts +0 -56
- package/src/matrix/client.ts +0 -14
- package/src/matrix/credentials.ts +0 -125
- package/src/matrix/deps.test.ts +0 -74
- package/src/matrix/deps.ts +0 -126
- package/src/matrix/format.test.ts +0 -33
- package/src/matrix/format.ts +0 -22
- package/src/matrix/index.ts +0 -11
- package/src/matrix/monitor/access-policy.ts +0 -126
- package/src/matrix/monitor/allowlist.test.ts +0 -45
- package/src/matrix/monitor/allowlist.ts +0 -94
- package/src/matrix/monitor/auto-join.ts +0 -72
- package/src/matrix/monitor/direct.test.ts +0 -396
- package/src/matrix/monitor/direct.ts +0 -152
- package/src/matrix/monitor/events.test.ts +0 -186
- package/src/matrix/monitor/events.ts +0 -168
- package/src/matrix/monitor/handler.body-for-agent.test.ts +0 -196
- package/src/matrix/monitor/handler.ts +0 -768
- package/src/matrix/monitor/inbound-body.test.ts +0 -73
- package/src/matrix/monitor/inbound-body.ts +0 -28
- package/src/matrix/monitor/index.test.ts +0 -18
- package/src/matrix/monitor/index.ts +0 -414
- package/src/matrix/monitor/location.ts +0 -100
- package/src/matrix/monitor/media.test.ts +0 -86
- package/src/matrix/monitor/media.ts +0 -118
- package/src/matrix/monitor/mentions.test.ts +0 -154
- package/src/matrix/monitor/mentions.ts +0 -62
- package/src/matrix/monitor/replies.test.ts +0 -184
- package/src/matrix/monitor/replies.ts +0 -124
- package/src/matrix/monitor/room-info.ts +0 -55
- package/src/matrix/monitor/rooms.test.ts +0 -124
- package/src/matrix/monitor/rooms.ts +0 -47
- package/src/matrix/monitor/threads.ts +0 -68
- package/src/matrix/monitor/types.ts +0 -39
- package/src/matrix/poll-types.test.ts +0 -21
- package/src/matrix/poll-types.ts +0 -167
- package/src/matrix/probe.ts +0 -69
- package/src/matrix/sdk-runtime.ts +0 -18
- package/src/matrix/send/client.ts +0 -99
- package/src/matrix/send/formatting.ts +0 -93
- package/src/matrix/send/media.ts +0 -230
- package/src/matrix/send/targets.test.ts +0 -98
- package/src/matrix/send/targets.ts +0 -150
- package/src/matrix/send/types.ts +0 -110
- package/src/matrix/send-queue.test.ts +0 -145
- package/src/matrix/send-queue.ts +0 -28
- package/src/matrix/send.test.ts +0 -319
- package/src/matrix/send.ts +0 -267
- package/src/onboarding.ts +0 -462
- package/src/outbound.test.ts +0 -159
- package/src/outbound.ts +0 -58
- package/src/resolve-targets.test.ts +0 -68
- package/src/resolve-targets.ts +0 -125
- package/src/runtime.ts +0 -6
- package/src/secret-input.ts +0 -13
- package/src/test-mocks.ts +0 -53
- package/src/tool-actions.ts +0 -164
- package/src/types.ts +0 -118
package/src/matrix/deps.test.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { ensureMatrixCryptoRuntime } from "./deps.js";
|
|
3
|
-
|
|
4
|
-
const logStub = vi.fn();
|
|
5
|
-
|
|
6
|
-
describe("ensureMatrixCryptoRuntime", () => {
|
|
7
|
-
it("returns immediately when matrix SDK loads", async () => {
|
|
8
|
-
const runCommand = vi.fn();
|
|
9
|
-
const requireFn = vi.fn(() => ({}));
|
|
10
|
-
|
|
11
|
-
await ensureMatrixCryptoRuntime({
|
|
12
|
-
log: logStub,
|
|
13
|
-
requireFn,
|
|
14
|
-
runCommand,
|
|
15
|
-
resolveFn: () => "/tmp/download-lib.js",
|
|
16
|
-
nodeExecutable: "/usr/bin/node",
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
expect(requireFn).toHaveBeenCalledTimes(1);
|
|
20
|
-
expect(runCommand).not.toHaveBeenCalled();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("bootstraps missing crypto runtime and retries matrix SDK load", async () => {
|
|
24
|
-
let bootstrapped = false;
|
|
25
|
-
const requireFn = vi.fn(() => {
|
|
26
|
-
if (!bootstrapped) {
|
|
27
|
-
throw new Error(
|
|
28
|
-
"Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu' (required by matrix sdk)",
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
return {};
|
|
32
|
-
});
|
|
33
|
-
const runCommand = vi.fn(async () => {
|
|
34
|
-
bootstrapped = true;
|
|
35
|
-
return { code: 0, stdout: "", stderr: "" };
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
await ensureMatrixCryptoRuntime({
|
|
39
|
-
log: logStub,
|
|
40
|
-
requireFn,
|
|
41
|
-
runCommand,
|
|
42
|
-
resolveFn: () => "/tmp/download-lib.js",
|
|
43
|
-
nodeExecutable: "/usr/bin/node",
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
expect(runCommand).toHaveBeenCalledWith({
|
|
47
|
-
argv: ["/usr/bin/node", "/tmp/download-lib.js"],
|
|
48
|
-
cwd: "/tmp",
|
|
49
|
-
timeoutMs: 300_000,
|
|
50
|
-
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
|
|
51
|
-
});
|
|
52
|
-
expect(requireFn).toHaveBeenCalledTimes(2);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("rethrows non-crypto module errors without bootstrapping", async () => {
|
|
56
|
-
const runCommand = vi.fn();
|
|
57
|
-
const requireFn = vi.fn(() => {
|
|
58
|
-
throw new Error("Cannot find module '@vector-im/matrix-bot-sdk'");
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
await expect(
|
|
62
|
-
ensureMatrixCryptoRuntime({
|
|
63
|
-
log: logStub,
|
|
64
|
-
requireFn,
|
|
65
|
-
runCommand,
|
|
66
|
-
resolveFn: () => "/tmp/download-lib.js",
|
|
67
|
-
nodeExecutable: "/usr/bin/node",
|
|
68
|
-
}),
|
|
69
|
-
).rejects.toThrow("Cannot find module '@vector-im/matrix-bot-sdk'");
|
|
70
|
-
|
|
71
|
-
expect(runCommand).not.toHaveBeenCalled();
|
|
72
|
-
expect(requireFn).toHaveBeenCalledTimes(1);
|
|
73
|
-
});
|
|
74
|
-
});
|
package/src/matrix/deps.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { runPluginCommandWithTimeout, type RuntimeEnv } from "openclaw/plugin-sdk/matrix";
|
|
6
|
-
|
|
7
|
-
const MATRIX_SDK_PACKAGE = "@vector-im/matrix-bot-sdk";
|
|
8
|
-
const MATRIX_CRYPTO_DOWNLOAD_HELPER = "@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js";
|
|
9
|
-
|
|
10
|
-
function formatCommandError(result: { stderr: string; stdout: string }): string {
|
|
11
|
-
const stderr = result.stderr.trim();
|
|
12
|
-
if (stderr) {
|
|
13
|
-
return stderr;
|
|
14
|
-
}
|
|
15
|
-
const stdout = result.stdout.trim();
|
|
16
|
-
if (stdout) {
|
|
17
|
-
return stdout;
|
|
18
|
-
}
|
|
19
|
-
return "unknown error";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function isMissingMatrixCryptoRuntimeError(err: unknown): boolean {
|
|
23
|
-
const message = err instanceof Error ? err.message : String(err ?? "");
|
|
24
|
-
return (
|
|
25
|
-
message.includes("Cannot find module") &&
|
|
26
|
-
message.includes("@matrix-org/matrix-sdk-crypto-nodejs-")
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function isMatrixSdkAvailable(): boolean {
|
|
31
|
-
try {
|
|
32
|
-
const req = createRequire(import.meta.url);
|
|
33
|
-
req.resolve(MATRIX_SDK_PACKAGE);
|
|
34
|
-
return true;
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function resolvePluginRoot(): string {
|
|
41
|
-
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
42
|
-
return path.resolve(currentDir, "..", "..");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function ensureMatrixCryptoRuntime(
|
|
46
|
-
params: {
|
|
47
|
-
log?: (message: string) => void;
|
|
48
|
-
requireFn?: (id: string) => unknown;
|
|
49
|
-
resolveFn?: (id: string) => string;
|
|
50
|
-
runCommand?: typeof runPluginCommandWithTimeout;
|
|
51
|
-
nodeExecutable?: string;
|
|
52
|
-
} = {},
|
|
53
|
-
): Promise<void> {
|
|
54
|
-
const req = createRequire(import.meta.url);
|
|
55
|
-
const requireFn = params.requireFn ?? ((id: string) => req(id));
|
|
56
|
-
const resolveFn = params.resolveFn ?? ((id: string) => req.resolve(id));
|
|
57
|
-
const runCommand = params.runCommand ?? runPluginCommandWithTimeout;
|
|
58
|
-
const nodeExecutable = params.nodeExecutable ?? process.execPath;
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
requireFn(MATRIX_SDK_PACKAGE);
|
|
62
|
-
return;
|
|
63
|
-
} catch (err) {
|
|
64
|
-
if (!isMissingMatrixCryptoRuntimeError(err)) {
|
|
65
|
-
throw err;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const scriptPath = resolveFn(MATRIX_CRYPTO_DOWNLOAD_HELPER);
|
|
70
|
-
params.log?.("matrix: crypto runtime missing; downloading platform library…");
|
|
71
|
-
const result = await runCommand({
|
|
72
|
-
argv: [nodeExecutable, scriptPath],
|
|
73
|
-
cwd: path.dirname(scriptPath),
|
|
74
|
-
timeoutMs: 300_000,
|
|
75
|
-
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
|
|
76
|
-
});
|
|
77
|
-
if (result.code !== 0) {
|
|
78
|
-
throw new Error(`Matrix crypto runtime bootstrap failed: ${formatCommandError(result)}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
requireFn(MATRIX_SDK_PACKAGE);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
throw new Error(
|
|
85
|
-
`Matrix crypto runtime remains unavailable after bootstrap: ${err instanceof Error ? err.message : String(err)}`,
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export async function ensureMatrixSdkInstalled(params: {
|
|
91
|
-
runtime: RuntimeEnv;
|
|
92
|
-
confirm?: (message: string) => Promise<boolean>;
|
|
93
|
-
}): Promise<void> {
|
|
94
|
-
if (isMatrixSdkAvailable()) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const confirm = params.confirm;
|
|
98
|
-
if (confirm) {
|
|
99
|
-
const ok = await confirm("Matrix requires @vector-im/matrix-bot-sdk. Install now?");
|
|
100
|
-
if (!ok) {
|
|
101
|
-
throw new Error("Matrix requires @vector-im/matrix-bot-sdk (install dependencies first).");
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const root = resolvePluginRoot();
|
|
106
|
-
const command = fs.existsSync(path.join(root, "pnpm-lock.yaml"))
|
|
107
|
-
? ["pnpm", "install"]
|
|
108
|
-
: ["npm", "install", "--omit=dev", "--silent"];
|
|
109
|
-
params.runtime.log?.(`matrix: installing dependencies via ${command[0]} (${root})…`);
|
|
110
|
-
const result = await runPluginCommandWithTimeout({
|
|
111
|
-
argv: command,
|
|
112
|
-
cwd: root,
|
|
113
|
-
timeoutMs: 300_000,
|
|
114
|
-
env: { COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" },
|
|
115
|
-
});
|
|
116
|
-
if (result.code !== 0) {
|
|
117
|
-
throw new Error(
|
|
118
|
-
result.stderr.trim() || result.stdout.trim() || "Matrix dependency install failed.",
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
if (!isMatrixSdkAvailable()) {
|
|
122
|
-
throw new Error(
|
|
123
|
-
"Matrix dependency install completed but @vector-im/matrix-bot-sdk is still missing.",
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { markdownToMatrixHtml } from "./format.js";
|
|
3
|
-
|
|
4
|
-
describe("markdownToMatrixHtml", () => {
|
|
5
|
-
it("renders basic inline formatting", () => {
|
|
6
|
-
const html = markdownToMatrixHtml("hi _there_ **boss** `code`");
|
|
7
|
-
expect(html).toContain("<em>there</em>");
|
|
8
|
-
expect(html).toContain("<strong>boss</strong>");
|
|
9
|
-
expect(html).toContain("<code>code</code>");
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("renders links as HTML", () => {
|
|
13
|
-
const html = markdownToMatrixHtml("see [docs](https://example.com)");
|
|
14
|
-
expect(html).toContain('<a href="https://example.com">docs</a>');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("escapes raw HTML", () => {
|
|
18
|
-
const html = markdownToMatrixHtml("<b>nope</b>");
|
|
19
|
-
expect(html).toContain("<b>nope</b>");
|
|
20
|
-
expect(html).not.toContain("<b>nope</b>");
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("flattens images into alt text", () => {
|
|
24
|
-
const html = markdownToMatrixHtml("");
|
|
25
|
-
expect(html).toContain("alt");
|
|
26
|
-
expect(html).not.toContain("<img");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("preserves line breaks", () => {
|
|
30
|
-
const html = markdownToMatrixHtml("line1\nline2");
|
|
31
|
-
expect(html).toContain("<br");
|
|
32
|
-
});
|
|
33
|
-
});
|
package/src/matrix/format.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import MarkdownIt from "markdown-it";
|
|
2
|
-
|
|
3
|
-
const md = new MarkdownIt({
|
|
4
|
-
html: false,
|
|
5
|
-
linkify: true,
|
|
6
|
-
breaks: true,
|
|
7
|
-
typographer: false,
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
md.enable("strikethrough");
|
|
11
|
-
|
|
12
|
-
const { escapeHtml } = md.utils;
|
|
13
|
-
|
|
14
|
-
md.renderer.rules.image = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
|
15
|
-
|
|
16
|
-
md.renderer.rules.html_block = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
|
17
|
-
md.renderer.rules.html_inline = (tokens, idx) => escapeHtml(tokens[idx]?.content ?? "");
|
|
18
|
-
|
|
19
|
-
export function markdownToMatrixHtml(markdown: string): string {
|
|
20
|
-
const rendered = md.render(markdown ?? "");
|
|
21
|
-
return rendered.trimEnd();
|
|
22
|
-
}
|
package/src/matrix/index.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export { monitorMatrixProvider } from "./monitor/index.js";
|
|
2
|
-
export { probeMatrix } from "./probe.js";
|
|
3
|
-
export {
|
|
4
|
-
reactMatrixMessage,
|
|
5
|
-
resolveMatrixRoomId,
|
|
6
|
-
sendReadReceiptMatrix,
|
|
7
|
-
sendMessageMatrix,
|
|
8
|
-
sendPollMatrix,
|
|
9
|
-
sendTypingMatrix,
|
|
10
|
-
} from "./send.js";
|
|
11
|
-
export { resolveMatrixAuth, resolveSharedMatrixClient } from "./client.js";
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatAllowlistMatchMeta,
|
|
3
|
-
issuePairingChallenge,
|
|
4
|
-
readStoreAllowFromForDmPolicy,
|
|
5
|
-
resolveDmGroupAccessWithLists,
|
|
6
|
-
resolveSenderScopedGroupPolicy,
|
|
7
|
-
} from "openclaw/plugin-sdk/matrix";
|
|
8
|
-
import {
|
|
9
|
-
normalizeMatrixAllowList,
|
|
10
|
-
resolveMatrixAllowListMatch,
|
|
11
|
-
resolveMatrixAllowListMatches,
|
|
12
|
-
} from "./allowlist.js";
|
|
13
|
-
|
|
14
|
-
type MatrixDmPolicy = "open" | "pairing" | "allowlist" | "disabled";
|
|
15
|
-
type MatrixGroupPolicy = "open" | "allowlist" | "disabled";
|
|
16
|
-
|
|
17
|
-
export async function resolveMatrixAccessState(params: {
|
|
18
|
-
isDirectMessage: boolean;
|
|
19
|
-
resolvedAccountId: string;
|
|
20
|
-
dmPolicy: MatrixDmPolicy;
|
|
21
|
-
groupPolicy: MatrixGroupPolicy;
|
|
22
|
-
allowFrom: string[];
|
|
23
|
-
groupAllowFrom: Array<string | number>;
|
|
24
|
-
senderId: string;
|
|
25
|
-
readStoreForDmPolicy: (provider: string, accountId: string) => Promise<string[]>;
|
|
26
|
-
}) {
|
|
27
|
-
const storeAllowFrom = params.isDirectMessage
|
|
28
|
-
? await readStoreAllowFromForDmPolicy({
|
|
29
|
-
provider: "matrix",
|
|
30
|
-
accountId: params.resolvedAccountId,
|
|
31
|
-
dmPolicy: params.dmPolicy,
|
|
32
|
-
readStore: params.readStoreForDmPolicy,
|
|
33
|
-
})
|
|
34
|
-
: [];
|
|
35
|
-
const normalizedGroupAllowFrom = normalizeMatrixAllowList(params.groupAllowFrom);
|
|
36
|
-
const senderGroupPolicy = resolveSenderScopedGroupPolicy({
|
|
37
|
-
groupPolicy: params.groupPolicy,
|
|
38
|
-
groupAllowFrom: normalizedGroupAllowFrom,
|
|
39
|
-
});
|
|
40
|
-
const access = resolveDmGroupAccessWithLists({
|
|
41
|
-
isGroup: !params.isDirectMessage,
|
|
42
|
-
dmPolicy: params.dmPolicy,
|
|
43
|
-
groupPolicy: senderGroupPolicy,
|
|
44
|
-
allowFrom: params.allowFrom,
|
|
45
|
-
groupAllowFrom: normalizedGroupAllowFrom,
|
|
46
|
-
storeAllowFrom,
|
|
47
|
-
groupAllowFromFallbackToAllowFrom: false,
|
|
48
|
-
isSenderAllowed: (allowFrom) =>
|
|
49
|
-
resolveMatrixAllowListMatches({
|
|
50
|
-
allowList: normalizeMatrixAllowList(allowFrom),
|
|
51
|
-
userId: params.senderId,
|
|
52
|
-
}),
|
|
53
|
-
});
|
|
54
|
-
const effectiveAllowFrom = normalizeMatrixAllowList(access.effectiveAllowFrom);
|
|
55
|
-
const effectiveGroupAllowFrom = normalizeMatrixAllowList(access.effectiveGroupAllowFrom);
|
|
56
|
-
return {
|
|
57
|
-
access,
|
|
58
|
-
effectiveAllowFrom,
|
|
59
|
-
effectiveGroupAllowFrom,
|
|
60
|
-
groupAllowConfigured: effectiveGroupAllowFrom.length > 0,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export async function enforceMatrixDirectMessageAccess(params: {
|
|
65
|
-
dmEnabled: boolean;
|
|
66
|
-
dmPolicy: MatrixDmPolicy;
|
|
67
|
-
accessDecision: "allow" | "block" | "pairing";
|
|
68
|
-
senderId: string;
|
|
69
|
-
senderName: string;
|
|
70
|
-
effectiveAllowFrom: string[];
|
|
71
|
-
upsertPairingRequest: (input: {
|
|
72
|
-
id: string;
|
|
73
|
-
meta?: Record<string, string | undefined>;
|
|
74
|
-
}) => Promise<{
|
|
75
|
-
code: string;
|
|
76
|
-
created: boolean;
|
|
77
|
-
}>;
|
|
78
|
-
sendPairingReply: (text: string) => Promise<void>;
|
|
79
|
-
logVerboseMessage: (message: string) => void;
|
|
80
|
-
}): Promise<boolean> {
|
|
81
|
-
if (!params.dmEnabled) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
if (params.accessDecision === "allow") {
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
const allowMatch = resolveMatrixAllowListMatch({
|
|
88
|
-
allowList: params.effectiveAllowFrom,
|
|
89
|
-
userId: params.senderId,
|
|
90
|
-
});
|
|
91
|
-
const allowMatchMeta = formatAllowlistMatchMeta(allowMatch);
|
|
92
|
-
if (params.accessDecision === "pairing") {
|
|
93
|
-
await issuePairingChallenge({
|
|
94
|
-
channel: "matrix",
|
|
95
|
-
senderId: params.senderId,
|
|
96
|
-
senderIdLine: `Matrix user id: ${params.senderId}`,
|
|
97
|
-
meta: { name: params.senderName },
|
|
98
|
-
upsertPairingRequest: params.upsertPairingRequest,
|
|
99
|
-
buildReplyText: ({ code }) =>
|
|
100
|
-
[
|
|
101
|
-
"OpenClaw: access not configured.",
|
|
102
|
-
"",
|
|
103
|
-
`Pairing code: ${code}`,
|
|
104
|
-
"",
|
|
105
|
-
"Ask the bot owner to approve with:",
|
|
106
|
-
"openclaw pairing approve matrix <code>",
|
|
107
|
-
].join("\n"),
|
|
108
|
-
sendPairingReply: params.sendPairingReply,
|
|
109
|
-
onCreated: () => {
|
|
110
|
-
params.logVerboseMessage(
|
|
111
|
-
`matrix pairing request sender=${params.senderId} name=${params.senderName ?? "unknown"} (${allowMatchMeta})`,
|
|
112
|
-
);
|
|
113
|
-
},
|
|
114
|
-
onReplyError: (err) => {
|
|
115
|
-
params.logVerboseMessage(
|
|
116
|
-
`matrix pairing reply failed for ${params.senderId}: ${String(err)}`,
|
|
117
|
-
);
|
|
118
|
-
},
|
|
119
|
-
});
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
params.logVerboseMessage(
|
|
123
|
-
`matrix: blocked dm sender ${params.senderId} (dmPolicy=${params.dmPolicy}, ${allowMatchMeta})`,
|
|
124
|
-
);
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { normalizeMatrixAllowList, resolveMatrixAllowListMatch } from "./allowlist.js";
|
|
3
|
-
|
|
4
|
-
describe("resolveMatrixAllowListMatch", () => {
|
|
5
|
-
it("matches full user IDs and prefixes", () => {
|
|
6
|
-
const userId = "@Alice:Example.org";
|
|
7
|
-
const direct = resolveMatrixAllowListMatch({
|
|
8
|
-
allowList: normalizeMatrixAllowList(["@alice:example.org"]),
|
|
9
|
-
userId,
|
|
10
|
-
});
|
|
11
|
-
expect(direct.allowed).toBe(true);
|
|
12
|
-
expect(direct.matchSource).toBe("id");
|
|
13
|
-
|
|
14
|
-
const prefixedMatrix = resolveMatrixAllowListMatch({
|
|
15
|
-
allowList: normalizeMatrixAllowList(["matrix:@alice:example.org"]),
|
|
16
|
-
userId,
|
|
17
|
-
});
|
|
18
|
-
expect(prefixedMatrix.allowed).toBe(true);
|
|
19
|
-
expect(prefixedMatrix.matchSource).toBe("prefixed-id");
|
|
20
|
-
|
|
21
|
-
const prefixedUser = resolveMatrixAllowListMatch({
|
|
22
|
-
allowList: normalizeMatrixAllowList(["user:@alice:example.org"]),
|
|
23
|
-
userId,
|
|
24
|
-
});
|
|
25
|
-
expect(prefixedUser.allowed).toBe(true);
|
|
26
|
-
expect(prefixedUser.matchSource).toBe("prefixed-user");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("ignores display names and localparts", () => {
|
|
30
|
-
const match = resolveMatrixAllowListMatch({
|
|
31
|
-
allowList: normalizeMatrixAllowList(["alice", "Alice"]),
|
|
32
|
-
userId: "@alice:example.org",
|
|
33
|
-
});
|
|
34
|
-
expect(match.allowed).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("matches wildcard", () => {
|
|
38
|
-
const match = resolveMatrixAllowListMatch({
|
|
39
|
-
allowList: normalizeMatrixAllowList(["*"]),
|
|
40
|
-
userId: "@alice:example.org",
|
|
41
|
-
});
|
|
42
|
-
expect(match.allowed).toBe(true);
|
|
43
|
-
expect(match.matchSource).toBe("wildcard");
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
compileAllowlist,
|
|
3
|
-
normalizeStringEntries,
|
|
4
|
-
resolveCompiledAllowlistMatch,
|
|
5
|
-
type AllowlistMatch,
|
|
6
|
-
} from "openclaw/plugin-sdk/matrix";
|
|
7
|
-
|
|
8
|
-
function normalizeAllowList(list?: Array<string | number>) {
|
|
9
|
-
return normalizeStringEntries(list);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function normalizeMatrixUser(raw?: string | null): string {
|
|
13
|
-
const value = (raw ?? "").trim();
|
|
14
|
-
if (!value) {
|
|
15
|
-
return "";
|
|
16
|
-
}
|
|
17
|
-
if (!value.startsWith("@") || !value.includes(":")) {
|
|
18
|
-
return value.toLowerCase();
|
|
19
|
-
}
|
|
20
|
-
const withoutAt = value.slice(1);
|
|
21
|
-
const splitIndex = withoutAt.indexOf(":");
|
|
22
|
-
if (splitIndex === -1) {
|
|
23
|
-
return value.toLowerCase();
|
|
24
|
-
}
|
|
25
|
-
const localpart = withoutAt.slice(0, splitIndex).toLowerCase();
|
|
26
|
-
const server = withoutAt.slice(splitIndex + 1).toLowerCase();
|
|
27
|
-
if (!server) {
|
|
28
|
-
return value.toLowerCase();
|
|
29
|
-
}
|
|
30
|
-
return `@${localpart}:${server.toLowerCase()}`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function normalizeMatrixUserId(raw?: string | null): string {
|
|
34
|
-
const trimmed = (raw ?? "").trim();
|
|
35
|
-
if (!trimmed) {
|
|
36
|
-
return "";
|
|
37
|
-
}
|
|
38
|
-
const lowered = trimmed.toLowerCase();
|
|
39
|
-
if (lowered.startsWith("matrix:")) {
|
|
40
|
-
return normalizeMatrixUser(trimmed.slice("matrix:".length));
|
|
41
|
-
}
|
|
42
|
-
if (lowered.startsWith("user:")) {
|
|
43
|
-
return normalizeMatrixUser(trimmed.slice("user:".length));
|
|
44
|
-
}
|
|
45
|
-
return normalizeMatrixUser(trimmed);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function normalizeMatrixAllowListEntry(raw: string): string {
|
|
49
|
-
const trimmed = raw.trim();
|
|
50
|
-
if (!trimmed) {
|
|
51
|
-
return "";
|
|
52
|
-
}
|
|
53
|
-
if (trimmed === "*") {
|
|
54
|
-
return trimmed;
|
|
55
|
-
}
|
|
56
|
-
const lowered = trimmed.toLowerCase();
|
|
57
|
-
if (lowered.startsWith("matrix:")) {
|
|
58
|
-
return `matrix:${normalizeMatrixUser(trimmed.slice("matrix:".length))}`;
|
|
59
|
-
}
|
|
60
|
-
if (lowered.startsWith("user:")) {
|
|
61
|
-
return `user:${normalizeMatrixUser(trimmed.slice("user:".length))}`;
|
|
62
|
-
}
|
|
63
|
-
return normalizeMatrixUser(trimmed);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function normalizeMatrixAllowList(list?: Array<string | number>) {
|
|
67
|
-
return normalizeAllowList(list).map((entry) => normalizeMatrixAllowListEntry(entry));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export type MatrixAllowListMatch = AllowlistMatch<
|
|
71
|
-
"wildcard" | "id" | "prefixed-id" | "prefixed-user"
|
|
72
|
-
>;
|
|
73
|
-
type MatrixAllowListSource = Exclude<MatrixAllowListMatch["matchSource"], undefined>;
|
|
74
|
-
|
|
75
|
-
export function resolveMatrixAllowListMatch(params: {
|
|
76
|
-
allowList: string[];
|
|
77
|
-
userId?: string;
|
|
78
|
-
}): MatrixAllowListMatch {
|
|
79
|
-
const compiledAllowList = compileAllowlist(params.allowList);
|
|
80
|
-
const userId = normalizeMatrixUser(params.userId);
|
|
81
|
-
const candidates: Array<{ value?: string; source: MatrixAllowListSource }> = [
|
|
82
|
-
{ value: userId, source: "id" },
|
|
83
|
-
{ value: userId ? `matrix:${userId}` : "", source: "prefixed-id" },
|
|
84
|
-
{ value: userId ? `user:${userId}` : "", source: "prefixed-user" },
|
|
85
|
-
];
|
|
86
|
-
return resolveCompiledAllowlistMatch({
|
|
87
|
-
compiledAllowlist: compiledAllowList,
|
|
88
|
-
candidates,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export function resolveMatrixAllowListMatches(params: { allowList: string[]; userId?: string }) {
|
|
93
|
-
return resolveMatrixAllowListMatch(params).allowed;
|
|
94
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
|
|
2
|
-
import type { RuntimeEnv } from "openclaw/plugin-sdk/matrix";
|
|
3
|
-
import { getMatrixRuntime } from "../../runtime.js";
|
|
4
|
-
import type { CoreConfig } from "../../types.js";
|
|
5
|
-
import { loadMatrixSdk } from "../sdk-runtime.js";
|
|
6
|
-
|
|
7
|
-
export function registerMatrixAutoJoin(params: {
|
|
8
|
-
client: MatrixClient;
|
|
9
|
-
cfg: CoreConfig;
|
|
10
|
-
runtime: RuntimeEnv;
|
|
11
|
-
}) {
|
|
12
|
-
const { client, cfg, runtime } = params;
|
|
13
|
-
const core = getMatrixRuntime();
|
|
14
|
-
const logVerbose = (message: string) => {
|
|
15
|
-
if (!core.logging.shouldLogVerbose()) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
runtime.log?.(message);
|
|
19
|
-
};
|
|
20
|
-
const autoJoin = cfg.channels?.matrix?.autoJoin ?? "always";
|
|
21
|
-
const autoJoinAllowlist = cfg.channels?.matrix?.autoJoinAllowlist ?? [];
|
|
22
|
-
|
|
23
|
-
if (autoJoin === "off") {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (autoJoin === "always") {
|
|
28
|
-
// Use the built-in autojoin mixin for "always" mode
|
|
29
|
-
const { AutojoinRoomsMixin } = loadMatrixSdk();
|
|
30
|
-
AutojoinRoomsMixin.setupOnClient(client);
|
|
31
|
-
logVerbose("matrix: auto-join enabled for all invites");
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// For "allowlist" mode, handle invites manually
|
|
36
|
-
client.on("room.invite", async (roomId: string, _inviteEvent: unknown) => {
|
|
37
|
-
if (autoJoin !== "allowlist") {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Get room alias if available
|
|
42
|
-
let alias: string | undefined;
|
|
43
|
-
let altAliases: string[] = [];
|
|
44
|
-
try {
|
|
45
|
-
const aliasState = await client
|
|
46
|
-
.getRoomStateEvent(roomId, "m.room.canonical_alias", "")
|
|
47
|
-
.catch(() => null);
|
|
48
|
-
alias = aliasState?.alias;
|
|
49
|
-
altAliases = Array.isArray(aliasState?.alt_aliases) ? aliasState.alt_aliases : [];
|
|
50
|
-
} catch {
|
|
51
|
-
// Ignore errors
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const allowed =
|
|
55
|
-
autoJoinAllowlist.includes("*") ||
|
|
56
|
-
autoJoinAllowlist.includes(roomId) ||
|
|
57
|
-
(alias ? autoJoinAllowlist.includes(alias) : false) ||
|
|
58
|
-
altAliases.some((value) => autoJoinAllowlist.includes(value));
|
|
59
|
-
|
|
60
|
-
if (!allowed) {
|
|
61
|
-
logVerbose(`matrix: invite ignored (not in allowlist) room=${roomId}`);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
await client.joinRoom(roomId);
|
|
67
|
-
logVerbose(`matrix: joined room ${roomId}`);
|
|
68
|
-
} catch (err) {
|
|
69
|
-
runtime.error?.(`matrix: failed to join room ${roomId}: ${String(err)}`);
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|