@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,227 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { withTempHome } from "../../../test/helpers/temp-home.js";
|
|
5
|
+
|
|
6
|
+
const legacyCryptoInspectorAvailability = vi.hoisted(() => ({
|
|
7
|
+
available: true,
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock("./legacy-crypto-inspector-availability.js", () => ({
|
|
11
|
+
isMatrixLegacyCryptoInspectorAvailable: () => legacyCryptoInspectorAvailability.available,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
import { runMatrixStartupMaintenance } from "./startup-maintenance.js";
|
|
15
|
+
import { resolveMatrixAccountStorageRoot } from "./storage-paths.js";
|
|
16
|
+
|
|
17
|
+
async function seedLegacyMatrixState(home: string) {
|
|
18
|
+
const stateDir = path.join(home, ".openclaw");
|
|
19
|
+
await fs.mkdir(path.join(stateDir, "matrix"), { recursive: true });
|
|
20
|
+
await fs.writeFile(path.join(stateDir, "matrix", "bot-storage.json"), '{"legacy":true}');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function makeMatrixStartupConfig(includeCredentials = true) {
|
|
24
|
+
return {
|
|
25
|
+
channels: {
|
|
26
|
+
matrix: includeCredentials
|
|
27
|
+
? {
|
|
28
|
+
homeserver: "https://matrix.example.org",
|
|
29
|
+
userId: "@bot:example.org",
|
|
30
|
+
accessToken: "tok-123",
|
|
31
|
+
}
|
|
32
|
+
: {
|
|
33
|
+
homeserver: "https://matrix.example.org",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
} as const;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function seedLegacyMatrixCrypto(home: string) {
|
|
40
|
+
const stateDir = path.join(home, ".openclaw");
|
|
41
|
+
const { rootDir } = resolveMatrixAccountStorageRoot({
|
|
42
|
+
stateDir,
|
|
43
|
+
homeserver: "https://matrix.example.org",
|
|
44
|
+
userId: "@bot:example.org",
|
|
45
|
+
accessToken: "tok-123",
|
|
46
|
+
});
|
|
47
|
+
await fs.mkdir(path.join(rootDir, "crypto"), { recursive: true });
|
|
48
|
+
await fs.writeFile(
|
|
49
|
+
path.join(rootDir, "crypto", "bot-sdk.json"),
|
|
50
|
+
JSON.stringify({ deviceId: "DEVICE123" }),
|
|
51
|
+
"utf8",
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function createSuccessfulMatrixMigrationDeps() {
|
|
56
|
+
return {
|
|
57
|
+
maybeCreateMatrixMigrationSnapshot: vi.fn(async () => ({
|
|
58
|
+
created: true,
|
|
59
|
+
archivePath: "/tmp/snapshot.tar.gz",
|
|
60
|
+
markerPath: "/tmp/migration-snapshot.json",
|
|
61
|
+
})),
|
|
62
|
+
autoMigrateLegacyMatrixState: vi.fn(async () => ({
|
|
63
|
+
migrated: true,
|
|
64
|
+
changes: [],
|
|
65
|
+
warnings: [],
|
|
66
|
+
})),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
describe("runMatrixStartupMaintenance", () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
legacyCryptoInspectorAvailability.available = true;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("creates a snapshot before actionable startup migration", async () => {
|
|
76
|
+
await withTempHome(async (home) => {
|
|
77
|
+
await seedLegacyMatrixState(home);
|
|
78
|
+
const deps = createSuccessfulMatrixMigrationDeps();
|
|
79
|
+
const autoPrepareLegacyMatrixCryptoMock = vi.fn(async () => ({
|
|
80
|
+
migrated: false,
|
|
81
|
+
changes: [],
|
|
82
|
+
warnings: [],
|
|
83
|
+
}));
|
|
84
|
+
|
|
85
|
+
await runMatrixStartupMaintenance({
|
|
86
|
+
cfg: makeMatrixStartupConfig(),
|
|
87
|
+
env: process.env,
|
|
88
|
+
deps: {
|
|
89
|
+
maybeCreateMatrixMigrationSnapshot: deps.maybeCreateMatrixMigrationSnapshot,
|
|
90
|
+
autoMigrateLegacyMatrixState: deps.autoMigrateLegacyMatrixState,
|
|
91
|
+
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock,
|
|
92
|
+
},
|
|
93
|
+
log: {},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(deps.maybeCreateMatrixMigrationSnapshot).toHaveBeenCalledWith(
|
|
97
|
+
expect.objectContaining({ trigger: "gateway-startup" }),
|
|
98
|
+
);
|
|
99
|
+
expect(deps.autoMigrateLegacyMatrixState).toHaveBeenCalledOnce();
|
|
100
|
+
expect(autoPrepareLegacyMatrixCryptoMock).toHaveBeenCalledOnce();
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("skips snapshot creation when startup only has warning-only migration state", async () => {
|
|
105
|
+
await withTempHome(async (home) => {
|
|
106
|
+
await seedLegacyMatrixState(home);
|
|
107
|
+
const maybeCreateMatrixMigrationSnapshotMock = vi.fn();
|
|
108
|
+
const autoMigrateLegacyMatrixStateMock = vi.fn();
|
|
109
|
+
const autoPrepareLegacyMatrixCryptoMock = vi.fn();
|
|
110
|
+
const info = vi.fn();
|
|
111
|
+
const warn = vi.fn();
|
|
112
|
+
|
|
113
|
+
await runMatrixStartupMaintenance({
|
|
114
|
+
cfg: makeMatrixStartupConfig(false),
|
|
115
|
+
env: process.env,
|
|
116
|
+
deps: {
|
|
117
|
+
maybeCreateMatrixMigrationSnapshot: maybeCreateMatrixMigrationSnapshotMock as never,
|
|
118
|
+
autoMigrateLegacyMatrixState: autoMigrateLegacyMatrixStateMock as never,
|
|
119
|
+
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock as never,
|
|
120
|
+
},
|
|
121
|
+
log: { info, warn },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(maybeCreateMatrixMigrationSnapshotMock).not.toHaveBeenCalled();
|
|
125
|
+
expect(autoMigrateLegacyMatrixStateMock).not.toHaveBeenCalled();
|
|
126
|
+
expect(autoPrepareLegacyMatrixCryptoMock).not.toHaveBeenCalled();
|
|
127
|
+
expect(info).toHaveBeenCalledWith(
|
|
128
|
+
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
|
129
|
+
);
|
|
130
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining("could not be resolved yet"));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("logs the concrete unavailable-inspector warning when startup migration is warning-only", async () => {
|
|
135
|
+
legacyCryptoInspectorAvailability.available = false;
|
|
136
|
+
|
|
137
|
+
await withTempHome(async (home) => {
|
|
138
|
+
await seedLegacyMatrixCrypto(home);
|
|
139
|
+
const maybeCreateMatrixMigrationSnapshotMock = vi.fn();
|
|
140
|
+
const autoMigrateLegacyMatrixStateMock = vi.fn();
|
|
141
|
+
const autoPrepareLegacyMatrixCryptoMock = vi.fn();
|
|
142
|
+
const info = vi.fn();
|
|
143
|
+
const warn = vi.fn();
|
|
144
|
+
|
|
145
|
+
await runMatrixStartupMaintenance({
|
|
146
|
+
cfg: makeMatrixStartupConfig(),
|
|
147
|
+
env: process.env,
|
|
148
|
+
deps: {
|
|
149
|
+
maybeCreateMatrixMigrationSnapshot: maybeCreateMatrixMigrationSnapshotMock as never,
|
|
150
|
+
autoMigrateLegacyMatrixState: autoMigrateLegacyMatrixStateMock as never,
|
|
151
|
+
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock as never,
|
|
152
|
+
},
|
|
153
|
+
log: { info, warn },
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
expect(maybeCreateMatrixMigrationSnapshotMock).not.toHaveBeenCalled();
|
|
157
|
+
expect(autoMigrateLegacyMatrixStateMock).not.toHaveBeenCalled();
|
|
158
|
+
expect(autoPrepareLegacyMatrixCryptoMock).not.toHaveBeenCalled();
|
|
159
|
+
expect(info).toHaveBeenCalledWith(
|
|
160
|
+
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
|
161
|
+
);
|
|
162
|
+
expect(warn).toHaveBeenCalledWith(
|
|
163
|
+
"matrix: legacy encrypted-state warnings:\n- Legacy Matrix encrypted state was detected, but the Matrix crypto inspector is unavailable.",
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("skips startup migration when snapshot creation fails", async () => {
|
|
169
|
+
await withTempHome(async (home) => {
|
|
170
|
+
await seedLegacyMatrixState(home);
|
|
171
|
+
const maybeCreateMatrixMigrationSnapshotMock = vi.fn(async () => {
|
|
172
|
+
throw new Error("backup failed");
|
|
173
|
+
});
|
|
174
|
+
const autoMigrateLegacyMatrixStateMock = vi.fn();
|
|
175
|
+
const autoPrepareLegacyMatrixCryptoMock = vi.fn();
|
|
176
|
+
const warn = vi.fn();
|
|
177
|
+
|
|
178
|
+
await runMatrixStartupMaintenance({
|
|
179
|
+
cfg: makeMatrixStartupConfig(),
|
|
180
|
+
env: process.env,
|
|
181
|
+
deps: {
|
|
182
|
+
maybeCreateMatrixMigrationSnapshot: maybeCreateMatrixMigrationSnapshotMock,
|
|
183
|
+
autoMigrateLegacyMatrixState: autoMigrateLegacyMatrixStateMock as never,
|
|
184
|
+
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock as never,
|
|
185
|
+
},
|
|
186
|
+
log: { warn },
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(autoMigrateLegacyMatrixStateMock).not.toHaveBeenCalled();
|
|
190
|
+
expect(autoPrepareLegacyMatrixCryptoMock).not.toHaveBeenCalled();
|
|
191
|
+
expect(warn).toHaveBeenCalledWith(
|
|
192
|
+
"gateway: failed creating a Matrix migration snapshot; skipping Matrix migration for now: Error: backup failed",
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("downgrades migration step failures to warnings so startup can continue", async () => {
|
|
198
|
+
await withTempHome(async (home) => {
|
|
199
|
+
await seedLegacyMatrixState(home);
|
|
200
|
+
const deps = createSuccessfulMatrixMigrationDeps();
|
|
201
|
+
const autoPrepareLegacyMatrixCryptoMock = vi.fn(async () => {
|
|
202
|
+
throw new Error("disk full");
|
|
203
|
+
});
|
|
204
|
+
const warn = vi.fn();
|
|
205
|
+
|
|
206
|
+
await expect(
|
|
207
|
+
runMatrixStartupMaintenance({
|
|
208
|
+
cfg: makeMatrixStartupConfig(),
|
|
209
|
+
env: process.env,
|
|
210
|
+
deps: {
|
|
211
|
+
maybeCreateMatrixMigrationSnapshot: deps.maybeCreateMatrixMigrationSnapshot,
|
|
212
|
+
autoMigrateLegacyMatrixState: deps.autoMigrateLegacyMatrixState,
|
|
213
|
+
autoPrepareLegacyMatrixCrypto: autoPrepareLegacyMatrixCryptoMock,
|
|
214
|
+
},
|
|
215
|
+
log: { warn },
|
|
216
|
+
}),
|
|
217
|
+
).resolves.toBeUndefined();
|
|
218
|
+
|
|
219
|
+
expect(deps.maybeCreateMatrixMigrationSnapshot).toHaveBeenCalledOnce();
|
|
220
|
+
expect(deps.autoMigrateLegacyMatrixState).toHaveBeenCalledOnce();
|
|
221
|
+
expect(autoPrepareLegacyMatrixCryptoMock).toHaveBeenCalledOnce();
|
|
222
|
+
expect(warn).toHaveBeenCalledWith(
|
|
223
|
+
"gateway: legacy Matrix encrypted-state preparation failed during Matrix migration; continuing startup: Error: disk full",
|
|
224
|
+
);
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
|
2
|
+
import {
|
|
3
|
+
autoMigrateLegacyMatrixState,
|
|
4
|
+
autoPrepareLegacyMatrixCrypto,
|
|
5
|
+
maybeCreateMatrixMigrationSnapshot,
|
|
6
|
+
resolveMatrixMigrationStatus,
|
|
7
|
+
type MatrixMigrationStatus,
|
|
8
|
+
} from "./matrix-migration.runtime.js";
|
|
9
|
+
|
|
10
|
+
type MatrixStartupLogger = {
|
|
11
|
+
info?: (message: string) => void;
|
|
12
|
+
warn?: (message: string) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function logWarningOnlyMatrixMigrationReasons(params: {
|
|
16
|
+
status: MatrixMigrationStatus;
|
|
17
|
+
log: MatrixStartupLogger;
|
|
18
|
+
}): void {
|
|
19
|
+
if (params.status.legacyState && "warning" in params.status.legacyState) {
|
|
20
|
+
params.log.warn?.(`matrix: ${params.status.legacyState.warning}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (params.status.legacyCrypto.warnings.length > 0) {
|
|
24
|
+
params.log.warn?.(
|
|
25
|
+
`matrix: legacy encrypted-state warnings:\n${params.status.legacyCrypto.warnings.map((entry) => `- ${entry}`).join("\n")}`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function runBestEffortMatrixMigrationStep(params: {
|
|
31
|
+
label: string;
|
|
32
|
+
log: MatrixStartupLogger;
|
|
33
|
+
logPrefix?: string;
|
|
34
|
+
run: () => Promise<unknown>;
|
|
35
|
+
}): Promise<void> {
|
|
36
|
+
try {
|
|
37
|
+
await params.run();
|
|
38
|
+
} catch (err) {
|
|
39
|
+
params.log.warn?.(
|
|
40
|
+
`${params.logPrefix?.trim() || "gateway"}: ${params.label} failed during Matrix migration; continuing startup: ${String(err)}`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function runMatrixStartupMaintenance(params: {
|
|
46
|
+
cfg: OpenClawConfig;
|
|
47
|
+
env?: NodeJS.ProcessEnv;
|
|
48
|
+
log: MatrixStartupLogger;
|
|
49
|
+
trigger?: string;
|
|
50
|
+
logPrefix?: string;
|
|
51
|
+
deps?: {
|
|
52
|
+
maybeCreateMatrixMigrationSnapshot?: typeof maybeCreateMatrixMigrationSnapshot;
|
|
53
|
+
autoMigrateLegacyMatrixState?: typeof autoMigrateLegacyMatrixState;
|
|
54
|
+
autoPrepareLegacyMatrixCrypto?: typeof autoPrepareLegacyMatrixCrypto;
|
|
55
|
+
};
|
|
56
|
+
}): Promise<void> {
|
|
57
|
+
const env = params.env ?? process.env;
|
|
58
|
+
const createSnapshot =
|
|
59
|
+
params.deps?.maybeCreateMatrixMigrationSnapshot ?? maybeCreateMatrixMigrationSnapshot;
|
|
60
|
+
const migrateLegacyState =
|
|
61
|
+
params.deps?.autoMigrateLegacyMatrixState ?? autoMigrateLegacyMatrixState;
|
|
62
|
+
const prepareLegacyCrypto =
|
|
63
|
+
params.deps?.autoPrepareLegacyMatrixCrypto ?? autoPrepareLegacyMatrixCrypto;
|
|
64
|
+
const trigger = params.trigger?.trim() || "gateway-startup";
|
|
65
|
+
const logPrefix = params.logPrefix?.trim() || "gateway";
|
|
66
|
+
const migrationStatus = resolveMatrixMigrationStatus({ cfg: params.cfg, env });
|
|
67
|
+
|
|
68
|
+
if (!migrationStatus.pending) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!migrationStatus.actionable) {
|
|
72
|
+
params.log.info?.(
|
|
73
|
+
"matrix: migration remains in a warning-only state; no pre-migration snapshot was needed yet",
|
|
74
|
+
);
|
|
75
|
+
logWarningOnlyMatrixMigrationReasons({ status: migrationStatus, log: params.log });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await createSnapshot({
|
|
81
|
+
trigger,
|
|
82
|
+
env,
|
|
83
|
+
log: params.log,
|
|
84
|
+
});
|
|
85
|
+
} catch (err) {
|
|
86
|
+
params.log.warn?.(
|
|
87
|
+
`${logPrefix}: failed creating a Matrix migration snapshot; skipping Matrix migration for now: ${String(err)}`,
|
|
88
|
+
);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
await runBestEffortMatrixMigrationStep({
|
|
93
|
+
label: "legacy Matrix state migration",
|
|
94
|
+
log: params.log,
|
|
95
|
+
logPrefix,
|
|
96
|
+
run: () =>
|
|
97
|
+
migrateLegacyState({
|
|
98
|
+
cfg: params.cfg,
|
|
99
|
+
env,
|
|
100
|
+
log: params.log,
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
await runBestEffortMatrixMigrationStep({
|
|
104
|
+
label: "legacy Matrix encrypted-state preparation",
|
|
105
|
+
log: params.log,
|
|
106
|
+
logPrefix,
|
|
107
|
+
run: () =>
|
|
108
|
+
prepareLegacyCrypto({
|
|
109
|
+
cfg: params.cfg,
|
|
110
|
+
env,
|
|
111
|
+
log: params.log,
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
4
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
|
5
|
+
|
|
6
|
+
export function sanitizeMatrixPathSegment(value: string): string {
|
|
7
|
+
const cleaned = normalizeLowercaseStringOrEmpty(value)
|
|
8
|
+
.replace(/[^a-z0-9._-]+/g, "_")
|
|
9
|
+
.replace(/^_+|_+$/g, "");
|
|
10
|
+
return cleaned || "unknown";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function resolveMatrixHomeserverKey(homeserver: string): string {
|
|
14
|
+
try {
|
|
15
|
+
const url = new URL(homeserver);
|
|
16
|
+
if (url.host) {
|
|
17
|
+
return sanitizeMatrixPathSegment(url.host);
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
// fall through
|
|
21
|
+
}
|
|
22
|
+
return sanitizeMatrixPathSegment(homeserver);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function hashMatrixAccessToken(accessToken: string): string {
|
|
26
|
+
return crypto.createHash("sha256").update(accessToken).digest("hex").slice(0, 16);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resolveMatrixCredentialsFilename(accountId?: string | null): string {
|
|
30
|
+
const normalized = normalizeAccountId(accountId);
|
|
31
|
+
return normalized === DEFAULT_ACCOUNT_ID ? "credentials.json" : `credentials-${normalized}.json`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function resolveMatrixCredentialsDir(stateDir: string): string {
|
|
35
|
+
return path.join(stateDir, "credentials", "lobi");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function resolveMatrixCredentialsPath(params: {
|
|
39
|
+
stateDir: string;
|
|
40
|
+
accountId?: string | null;
|
|
41
|
+
}): string {
|
|
42
|
+
return path.join(
|
|
43
|
+
resolveMatrixCredentialsDir(params.stateDir),
|
|
44
|
+
resolveMatrixCredentialsFilename(params.accountId),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function resolveMatrixLegacyFlatStoreRoot(stateDir: string): string {
|
|
49
|
+
return path.join(stateDir, "lobi");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function resolveMatrixLegacyFlatStoragePaths(stateDir: string): {
|
|
53
|
+
rootDir: string;
|
|
54
|
+
storagePath: string;
|
|
55
|
+
cryptoPath: string;
|
|
56
|
+
} {
|
|
57
|
+
const rootDir = resolveMatrixLegacyFlatStoreRoot(stateDir);
|
|
58
|
+
return {
|
|
59
|
+
rootDir,
|
|
60
|
+
storagePath: path.join(rootDir, "bot-storage.json"),
|
|
61
|
+
cryptoPath: path.join(rootDir, "crypto"),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function resolveMatrixAccountStorageRoot(params: {
|
|
66
|
+
stateDir: string;
|
|
67
|
+
homeserver: string;
|
|
68
|
+
userId: string;
|
|
69
|
+
accessToken: string;
|
|
70
|
+
accountId?: string | null;
|
|
71
|
+
}): {
|
|
72
|
+
rootDir: string;
|
|
73
|
+
accountKey: string;
|
|
74
|
+
tokenHash: string;
|
|
75
|
+
} {
|
|
76
|
+
const accountKey = sanitizeMatrixPathSegment(params.accountId ?? DEFAULT_ACCOUNT_ID);
|
|
77
|
+
const userKey = sanitizeMatrixPathSegment(params.userId);
|
|
78
|
+
const serverKey = resolveMatrixHomeserverKey(params.homeserver);
|
|
79
|
+
const tokenHash = hashMatrixAccessToken(params.accessToken);
|
|
80
|
+
return {
|
|
81
|
+
rootDir: path.join(
|
|
82
|
+
params.stateDir,
|
|
83
|
+
"lobi",
|
|
84
|
+
"accounts",
|
|
85
|
+
accountKey,
|
|
86
|
+
`${serverKey}__${userKey}`,
|
|
87
|
+
tokenHash,
|
|
88
|
+
),
|
|
89
|
+
accountKey,
|
|
90
|
+
tokenHash,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export const MATRIX_TEST_HOMESERVER = "https://matrix.example.org";
|
|
5
|
+
export const MATRIX_DEFAULT_USER_ID = "@bot:example.org";
|
|
6
|
+
export const MATRIX_DEFAULT_ACCESS_TOKEN = "tok-123";
|
|
7
|
+
export const MATRIX_DEFAULT_DEVICE_ID = "DEVICE123";
|
|
8
|
+
export const MATRIX_OPS_ACCOUNT_ID = "ops";
|
|
9
|
+
export const MATRIX_OPS_USER_ID = "@ops-bot:example.org";
|
|
10
|
+
export const LOBI_OPS_ACCESS_TOKEN = "tok-ops";
|
|
11
|
+
export const LOBI_OPS_DEVICE_ID = "DEVICEOPS";
|
|
12
|
+
|
|
13
|
+
export function writeFile(filePath: string, value: string) {
|
|
14
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
15
|
+
fs.writeFileSync(filePath, value, "utf8");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function writeMatrixCredentials(
|
|
19
|
+
stateDir: string,
|
|
20
|
+
params?: {
|
|
21
|
+
accountId?: string;
|
|
22
|
+
homeserver?: string;
|
|
23
|
+
userId?: string;
|
|
24
|
+
accessToken?: string;
|
|
25
|
+
deviceId?: string;
|
|
26
|
+
},
|
|
27
|
+
) {
|
|
28
|
+
const accountId = params?.accountId ?? MATRIX_OPS_ACCOUNT_ID;
|
|
29
|
+
writeFile(
|
|
30
|
+
path.join(stateDir, "credentials", "matrix", `credentials-${accountId}.json`),
|
|
31
|
+
JSON.stringify(
|
|
32
|
+
{
|
|
33
|
+
homeserver: params?.homeserver ?? MATRIX_TEST_HOMESERVER,
|
|
34
|
+
userId: params?.userId ?? MATRIX_OPS_USER_ID,
|
|
35
|
+
accessToken: params?.accessToken ?? LOBI_OPS_ACCESS_TOKEN,
|
|
36
|
+
deviceId: params?.deviceId ?? LOBI_OPS_DEVICE_ID,
|
|
37
|
+
},
|
|
38
|
+
null,
|
|
39
|
+
2,
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Mock } from "vitest";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
|
|
4
|
+
type MatrixBotSdkMockParams = {
|
|
5
|
+
matrixClient?: unknown;
|
|
6
|
+
simpleFsStorageProvider?: unknown;
|
|
7
|
+
rustSdkCryptoStorageProvider?: unknown;
|
|
8
|
+
includeVerboseLogService?: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type MatrixBotSdkMock = {
|
|
12
|
+
ConsoleLogger: new () => {
|
|
13
|
+
trace: Mock<() => void>;
|
|
14
|
+
debug: Mock<() => void>;
|
|
15
|
+
info: Mock<() => void>;
|
|
16
|
+
warn: Mock<() => void>;
|
|
17
|
+
error: Mock<() => void>;
|
|
18
|
+
};
|
|
19
|
+
MatrixClient: unknown;
|
|
20
|
+
LogService: {
|
|
21
|
+
setLogger: Mock<() => void>;
|
|
22
|
+
warn?: Mock<() => void>;
|
|
23
|
+
info?: Mock<() => void>;
|
|
24
|
+
debug?: Mock<() => void>;
|
|
25
|
+
};
|
|
26
|
+
SimpleFsStorageProvider: unknown;
|
|
27
|
+
RustSdkCryptoStorageProvider: unknown;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function createMatrixBotSdkMock(params: MatrixBotSdkMockParams = {}): MatrixBotSdkMock {
|
|
31
|
+
return {
|
|
32
|
+
ConsoleLogger: class {
|
|
33
|
+
trace = vi.fn();
|
|
34
|
+
debug = vi.fn();
|
|
35
|
+
info = vi.fn();
|
|
36
|
+
warn = vi.fn();
|
|
37
|
+
error = vi.fn();
|
|
38
|
+
},
|
|
39
|
+
MatrixClient: params.matrixClient ?? function MatrixClient() {},
|
|
40
|
+
LogService: {
|
|
41
|
+
setLogger: vi.fn(),
|
|
42
|
+
...(params.includeVerboseLogService
|
|
43
|
+
? {
|
|
44
|
+
warn: vi.fn(),
|
|
45
|
+
info: vi.fn(),
|
|
46
|
+
debug: vi.fn(),
|
|
47
|
+
}
|
|
48
|
+
: {}),
|
|
49
|
+
},
|
|
50
|
+
SimpleFsStorageProvider:
|
|
51
|
+
params.simpleFsStorageProvider ?? function SimpleFsStorageProvider() {},
|
|
52
|
+
RustSdkCryptoStorageProvider:
|
|
53
|
+
params.rustSdkCryptoStorageProvider ?? function RustSdkCryptoStorageProvider() {},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
implicitMentionKindWhen,
|
|
3
|
+
resolveInboundMentionDecision,
|
|
4
|
+
} from "openclaw/plugin-sdk/channel-inbound";
|
|
5
|
+
import { vi } from "vitest";
|
|
6
|
+
import type { PluginRuntime } from "./runtime-api.js";
|
|
7
|
+
import { setMatrixRuntime } from "./runtime.js";
|
|
8
|
+
|
|
9
|
+
type MatrixTestRuntimeOptions = {
|
|
10
|
+
cfg?: Record<string, unknown>;
|
|
11
|
+
logging?: Partial<PluginRuntime["logging"]>;
|
|
12
|
+
channel?: Partial<PluginRuntime["channel"]>;
|
|
13
|
+
stateDir?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function installMatrixTestRuntime(options: MatrixTestRuntimeOptions = {}): void {
|
|
17
|
+
const defaultStateDirResolver: NonNullable<PluginRuntime["state"]>["resolveStateDir"] = (
|
|
18
|
+
_env,
|
|
19
|
+
homeDir,
|
|
20
|
+
) => options.stateDir ?? (homeDir ?? (() => "/tmp"))();
|
|
21
|
+
const logging: PluginRuntime["logging"] | undefined = options.logging
|
|
22
|
+
? ({
|
|
23
|
+
shouldLogVerbose: () => false,
|
|
24
|
+
getChildLogger: () => ({
|
|
25
|
+
info: () => {},
|
|
26
|
+
warn: () => {},
|
|
27
|
+
error: () => {},
|
|
28
|
+
}),
|
|
29
|
+
...options.logging,
|
|
30
|
+
} as PluginRuntime["logging"])
|
|
31
|
+
: undefined;
|
|
32
|
+
|
|
33
|
+
setMatrixRuntime({
|
|
34
|
+
config: {
|
|
35
|
+
loadConfig: () => options.cfg ?? {},
|
|
36
|
+
},
|
|
37
|
+
...(options.channel ? { channel: options.channel as PluginRuntime["channel"] } : {}),
|
|
38
|
+
...(logging ? { logging } : {}),
|
|
39
|
+
state: {
|
|
40
|
+
resolveStateDir: defaultStateDirResolver,
|
|
41
|
+
},
|
|
42
|
+
} as PluginRuntime);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type MatrixMonitorTestRuntimeOptions = Pick<MatrixTestRuntimeOptions, "cfg" | "stateDir"> & {
|
|
46
|
+
matchesMentionPatterns?: (text: string, patterns: RegExp[]) => boolean;
|
|
47
|
+
saveMediaBuffer?: NonNullable<NonNullable<PluginRuntime["channel"]>["media"]>["saveMediaBuffer"];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function installMatrixMonitorTestRuntime(
|
|
51
|
+
options: MatrixMonitorTestRuntimeOptions = {},
|
|
52
|
+
): void {
|
|
53
|
+
installMatrixTestRuntime({
|
|
54
|
+
cfg: options.cfg,
|
|
55
|
+
stateDir: options.stateDir,
|
|
56
|
+
channel: {
|
|
57
|
+
mentions: {
|
|
58
|
+
buildMentionRegexes: () => [],
|
|
59
|
+
matchesMentionPatterns:
|
|
60
|
+
options.matchesMentionPatterns ??
|
|
61
|
+
((text: string, patterns: RegExp[]) => patterns.some((pattern) => pattern.test(text))),
|
|
62
|
+
matchesMentionWithExplicit: () => false,
|
|
63
|
+
implicitMentionKindWhen,
|
|
64
|
+
resolveInboundMentionDecision,
|
|
65
|
+
},
|
|
66
|
+
media: {
|
|
67
|
+
fetchRemoteMedia: vi.fn(),
|
|
68
|
+
saveMediaBuffer: options.saveMediaBuffer ?? vi.fn(),
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export {
|
|
2
|
+
registerSessionBindingAdapter,
|
|
3
|
+
__testing,
|
|
4
|
+
} from "../../../../src/infra/outbound/session-binding-service.js";
|
|
5
|
+
export { setActivePluginRegistry } from "../../../../src/plugins/runtime.js";
|
|
6
|
+
export { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
|
|
7
|
+
export { createTestRegistry } from "../../../../src/test-utils/channel-plugins.js";
|
|
8
|
+
export type { OpenClawConfig } from "../../../../src/config/config.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { handleMatrixAction } from "./tool-actions.js";
|