@archipelagolab/lobi 1.0.0
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 +164 -0
- package/ENDOFFILE +0 -0
- package/EOF +0 -0
- package/LICENSE +21 -0
- package/SPEC-SUPPORT.md +116 -0
- package/YAMLEND +0 -0
- package/api.ts +18 -0
- package/archipelagolab-lobi-1.0.0.tgz +0 -0
- package/auth-presence.ts +56 -0
- package/channel-plugin-api.ts +3 -0
- package/cli-metadata.ts +11 -0
- package/contract-api.ts +17 -0
- package/docs/CHECKLIST.md +83 -0
- package/docs/FORK_SDK_GUIDE.md +279 -0
- package/helper-api.ts +3 -0
- package/index.test.ts +61 -0
- package/index.ts +65 -0
- package/openclaw.plugin.json +23 -0
- package/package.json +52 -0
- package/plugin-entry.handlers.runtime.ts +1 -0
- package/runtime-api.ts +54 -0
- package/runtime-heavy-api.ts +1 -0
- package/scripts/migrate-to-lobi.sh +72 -0
- package/secret-contract-api.ts +5 -0
- package/setup-entry.ts +13 -0
- package/src/account-selection.test.ts +124 -0
- package/src/account-selection.ts +226 -0
- package/src/actions.account-propagation.test.ts +251 -0
- package/src/actions.test.ts +251 -0
- package/src/actions.ts +336 -0
- package/src/approval-auth.test.ts +23 -0
- package/src/approval-auth.ts +25 -0
- package/src/approval-handler.runtime.test.ts +46 -0
- package/src/approval-handler.runtime.ts +400 -0
- package/src/approval-ids.ts +6 -0
- package/src/approval-native.test.ts +329 -0
- package/src/approval-native.ts +336 -0
- package/src/approval-reactions.test.ts +107 -0
- package/src/approval-reactions.ts +158 -0
- package/src/auth-precedence.ts +61 -0
- package/src/channel-account-paths.ts +92 -0
- package/src/channel.account-paths.test.ts +102 -0
- package/src/channel.directory.test.ts +601 -0
- package/src/channel.resolve.test.ts +38 -0
- package/src/channel.runtime.ts +16 -0
- package/src/channel.setup.test.ts +269 -0
- package/src/channel.ts +570 -0
- package/src/cli-metadata.ts +19 -0
- package/src/cli.test.ts +1015 -0
- package/src/cli.ts +1198 -0
- package/src/config-adapter.ts +41 -0
- package/src/config-schema.test.ts +90 -0
- package/src/config-schema.ts +114 -0
- package/src/directory-live.test.ts +200 -0
- package/src/directory-live.ts +238 -0
- package/src/doctor-contract.ts +287 -0
- package/src/doctor.test.ts +440 -0
- package/src/doctor.ts +262 -0
- package/src/env-vars.ts +92 -0
- package/src/exec-approval-resolver.test.ts +68 -0
- package/src/exec-approval-resolver.ts +23 -0
- package/src/exec-approvals.test.ts +483 -0
- package/src/exec-approvals.ts +290 -0
- package/src/group-mentions.ts +41 -0
- package/src/legacy-crypto-inspector-availability.test.ts +81 -0
- package/src/legacy-crypto-inspector-availability.ts +60 -0
- package/src/legacy-crypto.test.ts +234 -0
- package/src/legacy-crypto.ts +549 -0
- package/src/legacy-state.test.ts +86 -0
- package/src/legacy-state.ts +156 -0
- package/src/matrix/account-config.ts +150 -0
- package/src/matrix/accounts.readiness.test.ts +27 -0
- package/src/matrix/accounts.test.ts +757 -0
- package/src/matrix/accounts.ts +194 -0
- package/src/matrix/actions/client.test.ts +215 -0
- package/src/matrix/actions/client.ts +31 -0
- package/src/matrix/actions/devices.test.ts +114 -0
- package/src/matrix/actions/devices.ts +34 -0
- package/src/matrix/actions/limits.test.ts +15 -0
- package/src/matrix/actions/limits.ts +6 -0
- package/src/matrix/actions/messages.test.ts +289 -0
- package/src/matrix/actions/messages.ts +123 -0
- package/src/matrix/actions/pins.test.ts +74 -0
- package/src/matrix/actions/pins.ts +64 -0
- package/src/matrix/actions/polls.test.ts +71 -0
- package/src/matrix/actions/polls.ts +109 -0
- package/src/matrix/actions/profile.test.ts +109 -0
- package/src/matrix/actions/profile.ts +37 -0
- package/src/matrix/actions/reactions.test.ts +135 -0
- package/src/matrix/actions/reactions.ts +59 -0
- package/src/matrix/actions/room.test.ts +79 -0
- package/src/matrix/actions/room.ts +71 -0
- package/src/matrix/actions/summary.test.ts +87 -0
- package/src/matrix/actions/summary.ts +88 -0
- package/src/matrix/actions/types.ts +82 -0
- package/src/matrix/actions/verification.test.ts +105 -0
- package/src/matrix/actions/verification.ts +237 -0
- package/src/matrix/actions.ts +37 -0
- package/src/matrix/active-client.ts +26 -0
- package/src/matrix/async-lock.ts +18 -0
- package/src/matrix/backup-health.ts +115 -0
- package/src/matrix/client/config-runtime-api.ts +14 -0
- package/src/matrix/client/config-secret-input.runtime.ts +1 -0
- package/src/matrix/client/config.ts +982 -0
- package/src/matrix/client/create-client.test.ts +115 -0
- package/src/matrix/client/create-client.ts +101 -0
- package/src/matrix/client/env-auth.ts +6 -0
- package/src/matrix/client/file-sync-store.test.ts +265 -0
- package/src/matrix/client/file-sync-store.ts +289 -0
- package/src/matrix/client/logging.ts +123 -0
- package/src/matrix/client/migration-snapshot.runtime.ts +1 -0
- package/src/matrix/client/private-network-host.ts +56 -0
- package/src/matrix/client/runtime.ts +4 -0
- package/src/matrix/client/shared.test.ts +344 -0
- package/src/matrix/client/shared.ts +306 -0
- package/src/matrix/client/storage.test.ts +634 -0
- package/src/matrix/client/storage.ts +544 -0
- package/src/matrix/client/types.ts +50 -0
- package/src/matrix/client-bootstrap.test.ts +84 -0
- package/src/matrix/client-bootstrap.ts +164 -0
- package/src/matrix/client-resolver.test-helpers.ts +147 -0
- package/src/matrix/client.test.ts +1521 -0
- package/src/matrix/client.ts +23 -0
- package/src/matrix/config-paths.ts +31 -0
- package/src/matrix/config-update.test.ts +237 -0
- package/src/matrix/config-update.ts +291 -0
- package/src/matrix/credentials-read.ts +206 -0
- package/src/matrix/credentials-write.runtime.ts +26 -0
- package/src/matrix/credentials.test.ts +501 -0
- package/src/matrix/credentials.ts +95 -0
- package/src/matrix/deps.test.ts +74 -0
- package/src/matrix/deps.ts +225 -0
- package/src/matrix/device-health.test.ts +45 -0
- package/src/matrix/device-health.ts +31 -0
- package/src/matrix/direct-management.test.ts +350 -0
- package/src/matrix/direct-management.ts +347 -0
- package/src/matrix/direct-room.test.ts +61 -0
- package/src/matrix/direct-room.ts +128 -0
- package/src/matrix/draft-stream.test.ts +406 -0
- package/src/matrix/draft-stream.ts +216 -0
- package/src/matrix/encryption-guidance.ts +27 -0
- package/src/matrix/errors.ts +21 -0
- package/src/matrix/format.test.ts +340 -0
- package/src/matrix/format.ts +428 -0
- package/src/matrix/legacy-crypto-inspector.ts +95 -0
- package/src/matrix/media-errors.ts +20 -0
- package/src/matrix/media-text.ts +169 -0
- package/src/matrix/monitor/access-state.test.ts +45 -0
- package/src/matrix/monitor/access-state.ts +77 -0
- package/src/matrix/monitor/ack-config.test.ts +57 -0
- package/src/matrix/monitor/ack-config.ts +26 -0
- package/src/matrix/monitor/allowlist.test.ts +45 -0
- package/src/matrix/monitor/allowlist.ts +94 -0
- package/src/matrix/monitor/auto-join.test.ts +203 -0
- package/src/matrix/monitor/auto-join.ts +86 -0
- package/src/matrix/monitor/config.test.ts +197 -0
- package/src/matrix/monitor/config.ts +303 -0
- package/src/matrix/monitor/context-summary.ts +43 -0
- package/src/matrix/monitor/direct.test.ts +529 -0
- package/src/matrix/monitor/direct.ts +270 -0
- package/src/matrix/monitor/events.test.ts +1524 -0
- package/src/matrix/monitor/events.ts +213 -0
- package/src/matrix/monitor/handler.body-for-agent.test.ts +396 -0
- package/src/matrix/monitor/handler.group-history.test.ts +648 -0
- package/src/matrix/monitor/handler.media-failure.test.ts +267 -0
- package/src/matrix/monitor/handler.test-helpers.ts +308 -0
- package/src/matrix/monitor/handler.test.ts +2952 -0
- package/src/matrix/monitor/handler.thread-root-media.test.ts +82 -0
- package/src/matrix/monitor/handler.ts +1679 -0
- package/src/matrix/monitor/inbound-dedupe.test.ts +146 -0
- package/src/matrix/monitor/inbound-dedupe.ts +267 -0
- package/src/matrix/monitor/index.test.ts +920 -0
- package/src/matrix/monitor/index.ts +434 -0
- package/src/matrix/monitor/legacy-crypto-restore.test.ts +206 -0
- package/src/matrix/monitor/legacy-crypto-restore.ts +139 -0
- package/src/matrix/monitor/location.ts +100 -0
- package/src/matrix/monitor/media.test.ts +159 -0
- package/src/matrix/monitor/media.ts +119 -0
- package/src/matrix/monitor/mentions.test.ts +289 -0
- package/src/matrix/monitor/mentions.ts +177 -0
- package/src/matrix/monitor/reaction-events.test.ts +326 -0
- package/src/matrix/monitor/reaction-events.ts +187 -0
- package/src/matrix/monitor/recent-invite.test.ts +92 -0
- package/src/matrix/monitor/recent-invite.ts +30 -0
- package/src/matrix/monitor/replies.test.ts +265 -0
- package/src/matrix/monitor/replies.ts +136 -0
- package/src/matrix/monitor/reply-context.test.ts +276 -0
- package/src/matrix/monitor/reply-context.ts +92 -0
- package/src/matrix/monitor/room-history.test.ts +258 -0
- package/src/matrix/monitor/room-history.ts +301 -0
- package/src/matrix/monitor/room-info.test.ts +201 -0
- package/src/matrix/monitor/room-info.ts +126 -0
- package/src/matrix/monitor/rooms.test.ts +121 -0
- package/src/matrix/monitor/rooms.ts +52 -0
- package/src/matrix/monitor/route.test.ts +255 -0
- package/src/matrix/monitor/route.ts +178 -0
- package/src/matrix/monitor/runtime-api.ts +31 -0
- package/src/matrix/monitor/startup-verification.test.ts +294 -0
- package/src/matrix/monitor/startup-verification.ts +237 -0
- package/src/matrix/monitor/startup.test.ts +257 -0
- package/src/matrix/monitor/startup.ts +218 -0
- package/src/matrix/monitor/status.ts +111 -0
- package/src/matrix/monitor/sync-lifecycle.test.ts +224 -0
- package/src/matrix/monitor/sync-lifecycle.ts +91 -0
- package/src/matrix/monitor/task-runner.ts +38 -0
- package/src/matrix/monitor/thread-context.test.ts +149 -0
- package/src/matrix/monitor/thread-context.ts +108 -0
- package/src/matrix/monitor/threads.test.ts +68 -0
- package/src/matrix/monitor/threads.ts +85 -0
- package/src/matrix/monitor/types.ts +30 -0
- package/src/matrix/monitor/verification-events.ts +627 -0
- package/src/matrix/monitor/verification-utils.test.ts +47 -0
- package/src/matrix/monitor/verification-utils.ts +46 -0
- package/src/matrix/outbound-media-runtime.ts +1 -0
- package/src/matrix/poll-summary.ts +110 -0
- package/src/matrix/poll-types.test.ts +205 -0
- package/src/matrix/poll-types.ts +433 -0
- package/src/matrix/probe.runtime.ts +4 -0
- package/src/matrix/probe.test.ts +154 -0
- package/src/matrix/probe.ts +96 -0
- package/src/matrix/profile.test.ts +154 -0
- package/src/matrix/profile.ts +184 -0
- package/src/matrix/reaction-common.test.ts +96 -0
- package/src/matrix/reaction-common.ts +147 -0
- package/src/matrix/sdk/crypto-bootstrap.test.ts +505 -0
- package/src/matrix/sdk/crypto-bootstrap.ts +341 -0
- package/src/matrix/sdk/crypto-facade.test.ts +197 -0
- package/src/matrix/sdk/crypto-facade.ts +207 -0
- package/src/matrix/sdk/crypto-node.runtime.test.ts +27 -0
- package/src/matrix/sdk/crypto-node.runtime.ts +9 -0
- package/src/matrix/sdk/crypto-runtime.ts +11 -0
- package/src/matrix/sdk/decrypt-bridge.ts +356 -0
- package/src/matrix/sdk/event-helpers.test.ts +60 -0
- package/src/matrix/sdk/event-helpers.ts +71 -0
- package/src/matrix/sdk/http-client.test.ts +134 -0
- package/src/matrix/sdk/http-client.ts +87 -0
- package/src/matrix/sdk/idb-persistence-lock.ts +51 -0
- package/src/matrix/sdk/idb-persistence.lock-order.test.ts +108 -0
- package/src/matrix/sdk/idb-persistence.test-helpers.ts +88 -0
- package/src/matrix/sdk/idb-persistence.test.ts +149 -0
- package/src/matrix/sdk/idb-persistence.ts +283 -0
- package/src/matrix/sdk/logger.test.ts +25 -0
- package/src/matrix/sdk/logger.ts +108 -0
- package/src/matrix/sdk/read-response-with-limit.ts +19 -0
- package/src/matrix/sdk/recovery-key-store.test.ts +385 -0
- package/src/matrix/sdk/recovery-key-store.ts +430 -0
- package/src/matrix/sdk/transport.test.ts +161 -0
- package/src/matrix/sdk/transport.ts +344 -0
- package/src/matrix/sdk/types.ts +236 -0
- package/src/matrix/sdk/verification-manager.test.ts +509 -0
- package/src/matrix/sdk/verification-manager.ts +694 -0
- package/src/matrix/sdk/verification-status.ts +23 -0
- package/src/matrix/sdk.test.ts +2568 -0
- package/src/matrix/sdk.ts +1789 -0
- package/src/matrix/send/client.test.ts +174 -0
- package/src/matrix/send/client.ts +90 -0
- package/src/matrix/send/formatting.ts +189 -0
- package/src/matrix/send/media.ts +244 -0
- package/src/matrix/send/targets.test.ts +254 -0
- package/src/matrix/send/targets.ts +104 -0
- package/src/matrix/send/types.ts +134 -0
- package/src/matrix/send.test.ts +958 -0
- package/src/matrix/send.ts +609 -0
- package/src/matrix/session-store-metadata.ts +108 -0
- package/src/matrix/startup-abort.ts +44 -0
- package/src/matrix/sync-state.ts +27 -0
- package/src/matrix/target-ids.ts +102 -0
- package/src/matrix/thread-bindings-shared.ts +201 -0
- package/src/matrix/thread-bindings.test.ts +673 -0
- package/src/matrix/thread-bindings.ts +577 -0
- package/src/matrix-migration.runtime.ts +9 -0
- package/src/migration-config.test.ts +228 -0
- package/src/migration-config.ts +243 -0
- package/src/migration-snapshot-backup.ts +117 -0
- package/src/migration-snapshot.test.ts +184 -0
- package/src/migration-snapshot.ts +55 -0
- package/src/onboarding.resolve.test.ts +55 -0
- package/src/onboarding.test-harness.ts +158 -0
- package/src/onboarding.test.ts +665 -0
- package/src/onboarding.ts +773 -0
- package/src/outbound.test.ts +173 -0
- package/src/outbound.ts +78 -0
- package/src/plugin-entry.runtime.js +159 -0
- package/src/plugin-entry.runtime.test.ts +108 -0
- package/src/plugin-entry.runtime.ts +68 -0
- package/src/profile-update.ts +68 -0
- package/src/record-shared.ts +3 -0
- package/src/resolve-targets.test.ts +178 -0
- package/src/resolve-targets.ts +175 -0
- package/src/resolver.ts +21 -0
- package/src/runtime-api.ts +144 -0
- package/src/runtime.ts +7 -0
- package/src/secret-contract.ts +174 -0
- package/src/session-route.test.ts +315 -0
- package/src/session-route.ts +113 -0
- package/src/setup-bootstrap.ts +94 -0
- package/src/setup-config.ts +222 -0
- package/src/setup-contract.ts +89 -0
- package/src/setup-core.test.ts +326 -0
- package/src/setup-core.ts +50 -0
- package/src/setup-surface.ts +4 -0
- package/src/startup-maintenance.test.ts +227 -0
- package/src/startup-maintenance.ts +114 -0
- package/src/storage-paths.ts +92 -0
- package/src/test-helpers.ts +42 -0
- package/src/test-mocks.ts +55 -0
- package/src/test-runtime.ts +72 -0
- package/src/test-support/monitor-route-test-support.ts +8 -0
- package/src/tool-actions.runtime.ts +1 -0
- package/src/tool-actions.test.ts +422 -0
- package/src/tool-actions.ts +498 -0
- package/src/types.ts +230 -0
- package/test-api.ts +2 -0
- package/thread-bindings-runtime.ts +4 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
findMatrixAccountEntry,
|
|
5
|
+
requiresExplicitMatrixDefaultAccount,
|
|
6
|
+
resolveConfiguredMatrixAccountIds,
|
|
7
|
+
resolveMatrixDefaultOrOnlyAccountId,
|
|
8
|
+
} from "./account-selection.js";
|
|
9
|
+
import { getMatrixScopedEnvVarNames } from "./env-vars.js";
|
|
10
|
+
|
|
11
|
+
describe("matrix account selection", () => {
|
|
12
|
+
it("resolves configured account ids from non-canonical account keys", () => {
|
|
13
|
+
const cfg: OpenClawConfig = {
|
|
14
|
+
channels: {
|
|
15
|
+
matrix: {
|
|
16
|
+
accounts: {
|
|
17
|
+
"Team Ops": { homeserver: "https://matrix.example.org" },
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
expect(resolveConfiguredMatrixAccountIds(cfg)).toEqual(["team-ops"]);
|
|
24
|
+
expect(resolveMatrixDefaultOrOnlyAccountId(cfg)).toBe("team-ops");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("matches the default account against normalized Matrix account keys", () => {
|
|
28
|
+
const cfg: OpenClawConfig = {
|
|
29
|
+
channels: {
|
|
30
|
+
matrix: {
|
|
31
|
+
defaultAccount: "Team Ops",
|
|
32
|
+
accounts: {
|
|
33
|
+
"Ops Bot": { homeserver: "https://matrix.example.org" },
|
|
34
|
+
"Team Ops": { homeserver: "https://matrix.example.org" },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
expect(resolveMatrixDefaultOrOnlyAccountId(cfg)).toBe("team-ops");
|
|
41
|
+
expect(requiresExplicitMatrixDefaultAccount(cfg)).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("requires an explicit default when multiple Matrix accounts exist without one", () => {
|
|
45
|
+
const cfg: OpenClawConfig = {
|
|
46
|
+
channels: {
|
|
47
|
+
matrix: {
|
|
48
|
+
accounts: {
|
|
49
|
+
ops: { homeserver: "https://matrix.example.org" },
|
|
50
|
+
alerts: { homeserver: "https://matrix.example.org" },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
expect(requiresExplicitMatrixDefaultAccount(cfg)).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("finds the raw Matrix account entry by normalized account id", () => {
|
|
60
|
+
const cfg: OpenClawConfig = {
|
|
61
|
+
channels: {
|
|
62
|
+
matrix: {
|
|
63
|
+
accounts: {
|
|
64
|
+
"Team Ops": {
|
|
65
|
+
homeserver: "https://matrix.example.org",
|
|
66
|
+
userId: "@ops:example.org",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
expect(findMatrixAccountEntry(cfg, "team-ops")).toEqual({
|
|
74
|
+
homeserver: "https://matrix.example.org",
|
|
75
|
+
userId: "@ops:example.org",
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("discovers env-backed named Matrix accounts during enumeration", () => {
|
|
80
|
+
const keys = getMatrixScopedEnvVarNames("team-ops");
|
|
81
|
+
const cfg: OpenClawConfig = {
|
|
82
|
+
channels: {
|
|
83
|
+
matrix: {},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
const env = {
|
|
87
|
+
[keys.homeserver]: "https://matrix.example.org",
|
|
88
|
+
[keys.accessToken]: "secret",
|
|
89
|
+
} satisfies NodeJS.ProcessEnv;
|
|
90
|
+
|
|
91
|
+
expect(resolveConfiguredMatrixAccountIds(cfg, env)).toEqual(["team-ops"]);
|
|
92
|
+
expect(resolveMatrixDefaultOrOnlyAccountId(cfg, env)).toBe("team-ops");
|
|
93
|
+
expect(requiresExplicitMatrixDefaultAccount(cfg, env)).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("treats mixed default and named env-backed Matrix accounts as multi-account", () => {
|
|
97
|
+
const keys = getMatrixScopedEnvVarNames("team-ops");
|
|
98
|
+
const cfg: OpenClawConfig = {
|
|
99
|
+
channels: {
|
|
100
|
+
matrix: {},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
const env = {
|
|
104
|
+
LOBI_HOMESERVER: "https://matrix.example.org",
|
|
105
|
+
LOBI_ACCESS_TOKEN: "default-secret",
|
|
106
|
+
[keys.homeserver]: "https://matrix.example.org",
|
|
107
|
+
[keys.accessToken]: "team-secret",
|
|
108
|
+
} satisfies NodeJS.ProcessEnv;
|
|
109
|
+
|
|
110
|
+
expect(resolveConfiguredMatrixAccountIds(cfg, env)).toEqual(["default", "team-ops"]);
|
|
111
|
+
expect(requiresExplicitMatrixDefaultAccount(cfg, env)).toBe(true);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("discovers default Matrix accounts backed only by global env vars", () => {
|
|
115
|
+
const cfg: OpenClawConfig = {};
|
|
116
|
+
const env = {
|
|
117
|
+
LOBI_HOMESERVER: "https://matrix.example.org",
|
|
118
|
+
LOBI_ACCESS_TOKEN: "default-secret",
|
|
119
|
+
} satisfies NodeJS.ProcessEnv;
|
|
120
|
+
|
|
121
|
+
expect(resolveConfiguredMatrixAccountIds(cfg, env)).toEqual(["default"]);
|
|
122
|
+
expect(resolveMatrixDefaultOrOnlyAccountId(cfg, env)).toBe("default");
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
listCombinedAccountIds,
|
|
3
|
+
listConfiguredAccountIds,
|
|
4
|
+
resolveListedDefaultAccountId,
|
|
5
|
+
resolveNormalizedAccountEntry,
|
|
6
|
+
} from "openclaw/plugin-sdk/account-core";
|
|
7
|
+
import {
|
|
8
|
+
DEFAULT_ACCOUNT_ID,
|
|
9
|
+
normalizeAccountId,
|
|
10
|
+
normalizeOptionalAccountId,
|
|
11
|
+
} from "openclaw/plugin-sdk/account-id";
|
|
12
|
+
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
|
13
|
+
import { hasConfiguredSecretInput } from "openclaw/plugin-sdk/secret-input";
|
|
14
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
15
|
+
import {
|
|
16
|
+
resolveMatrixAccountStringValues,
|
|
17
|
+
type MatrixResolvedStringField,
|
|
18
|
+
} from "./auth-precedence.js";
|
|
19
|
+
import { getLobiScopedEnvVarNames as getMatrixScopedEnvVarNames, listLobiEnvAccountIds as listMatrixEnvAccountIds } from "./env-vars.js";
|
|
20
|
+
import { isRecord } from "./record-shared.js";
|
|
21
|
+
|
|
22
|
+
type MatrixTopologyStringSources = Partial<Record<MatrixResolvedStringField, string>>;
|
|
23
|
+
|
|
24
|
+
function readConfiguredMatrixString(value: unknown): string {
|
|
25
|
+
return normalizeOptionalString(value) ?? "";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function readConfiguredMatrixSecretSource(value: unknown): string {
|
|
29
|
+
return hasConfiguredSecretInput(value) ? "configured" : "";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function resolveMatrixChannelStringSources(
|
|
33
|
+
entry: Record<string, unknown> | null,
|
|
34
|
+
): MatrixTopologyStringSources {
|
|
35
|
+
if (!entry) {
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
homeserver: readConfiguredMatrixString(entry.homeserver),
|
|
40
|
+
userId: readConfiguredMatrixString(entry.userId),
|
|
41
|
+
accessToken: readConfiguredMatrixSecretSource(entry.accessToken),
|
|
42
|
+
password: readConfiguredMatrixSecretSource(entry.password),
|
|
43
|
+
deviceId: readConfiguredMatrixString(entry.deviceId),
|
|
44
|
+
deviceName: readConfiguredMatrixString(entry.deviceName),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const DEFAULT_LOBI_HOMESERVER = "https://lobi.lobisland.com/";
|
|
49
|
+
|
|
50
|
+
function readEnvLobiString(env: NodeJS.ProcessEnv, key: string): string {
|
|
51
|
+
const value = normalizeOptionalString(env[key]);
|
|
52
|
+
if (key === "LOBI_HOMESERVER" && !value) {
|
|
53
|
+
return DEFAULT_LOBI_HOMESERVER;
|
|
54
|
+
}
|
|
55
|
+
return value ?? "";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveScopedLobiEnvStringSources(
|
|
59
|
+
accountId: string,
|
|
60
|
+
env: NodeJS.ProcessEnv,
|
|
61
|
+
): MatrixTopologyStringSources {
|
|
62
|
+
const keys = getMatrixScopedEnvVarNames(accountId);
|
|
63
|
+
return {
|
|
64
|
+
homeserver: readEnvLobiString(env, keys.homeserver),
|
|
65
|
+
userId: readEnvLobiString(env, keys.userId),
|
|
66
|
+
accessToken: readEnvLobiString(env, keys.accessToken),
|
|
67
|
+
password: readEnvLobiString(env, keys.password),
|
|
68
|
+
deviceId: readEnvLobiString(env, keys.deviceId),
|
|
69
|
+
deviceName: readEnvLobiString(env, keys.deviceName),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function resolveGlobalLobiEnvStringSources(env: NodeJS.ProcessEnv): MatrixTopologyStringSources {
|
|
74
|
+
return {
|
|
75
|
+
homeserver: readEnvLobiString(env, "LOBI_HOMESERVER"),
|
|
76
|
+
userId: readEnvLobiString(env, "LOBI_USER_ID"),
|
|
77
|
+
accessToken: readEnvLobiString(env, "LOBI_ACCESS_TOKEN"),
|
|
78
|
+
password: readEnvLobiString(env, "LOBI_PASSWORD"),
|
|
79
|
+
deviceId: readEnvLobiString(env, "LOBI_DEVICE_ID"),
|
|
80
|
+
deviceName: readEnvLobiString(env, "LOBI_DEVICE_NAME"),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function hasUsableResolvedMatrixAuth(values: {
|
|
85
|
+
homeserver: string;
|
|
86
|
+
userId: string;
|
|
87
|
+
accessToken: string;
|
|
88
|
+
}): boolean {
|
|
89
|
+
// Account discovery must keep homeserver+userId shapes because auth can still
|
|
90
|
+
// resolve through cached Matrix credentials even when no fresh token/password
|
|
91
|
+
// is present in config or env.
|
|
92
|
+
return Boolean(values.homeserver && (values.accessToken || values.userId));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function hasFreshResolvedMatrixAuth(values: {
|
|
96
|
+
homeserver: string;
|
|
97
|
+
userId: string;
|
|
98
|
+
accessToken: string;
|
|
99
|
+
password: string;
|
|
100
|
+
}): boolean {
|
|
101
|
+
return Boolean(values.homeserver && (values.accessToken || (values.userId && values.password)));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function resolveEffectiveMatrixAccountSources(params: {
|
|
105
|
+
channel: Record<string, unknown> | null;
|
|
106
|
+
accountId: string;
|
|
107
|
+
env: NodeJS.ProcessEnv;
|
|
108
|
+
}): ReturnType<typeof resolveMatrixAccountStringValues> {
|
|
109
|
+
const normalizedAccountId = normalizeAccountId(params.accountId);
|
|
110
|
+
return resolveMatrixAccountStringValues({
|
|
111
|
+
accountId: normalizedAccountId,
|
|
112
|
+
scopedEnv: resolveScopedLobiEnvStringSources(normalizedAccountId, params.env),
|
|
113
|
+
channel: resolveMatrixChannelStringSources(params.channel),
|
|
114
|
+
globalEnv: resolveGlobalLobiEnvStringSources(params.env),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function hasUsableEffectiveMatrixAccountSource(params: {
|
|
119
|
+
channel: Record<string, unknown> | null;
|
|
120
|
+
accountId: string;
|
|
121
|
+
env: NodeJS.ProcessEnv;
|
|
122
|
+
}): boolean {
|
|
123
|
+
return hasUsableResolvedMatrixAuth(resolveEffectiveMatrixAccountSources(params));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function hasFreshEffectiveMatrixAccountSource(params: {
|
|
127
|
+
channel: Record<string, unknown> | null;
|
|
128
|
+
accountId: string;
|
|
129
|
+
env: NodeJS.ProcessEnv;
|
|
130
|
+
}): boolean {
|
|
131
|
+
return hasFreshResolvedMatrixAuth(resolveEffectiveMatrixAccountSources(params));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function hasConfiguredDefaultMatrixAccountSource(params: {
|
|
135
|
+
channel: Record<string, unknown> | null;
|
|
136
|
+
env: NodeJS.ProcessEnv;
|
|
137
|
+
}): boolean {
|
|
138
|
+
return hasFreshEffectiveMatrixAccountSource({
|
|
139
|
+
channel: params.channel,
|
|
140
|
+
accountId: DEFAULT_ACCOUNT_ID,
|
|
141
|
+
env: params.env,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function resolveMatrixChannelConfig(cfg: OpenClawConfig): Record<string, unknown> | null {
|
|
146
|
+
return isRecord(cfg.channels?.matrix) ? cfg.channels.lobi : null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function findMatrixAccountEntry(
|
|
150
|
+
cfg: OpenClawConfig,
|
|
151
|
+
accountId: string,
|
|
152
|
+
): Record<string, unknown> | null {
|
|
153
|
+
const channel = resolveMatrixChannelConfig(cfg);
|
|
154
|
+
if (!channel) {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const accounts = isRecord(channel.accounts) ? channel.accounts : null;
|
|
159
|
+
if (!accounts) {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const entry = resolveNormalizedAccountEntry(accounts, accountId, normalizeAccountId);
|
|
163
|
+
return isRecord(entry) ? entry : null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function resolveConfiguredMatrixAccountIds(
|
|
167
|
+
cfg: OpenClawConfig,
|
|
168
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
169
|
+
): string[] {
|
|
170
|
+
const channel = resolveMatrixChannelConfig(cfg);
|
|
171
|
+
const configuredAccountIds = listConfiguredAccountIds({
|
|
172
|
+
accounts: channel && isRecord(channel.accounts) ? channel.accounts : undefined,
|
|
173
|
+
normalizeAccountId,
|
|
174
|
+
});
|
|
175
|
+
if (hasConfiguredDefaultMatrixAccountSource({ channel, env })) {
|
|
176
|
+
configuredAccountIds.push(DEFAULT_ACCOUNT_ID);
|
|
177
|
+
}
|
|
178
|
+
const readyEnvAccountIds = listMatrixEnvAccountIds(env).filter((accountId) =>
|
|
179
|
+
normalizeAccountId(accountId) === DEFAULT_ACCOUNT_ID
|
|
180
|
+
? hasConfiguredDefaultMatrixAccountSource({ channel, env })
|
|
181
|
+
: hasUsableEffectiveMatrixAccountSource({ channel, accountId, env }),
|
|
182
|
+
);
|
|
183
|
+
return listCombinedAccountIds({
|
|
184
|
+
configuredAccountIds,
|
|
185
|
+
additionalAccountIds: readyEnvAccountIds,
|
|
186
|
+
fallbackAccountIdWhenEmpty: channel ? DEFAULT_ACCOUNT_ID : undefined,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function resolveMatrixDefaultOrOnlyAccountId(
|
|
191
|
+
cfg: OpenClawConfig,
|
|
192
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
193
|
+
): string {
|
|
194
|
+
const channel = resolveMatrixChannelConfig(cfg);
|
|
195
|
+
if (!channel) {
|
|
196
|
+
return DEFAULT_ACCOUNT_ID;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const configuredDefault = normalizeOptionalAccountId(
|
|
200
|
+
typeof channel.defaultAccount === "string" ? channel.defaultAccount : undefined,
|
|
201
|
+
);
|
|
202
|
+
const configuredAccountIds = resolveConfiguredMatrixAccountIds(cfg, env);
|
|
203
|
+
return resolveListedDefaultAccountId({
|
|
204
|
+
accountIds: configuredAccountIds,
|
|
205
|
+
configuredDefaultAccountId: configuredDefault,
|
|
206
|
+
ambiguousFallbackAccountId: DEFAULT_ACCOUNT_ID,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function requiresExplicitMatrixDefaultAccount(
|
|
211
|
+
cfg: OpenClawConfig,
|
|
212
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
213
|
+
): boolean {
|
|
214
|
+
const channel = resolveMatrixChannelConfig(cfg);
|
|
215
|
+
if (!channel) {
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
const configuredAccountIds = resolveConfiguredMatrixAccountIds(cfg, env);
|
|
219
|
+
if (configuredAccountIds.length <= 1) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const configuredDefault = normalizeOptionalAccountId(
|
|
223
|
+
typeof channel.defaultAccount === "string" ? channel.defaultAccount : undefined,
|
|
224
|
+
);
|
|
225
|
+
return !(configuredDefault && configuredAccountIds.includes(configuredDefault));
|
|
226
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type { ChannelMessageActionContext } from "../runtime-api.js";
|
|
3
|
+
import type { CoreConfig } from "./types.js";
|
|
4
|
+
|
|
5
|
+
const mocks = vi.hoisted(() => ({
|
|
6
|
+
handleMatrixAction: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("./tool-actions.js", () => ({
|
|
10
|
+
handleMatrixAction: mocks.handleMatrixAction,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
const { matrixMessageActions } = await import("./actions.js");
|
|
14
|
+
|
|
15
|
+
const profileAction = "set-profile" as ChannelMessageActionContext["action"];
|
|
16
|
+
|
|
17
|
+
function createContext(
|
|
18
|
+
overrides: Partial<ChannelMessageActionContext>,
|
|
19
|
+
): ChannelMessageActionContext {
|
|
20
|
+
return {
|
|
21
|
+
channel: "matrix",
|
|
22
|
+
action: "send",
|
|
23
|
+
cfg: {
|
|
24
|
+
channels: {
|
|
25
|
+
matrix: {
|
|
26
|
+
enabled: true,
|
|
27
|
+
homeserver: "https://matrix.example.org",
|
|
28
|
+
userId: "@bot:example.org",
|
|
29
|
+
accessToken: "token",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
} as CoreConfig,
|
|
33
|
+
params: {},
|
|
34
|
+
...overrides,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("matrixMessageActions account propagation", () => {
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
mocks.handleMatrixAction.mockReset().mockResolvedValue({
|
|
41
|
+
ok: true,
|
|
42
|
+
output: "",
|
|
43
|
+
details: { ok: true },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("forwards accountId for send actions", async () => {
|
|
48
|
+
await matrixMessageActions.handleAction?.(
|
|
49
|
+
createContext({
|
|
50
|
+
action: "send",
|
|
51
|
+
accountId: "ops",
|
|
52
|
+
params: {
|
|
53
|
+
to: "room:!room:example",
|
|
54
|
+
message: "hello",
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
60
|
+
expect.objectContaining({
|
|
61
|
+
action: "sendMessage",
|
|
62
|
+
accountId: "ops",
|
|
63
|
+
}),
|
|
64
|
+
expect.any(Object),
|
|
65
|
+
{ mediaLocalRoots: undefined },
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("forwards accountId for permissions actions", async () => {
|
|
70
|
+
await matrixMessageActions.handleAction?.(
|
|
71
|
+
createContext({
|
|
72
|
+
action: "permissions",
|
|
73
|
+
accountId: "ops",
|
|
74
|
+
params: {
|
|
75
|
+
operation: "verification-list",
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
81
|
+
expect.objectContaining({
|
|
82
|
+
action: "verificationList",
|
|
83
|
+
accountId: "ops",
|
|
84
|
+
}),
|
|
85
|
+
expect.any(Object),
|
|
86
|
+
{ mediaLocalRoots: undefined },
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("forwards accountId for self-profile updates", async () => {
|
|
91
|
+
await matrixMessageActions.handleAction?.(
|
|
92
|
+
createContext({
|
|
93
|
+
action: profileAction,
|
|
94
|
+
senderIsOwner: true,
|
|
95
|
+
accountId: "ops",
|
|
96
|
+
params: {
|
|
97
|
+
displayName: "Ops Bot",
|
|
98
|
+
avatarUrl: "mxc://example/avatar",
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
104
|
+
expect.objectContaining({
|
|
105
|
+
action: "setProfile",
|
|
106
|
+
accountId: "ops",
|
|
107
|
+
displayName: "Ops Bot",
|
|
108
|
+
avatarUrl: "mxc://example/avatar",
|
|
109
|
+
}),
|
|
110
|
+
expect.any(Object),
|
|
111
|
+
{ mediaLocalRoots: undefined },
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("rejects self-profile updates for non-owner callers", async () => {
|
|
116
|
+
await expect(
|
|
117
|
+
matrixMessageActions.handleAction?.(
|
|
118
|
+
createContext({
|
|
119
|
+
action: profileAction,
|
|
120
|
+
senderIsOwner: false,
|
|
121
|
+
accountId: "ops",
|
|
122
|
+
params: {
|
|
123
|
+
displayName: "Ops Bot",
|
|
124
|
+
},
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
).rejects.toMatchObject({
|
|
128
|
+
name: "ToolAuthorizationError",
|
|
129
|
+
message: "Matrix profile updates require owner access.",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
expect(mocks.handleMatrixAction).not.toHaveBeenCalled();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("rejects self-profile updates when owner status is unknown", async () => {
|
|
136
|
+
await expect(
|
|
137
|
+
matrixMessageActions.handleAction?.(
|
|
138
|
+
createContext({
|
|
139
|
+
action: profileAction,
|
|
140
|
+
accountId: "ops",
|
|
141
|
+
params: {
|
|
142
|
+
displayName: "Ops Bot",
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
),
|
|
146
|
+
).rejects.toMatchObject({
|
|
147
|
+
name: "ToolAuthorizationError",
|
|
148
|
+
message: "Matrix profile updates require owner access.",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(mocks.handleMatrixAction).not.toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("forwards local avatar paths for self-profile updates", async () => {
|
|
155
|
+
await matrixMessageActions.handleAction?.(
|
|
156
|
+
createContext({
|
|
157
|
+
action: profileAction,
|
|
158
|
+
senderIsOwner: true,
|
|
159
|
+
accountId: "ops",
|
|
160
|
+
params: {
|
|
161
|
+
path: "/tmp/avatar.jpg",
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
167
|
+
expect.objectContaining({
|
|
168
|
+
action: "setProfile",
|
|
169
|
+
accountId: "ops",
|
|
170
|
+
avatarPath: "/tmp/avatar.jpg",
|
|
171
|
+
}),
|
|
172
|
+
expect.any(Object),
|
|
173
|
+
{ mediaLocalRoots: undefined },
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("forwards mediaLocalRoots for media sends", async () => {
|
|
178
|
+
await matrixMessageActions.handleAction?.(
|
|
179
|
+
createContext({
|
|
180
|
+
action: "send",
|
|
181
|
+
accountId: "ops",
|
|
182
|
+
mediaLocalRoots: ["/tmp/openclaw-matrix-test"],
|
|
183
|
+
params: {
|
|
184
|
+
to: "room:!room:example",
|
|
185
|
+
message: "hello",
|
|
186
|
+
media: "file:///tmp/photo.png",
|
|
187
|
+
},
|
|
188
|
+
}),
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
192
|
+
expect.objectContaining({
|
|
193
|
+
action: "sendMessage",
|
|
194
|
+
accountId: "ops",
|
|
195
|
+
mediaUrl: "file:///tmp/photo.png",
|
|
196
|
+
}),
|
|
197
|
+
expect.any(Object),
|
|
198
|
+
{ mediaLocalRoots: ["/tmp/openclaw-matrix-test"] },
|
|
199
|
+
);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("allows media-only sends without requiring a message body", async () => {
|
|
203
|
+
await matrixMessageActions.handleAction?.(
|
|
204
|
+
createContext({
|
|
205
|
+
action: "send",
|
|
206
|
+
accountId: "ops",
|
|
207
|
+
params: {
|
|
208
|
+
to: "room:!room:example",
|
|
209
|
+
media: "file:///tmp/photo.png",
|
|
210
|
+
},
|
|
211
|
+
}),
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
215
|
+
expect.objectContaining({
|
|
216
|
+
action: "sendMessage",
|
|
217
|
+
accountId: "ops",
|
|
218
|
+
content: undefined,
|
|
219
|
+
mediaUrl: "file:///tmp/photo.png",
|
|
220
|
+
}),
|
|
221
|
+
expect.any(Object),
|
|
222
|
+
{ mediaLocalRoots: undefined },
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("accepts shared media aliases and forwards voice-send intent", async () => {
|
|
227
|
+
await matrixMessageActions.handleAction?.(
|
|
228
|
+
createContext({
|
|
229
|
+
action: "send",
|
|
230
|
+
accountId: "ops",
|
|
231
|
+
params: {
|
|
232
|
+
to: "room:!room:example",
|
|
233
|
+
filePath: "/tmp/clip.mp3",
|
|
234
|
+
asVoice: true,
|
|
235
|
+
},
|
|
236
|
+
}),
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
expect(mocks.handleMatrixAction).toHaveBeenCalledWith(
|
|
240
|
+
expect.objectContaining({
|
|
241
|
+
action: "sendMessage",
|
|
242
|
+
accountId: "ops",
|
|
243
|
+
content: undefined,
|
|
244
|
+
mediaUrl: "/tmp/clip.mp3",
|
|
245
|
+
audioAsVoice: true,
|
|
246
|
+
}),
|
|
247
|
+
expect.any(Object),
|
|
248
|
+
{ mediaLocalRoots: undefined },
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
});
|