@badgerclaw/connect 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@badgerclaw/connect",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "BadgerClaw channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -0,0 +1,95 @@
1
+ import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
2
+ import { appendFileSync, mkdirSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { getMatrixLogService } from "../sdk-runtime.js";
6
+
7
+ export type KeyBackupStatus = {
8
+ enabled: boolean;
9
+ version: string | null;
10
+ deviceId: string | null;
11
+ };
12
+
13
+ export async function getEncryptionKeyBackupStatus(
14
+ client: MatrixClient,
15
+ ): Promise<KeyBackupStatus> {
16
+ const LogService = getMatrixLogService();
17
+ try {
18
+ const backupInfo = await client.getKeyBackupVersion();
19
+ const whoami = await client.getWhoAmI();
20
+ const deviceId = whoami.device_id ?? null;
21
+ return {
22
+ enabled: backupInfo !== null,
23
+ version: backupInfo?.version ?? null,
24
+ deviceId,
25
+ };
26
+ } catch (err) {
27
+ LogService.warn("MatrixKeyBackup", "Failed to check key backup status:", err);
28
+ return { enabled: false, version: null, deviceId: null };
29
+ }
30
+ }
31
+
32
+ export async function setupKeyBackup(client: MatrixClient): Promise<void> {
33
+ const LogService = getMatrixLogService();
34
+
35
+ let deviceId = "(unknown)";
36
+ try {
37
+ const whoami = await client.getWhoAmI();
38
+ deviceId = whoami.device_id ?? deviceId;
39
+ } catch {
40
+ // Non-fatal
41
+ }
42
+
43
+ LogService.info("MatrixKeyBackup", `Crypto ready — device ID: ${deviceId}`);
44
+
45
+ if (!client.crypto) {
46
+ LogService.info("MatrixKeyBackup", "Crypto client not available, skipping key backup setup");
47
+ return;
48
+ }
49
+
50
+ try {
51
+ let backupInfo = await client.getKeyBackupVersion();
52
+
53
+ if (!backupInfo) {
54
+ // No backup exists — create one now
55
+ LogService.info("MatrixKeyBackup", "No key backup found — creating server-side key backup");
56
+ try {
57
+ backupInfo = await (client as any).signAndCreateKeyBackupVersion({
58
+ algorithm: "m.megolm_backup.v1.curve25519-aes-sha2",
59
+ auth_data: {},
60
+ });
61
+ LogService.info("MatrixKeyBackup", `Created new key backup version ${backupInfo?.version}`);
62
+ } catch (createErr) {
63
+ LogService.warn("MatrixKeyBackup", "Failed to create key backup version:", createErr);
64
+ return;
65
+ }
66
+ }
67
+
68
+ if (!backupInfo) {
69
+ LogService.warn("MatrixKeyBackup", "Key backup info unavailable after creation attempt");
70
+ return;
71
+ }
72
+
73
+ await client.crypto.enableKeyBackup(backupInfo);
74
+ LogService.info(
75
+ "MatrixKeyBackup",
76
+ `Key backup enabled (version ${backupInfo.version}) on device ${deviceId} — keys will upload automatically`,
77
+ );
78
+ _persistBackupRecord(backupInfo.version, deviceId);
79
+ } catch (err) {
80
+ LogService.warn("MatrixKeyBackup", "Key backup setup failed:", err);
81
+ }
82
+ }
83
+
84
+ function _persistBackupRecord(version: string, deviceId: string): void {
85
+ try {
86
+ const dir = join(homedir(), ".openclaw", "backup");
87
+ mkdirSync(dir, { recursive: true });
88
+ const path = join(dir, "key-backup-record.log");
89
+ const entry =
90
+ JSON.stringify({ version, deviceId, timestamp: new Date().toISOString() }) + "\n";
91
+ appendFileSync(path, entry, "utf8");
92
+ } catch {
93
+ // Non-fatal — backup is enabled, record persistence is best-effort
94
+ }
95
+ }
@@ -2,6 +2,7 @@ import type { MatrixClient } from "@vector-im/matrix-bot-sdk";
2
2
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
3
3
  import type { CoreConfig } from "../../types.js";
4
4
  import { getMatrixLogService } from "../sdk-runtime.js";
5
+ import { setupKeyBackup } from "./backup.js";
5
6
  import { resolveMatrixAuth } from "./config.js";
6
7
  import { createMatrixClient } from "./create-client.js";
7
8
  import { startMatrixClientWithGrace } from "./startup.js";
@@ -79,6 +80,7 @@ async function ensureSharedClientStarted(params: {
79
80
  joinedRooms,
80
81
  );
81
82
  params.state.cryptoReady = true;
83
+ await setupKeyBackup(client);
82
84
  }
83
85
  } catch (err) {
84
86
  const LogService = getMatrixLogService();