@badgerclaw/connect 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.
Files changed (70) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/SETUP.md +131 -0
  3. package/index.ts +23 -0
  4. package/openclaw.plugin.json +1 -0
  5. package/package.json +32 -0
  6. package/src/actions.ts +195 -0
  7. package/src/channel.ts +461 -0
  8. package/src/config-schema.ts +62 -0
  9. package/src/connect.ts +17 -0
  10. package/src/directory-live.ts +209 -0
  11. package/src/group-mentions.ts +52 -0
  12. package/src/matrix/accounts.ts +114 -0
  13. package/src/matrix/actions/client.ts +47 -0
  14. package/src/matrix/actions/limits.ts +6 -0
  15. package/src/matrix/actions/messages.ts +126 -0
  16. package/src/matrix/actions/pins.ts +84 -0
  17. package/src/matrix/actions/reactions.ts +102 -0
  18. package/src/matrix/actions/room.ts +85 -0
  19. package/src/matrix/actions/summary.ts +75 -0
  20. package/src/matrix/actions/types.ts +85 -0
  21. package/src/matrix/actions.ts +15 -0
  22. package/src/matrix/active-client.ts +32 -0
  23. package/src/matrix/client/config.ts +245 -0
  24. package/src/matrix/client/create-client.ts +125 -0
  25. package/src/matrix/client/logging.ts +46 -0
  26. package/src/matrix/client/runtime.ts +4 -0
  27. package/src/matrix/client/shared.ts +210 -0
  28. package/src/matrix/client/startup.ts +29 -0
  29. package/src/matrix/client/storage.ts +131 -0
  30. package/src/matrix/client/types.ts +34 -0
  31. package/src/matrix/client-bootstrap.ts +47 -0
  32. package/src/matrix/client.ts +14 -0
  33. package/src/matrix/credentials.ts +125 -0
  34. package/src/matrix/deps.ts +126 -0
  35. package/src/matrix/format.ts +22 -0
  36. package/src/matrix/index.ts +11 -0
  37. package/src/matrix/monitor/access-policy.ts +126 -0
  38. package/src/matrix/monitor/allowlist.ts +94 -0
  39. package/src/matrix/monitor/auto-join.ts +72 -0
  40. package/src/matrix/monitor/direct.ts +152 -0
  41. package/src/matrix/monitor/events.ts +168 -0
  42. package/src/matrix/monitor/handler.ts +768 -0
  43. package/src/matrix/monitor/inbound-body.ts +28 -0
  44. package/src/matrix/monitor/index.ts +414 -0
  45. package/src/matrix/monitor/location.ts +100 -0
  46. package/src/matrix/monitor/media.ts +118 -0
  47. package/src/matrix/monitor/mentions.ts +62 -0
  48. package/src/matrix/monitor/replies.ts +124 -0
  49. package/src/matrix/monitor/room-info.ts +55 -0
  50. package/src/matrix/monitor/rooms.ts +47 -0
  51. package/src/matrix/monitor/threads.ts +68 -0
  52. package/src/matrix/monitor/types.ts +39 -0
  53. package/src/matrix/poll-types.ts +167 -0
  54. package/src/matrix/probe.ts +69 -0
  55. package/src/matrix/sdk-runtime.ts +18 -0
  56. package/src/matrix/send/client.ts +99 -0
  57. package/src/matrix/send/formatting.ts +93 -0
  58. package/src/matrix/send/media.ts +230 -0
  59. package/src/matrix/send/targets.ts +150 -0
  60. package/src/matrix/send/types.ts +110 -0
  61. package/src/matrix/send-queue.ts +28 -0
  62. package/src/matrix/send.ts +267 -0
  63. package/src/onboarding.ts +331 -0
  64. package/src/outbound.ts +58 -0
  65. package/src/resolve-targets.ts +125 -0
  66. package/src/runtime.ts +6 -0
  67. package/src/secret-input.ts +13 -0
  68. package/src/test-mocks.ts +53 -0
  69. package/src/tool-actions.ts +164 -0
  70. package/src/types.ts +118 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,104 @@
1
+ # Changelog
2
+
3
+ ## 2026.3.13
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core OpenClaw release numbers.
8
+
9
+ ## 2026.3.12
10
+
11
+ ### Changes
12
+
13
+ - Version alignment with core OpenClaw release numbers.
14
+
15
+ ## 2026.3.11
16
+
17
+ ### Changes
18
+
19
+ - Version alignment with core OpenClaw release numbers.
20
+
21
+ ## 2026.3.10
22
+
23
+ ### Changes
24
+
25
+ - Version alignment with core OpenClaw release numbers.
26
+
27
+ ## 2026.3.9
28
+
29
+ ### Changes
30
+
31
+ - Version alignment with core OpenClaw release numbers.
32
+
33
+ ## 2026.3.8-beta.1
34
+
35
+ ### Changes
36
+
37
+ - Version alignment with core OpenClaw release numbers.
38
+
39
+ ## 2026.3.8
40
+
41
+ ### Changes
42
+
43
+ - Version alignment with core OpenClaw release numbers.
44
+
45
+ ## 2026.3.7
46
+
47
+ ### Changes
48
+
49
+ - Version alignment with core OpenClaw release numbers.
50
+
51
+ ## 2026.3.3
52
+
53
+ ### Changes
54
+
55
+ - Version alignment with core OpenClaw release numbers.
56
+
57
+ ## 2026.3.2
58
+
59
+ ### Changes
60
+
61
+ - Version alignment with core OpenClaw release numbers.
62
+
63
+ ## 2026.3.1
64
+
65
+ ### Changes
66
+
67
+ - Version alignment with core OpenClaw release numbers.
68
+
69
+ ## 2026.2.26
70
+
71
+ ### Changes
72
+
73
+ - Version alignment with core OpenClaw release numbers.
74
+
75
+ ## 2026.2.25
76
+
77
+ ### Changes
78
+
79
+ - Version alignment with core OpenClaw release numbers.
80
+
81
+ ## 2026.2.24
82
+
83
+ ### Changes
84
+
85
+ - Version alignment with core OpenClaw release numbers.
86
+
87
+ ## 2026.2.22
88
+
89
+ ### Changes
90
+
91
+ - Version alignment with core OpenClaw release numbers.
92
+
93
+ ## 2026.1.14
94
+
95
+ ### Features
96
+
97
+ - Matrix channel plugin with homeserver + user ID auth (access token or password login with device name).
98
+ - Direct messages with pairing/allowlist/open/disabled policies and allowFrom support.
99
+ - Group/room controls: allowlist policy, per-room config, mention gating, auto-reply, per-room skills/system prompts.
100
+ - Threads: replyToMode controls and thread replies (off/inbound/always).
101
+ - Messaging: text chunking, media uploads with size caps, reactions, polls, typing, and message edits/deletes.
102
+ - Actions: read messages, list/remove reactions, pin/unpin/list pins, member info, room info.
103
+ - Auto-join invites with allowlist support.
104
+ - Status + probe reporting for health checks.
package/SETUP.md ADDED
@@ -0,0 +1,131 @@
1
+ # BadgerClaw + OpenClaw — Setup Guide
2
+
3
+ Connect your OpenClaw AI agent to BadgerClaw encrypted chat rooms.
4
+
5
+ ## Prerequisites
6
+
7
+ - **BadgerClaw iOS app** installed and logged in
8
+ - **OpenClaw** installed on your machine (`npm install -g openclaw`)
9
+ - Both on the same network (not required, just for initial setup)
10
+
11
+ ---
12
+
13
+ ## Step 1: Create a Bot in BadgerClaw
14
+
15
+ Open the BadgerClaw app on your phone.
16
+
17
+ 1. Open any room or DM
18
+ 2. Type: `/bot create <name>`
19
+ - Example: `/bot create jarvis`
20
+ 3. BotBadger responds with:
21
+
22
+ ```
23
+ 🦡 Bot created!
24
+
25
+ Name: jarvis
26
+ ID: @abc123_jarvis_bot:badger.signout.io
27
+
28
+ Connect to OpenClaw:
29
+ openclaw plugins install @badgerclaw/connect
30
+ openclaw badgerclaw connect BCK-A8F3-X9K2
31
+
32
+ Code expires in 24 hours.
33
+ Run /bot pair jarvis to generate a new code.
34
+ ```
35
+
36
+ 4. **Copy the pairing code** (BCK-XXXX-XXXX)
37
+
38
+ > **Need a new code?** Type `/bot pair jarvis` to regenerate.
39
+
40
+ ---
41
+
42
+ ## Step 2: Install the BadgerClaw Plugin
43
+
44
+ On your machine (Mac, PC, Linux, Pi), run:
45
+
46
+ ```bash
47
+ # From GitHub (current method)
48
+ git clone https://github.com/darkstaar4/badgerclaw-plugin.git
49
+ openclaw plugins install ./badgerclaw-plugin
50
+
51
+ # From npm (coming soon)
52
+ # openclaw plugins install @badgerclaw/connect
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Step 3: Connect with Pairing Code
58
+
59
+ Run the OpenClaw configure wizard:
60
+
61
+ ```bash
62
+ openclaw configure
63
+ ```
64
+
65
+ 1. Select **BadgerClaw** as your channel
66
+ 2. Enter your pairing code: `BCK-XXXX-XXXX`
67
+ 3. The plugin automatically:
68
+ - Validates the code with BadgerClaw servers
69
+ - Retrieves your bot's credentials
70
+ - Enables end-to-end encryption
71
+ - Configures auto-join for room invites
72
+ 4. Done! Your agent is connected.
73
+
74
+ ---
75
+
76
+ ## Step 4: Start Chatting
77
+
78
+ Restart the OpenClaw gateway to apply the new config:
79
+
80
+ ```bash
81
+ openclaw gateway restart
82
+ ```
83
+
84
+ Now in the BadgerClaw app:
85
+
86
+ 1. **DM your bot** — find it in your contacts (`@xxx_jarvis_bot:badger.signout.io`) and send a message
87
+ 2. **Add to a room** — type `/bot add @jarvis` in any room
88
+ 3. **Add to a Space** — add the bot to any room inside a Space
89
+
90
+ Your OpenClaw agent will receive messages and respond through BadgerClaw — fully end-to-end encrypted.
91
+
92
+ ---
93
+
94
+ ## Troubleshooting
95
+
96
+ ### "Invalid pairing code"
97
+ - Code may have expired (24h limit). Run `/bot pair <name>` in the app to get a new one.
98
+ - Make sure you're entering the code exactly as shown (BCK-XXXX-XXXX).
99
+
100
+ ### Bot doesn't respond
101
+ 1. Check OpenClaw is running: `openclaw status`
102
+ 2. Check gateway logs: `openclaw logs --follow`
103
+ 3. Verify the BadgerClaw channel is configured: `openclaw channels status`
104
+
105
+ ### "Pairing code already redeemed"
106
+ Each code is one-time use. Run `/bot pair <name>` to generate a fresh one.
107
+
108
+ ### Need to reconnect
109
+ Run `openclaw configure` again and enter a new pairing code.
110
+
111
+ ---
112
+
113
+ ## Architecture
114
+
115
+ ```
116
+ Your Phone (BadgerClaw App)
117
+
118
+ │ E2EE Messages
119
+
120
+ BadgerClaw Server (badger.signout.io)
121
+
122
+ │ E2EE Messages
123
+
124
+ Your Machine (OpenClaw + BadgerClaw Plugin)
125
+
126
+ │ Agent Processing
127
+
128
+ AI Response → Back through the same encrypted path
129
+ ```
130
+
131
+ All messages are end-to-end encrypted. BadgerClaw servers cannot read your conversations.
package/index.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/matrix";
2
+ import { emptyPluginConfigSchema } from "openclaw/plugin-sdk/matrix";
3
+ import { matrixPlugin } from "./src/channel.js";
4
+ import { ensureMatrixCryptoRuntime } from "./src/matrix/deps.js";
5
+ import { setMatrixRuntime } from "./src/runtime.js";
6
+
7
+ const plugin = {
8
+ id: "badgerclaw",
9
+ name: "BadgerClaw",
10
+ description: "BadgerClaw encrypted AI agent channel",
11
+ configSchema: emptyPluginConfigSchema(),
12
+ register(api: OpenClawPluginApi) {
13
+ setMatrixRuntime(api.runtime);
14
+ void ensureMatrixCryptoRuntime({ log: api.logger.info }).catch((err) => {
15
+ const message = err instanceof Error ? err.message : String(err);
16
+ api.logger.warn?.(`badgerclaw: crypto runtime bootstrap failed: ${message}`);
17
+ });
18
+ api.registerChannel({ plugin: matrixPlugin });
19
+ },
20
+ };
21
+
22
+ export { redeemPairingCode } from "./src/connect.js";
23
+ export default plugin;
@@ -0,0 +1 @@
1
+ {"id":"badgerclaw","channels":["badgerclaw"],"configSchema":{"type":"object","additionalProperties":false,"properties":{}}}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@badgerclaw/connect",
3
+ "version": "1.0.0",
4
+ "description": "BadgerClaw channel plugin for OpenClaw",
5
+ "type": "module",
6
+ "dependencies": {
7
+ "@mariozechner/pi-agent-core": "0.58.0",
8
+ "@matrix-org/matrix-sdk-crypto-nodejs": "^0.4.0",
9
+ "@vector-im/matrix-bot-sdk": "0.8.0-element.3",
10
+ "markdown-it": "14.1.1",
11
+ "music-metadata": "^11.12.3",
12
+ "zod": "^4.3.6"
13
+ },
14
+ "openclaw": {
15
+ "extensions": ["./index.ts"],
16
+ "channel": {
17
+ "id": "badgerclaw",
18
+ "label": "BadgerClaw",
19
+ "selectionLabel": "BadgerClaw (encrypted AI agents)",
20
+ "docsPath": "/channels/badgerclaw",
21
+ "docsLabel": "badgerclaw",
22
+ "blurb": "encrypted AI agent messaging platform",
23
+ "order": 15,
24
+ "quickstartAllowFrom": true
25
+ },
26
+ "install": {
27
+ "npmSpec": "@badgerclaw/connect",
28
+ "localPath": "extensions/badgerclaw",
29
+ "defaultChoice": "npm"
30
+ }
31
+ }
32
+ }
package/src/actions.ts ADDED
@@ -0,0 +1,195 @@
1
+ import {
2
+ createActionGate,
3
+ readNumberParam,
4
+ readStringParam,
5
+ type ChannelMessageActionAdapter,
6
+ type ChannelMessageActionContext,
7
+ type ChannelMessageActionName,
8
+ type ChannelToolSend,
9
+ } from "openclaw/plugin-sdk/matrix";
10
+ import { resolveMatrixAccount } from "./matrix/accounts.js";
11
+ import { handleMatrixAction } from "./tool-actions.js";
12
+ import type { CoreConfig } from "./types.js";
13
+
14
+ export const matrixMessageActions: ChannelMessageActionAdapter = {
15
+ listActions: ({ cfg }) => {
16
+ const account = resolveMatrixAccount({ cfg: cfg as CoreConfig });
17
+ if (!account.enabled || !account.configured) {
18
+ return [];
19
+ }
20
+ const gate = createActionGate((cfg as CoreConfig).channels?.badgerclaw?.actions);
21
+ const actions = new Set<ChannelMessageActionName>(["send", "poll"]);
22
+ if (gate("reactions")) {
23
+ actions.add("react");
24
+ actions.add("reactions");
25
+ }
26
+ if (gate("messages")) {
27
+ actions.add("read");
28
+ actions.add("edit");
29
+ actions.add("delete");
30
+ }
31
+ if (gate("pins")) {
32
+ actions.add("pin");
33
+ actions.add("unpin");
34
+ actions.add("list-pins");
35
+ }
36
+ if (gate("memberInfo")) {
37
+ actions.add("member-info");
38
+ }
39
+ if (gate("channelInfo")) {
40
+ actions.add("channel-info");
41
+ }
42
+ return Array.from(actions);
43
+ },
44
+ supportsAction: ({ action }) => action !== "poll",
45
+ extractToolSend: ({ args }): ChannelToolSend | null => {
46
+ const action = typeof args.action === "string" ? args.action.trim() : "";
47
+ if (action !== "sendMessage") {
48
+ return null;
49
+ }
50
+ const to = typeof args.to === "string" ? args.to : undefined;
51
+ if (!to) {
52
+ return null;
53
+ }
54
+ return { to };
55
+ },
56
+ handleAction: async (ctx: ChannelMessageActionContext) => {
57
+ const { action, params, cfg } = ctx;
58
+ const resolveRoomId = () =>
59
+ readStringParam(params, "roomId") ??
60
+ readStringParam(params, "channelId") ??
61
+ readStringParam(params, "to", { required: true });
62
+
63
+ if (action === "send") {
64
+ const to = readStringParam(params, "to", { required: true });
65
+ const content = readStringParam(params, "message", {
66
+ required: true,
67
+ allowEmpty: true,
68
+ });
69
+ const mediaUrl = readStringParam(params, "media", { trim: false });
70
+ const replyTo = readStringParam(params, "replyTo");
71
+ const threadId = readStringParam(params, "threadId");
72
+ return await handleMatrixAction(
73
+ {
74
+ action: "sendMessage",
75
+ to,
76
+ content,
77
+ mediaUrl: mediaUrl ?? undefined,
78
+ replyToId: replyTo ?? undefined,
79
+ threadId: threadId ?? undefined,
80
+ },
81
+ cfg as CoreConfig,
82
+ );
83
+ }
84
+
85
+ if (action === "react") {
86
+ const messageId = readStringParam(params, "messageId", { required: true });
87
+ const emoji = readStringParam(params, "emoji", { allowEmpty: true });
88
+ const remove = typeof params.remove === "boolean" ? params.remove : undefined;
89
+ return await handleMatrixAction(
90
+ {
91
+ action: "react",
92
+ roomId: resolveRoomId(),
93
+ messageId,
94
+ emoji,
95
+ remove,
96
+ },
97
+ cfg as CoreConfig,
98
+ );
99
+ }
100
+
101
+ if (action === "reactions") {
102
+ const messageId = readStringParam(params, "messageId", { required: true });
103
+ const limit = readNumberParam(params, "limit", { integer: true });
104
+ return await handleMatrixAction(
105
+ {
106
+ action: "reactions",
107
+ roomId: resolveRoomId(),
108
+ messageId,
109
+ limit,
110
+ },
111
+ cfg as CoreConfig,
112
+ );
113
+ }
114
+
115
+ if (action === "read") {
116
+ const limit = readNumberParam(params, "limit", { integer: true });
117
+ return await handleMatrixAction(
118
+ {
119
+ action: "readMessages",
120
+ roomId: resolveRoomId(),
121
+ limit,
122
+ before: readStringParam(params, "before"),
123
+ after: readStringParam(params, "after"),
124
+ },
125
+ cfg as CoreConfig,
126
+ );
127
+ }
128
+
129
+ if (action === "edit") {
130
+ const messageId = readStringParam(params, "messageId", { required: true });
131
+ const content = readStringParam(params, "message", { required: true });
132
+ return await handleMatrixAction(
133
+ {
134
+ action: "editMessage",
135
+ roomId: resolveRoomId(),
136
+ messageId,
137
+ content,
138
+ },
139
+ cfg as CoreConfig,
140
+ );
141
+ }
142
+
143
+ if (action === "delete") {
144
+ const messageId = readStringParam(params, "messageId", { required: true });
145
+ return await handleMatrixAction(
146
+ {
147
+ action: "deleteMessage",
148
+ roomId: resolveRoomId(),
149
+ messageId,
150
+ },
151
+ cfg as CoreConfig,
152
+ );
153
+ }
154
+
155
+ if (action === "pin" || action === "unpin" || action === "list-pins") {
156
+ const messageId =
157
+ action === "list-pins"
158
+ ? undefined
159
+ : readStringParam(params, "messageId", { required: true });
160
+ return await handleMatrixAction(
161
+ {
162
+ action:
163
+ action === "pin" ? "pinMessage" : action === "unpin" ? "unpinMessage" : "listPins",
164
+ roomId: resolveRoomId(),
165
+ messageId,
166
+ },
167
+ cfg as CoreConfig,
168
+ );
169
+ }
170
+
171
+ if (action === "member-info") {
172
+ const userId = readStringParam(params, "userId", { required: true });
173
+ return await handleMatrixAction(
174
+ {
175
+ action: "memberInfo",
176
+ userId,
177
+ roomId: readStringParam(params, "roomId") ?? readStringParam(params, "channelId"),
178
+ },
179
+ cfg as CoreConfig,
180
+ );
181
+ }
182
+
183
+ if (action === "channel-info") {
184
+ return await handleMatrixAction(
185
+ {
186
+ action: "channelInfo",
187
+ roomId: resolveRoomId(),
188
+ },
189
+ cfg as CoreConfig,
190
+ );
191
+ }
192
+
193
+ throw new Error(`Action ${action} is not supported for provider matrix.`);
194
+ },
195
+ };