openclaw-bitchat 0.1.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/dist/index.js ADDED
@@ -0,0 +1,240 @@
1
+ /**
2
+ * @openclaw/bitchat - Bitchat BLE Mesh Channel Plugin
3
+ *
4
+ * This plugin enables OpenClaw to communicate via the Bitchat
5
+ * peer-to-peer BLE mesh network.
6
+ *
7
+ * Architecture:
8
+ * - bitchat-node runs as a background service (separate process)
9
+ * - This plugin communicates with it via HTTP bridge
10
+ * - Inbound: webhook from bitchat-node → OpenClaw session
11
+ * - Outbound: OpenClaw → HTTP API → bitchat-node → BLE mesh
12
+ */
13
+ import { BitchatBridge } from './bridge.js';
14
+ // Default config values
15
+ const DEFAULT_CONFIG = {
16
+ enabled: true,
17
+ nickname: 'openclaw',
18
+ bridgeUrl: 'http://localhost:3939',
19
+ webhookPath: '/bitchat-webhook',
20
+ autoStart: false,
21
+ dmPolicy: 'open',
22
+ allowFrom: [],
23
+ };
24
+ // Bridge instance (singleton for the gateway)
25
+ let bridge = null;
26
+ /**
27
+ * Resolve channel config from OpenClaw config
28
+ */
29
+ function resolveConfig(cfg) {
30
+ const channelConfig = cfg.channels?.bitchat;
31
+ return {
32
+ ...DEFAULT_CONFIG,
33
+ ...channelConfig,
34
+ };
35
+ }
36
+ /**
37
+ * Check if a sender is allowed based on policy
38
+ */
39
+ function isSenderAllowed(config, senderPeerID) {
40
+ switch (config.dmPolicy) {
41
+ case 'disabled':
42
+ return false;
43
+ case 'allowlist':
44
+ return config.allowFrom.includes(senderPeerID) || config.allowFrom.includes('*');
45
+ case 'open':
46
+ default:
47
+ return true;
48
+ }
49
+ }
50
+ /**
51
+ * Create the Bitchat channel plugin
52
+ */
53
+ function createBitchatPlugin() {
54
+ return {
55
+ id: 'bitchat',
56
+ meta: {
57
+ id: 'bitchat',
58
+ label: 'Bitchat',
59
+ selectionLabel: 'Bitchat (BLE Mesh)',
60
+ docsPath: '/channels/bitchat',
61
+ docsLabel: 'bitchat',
62
+ blurb: 'Peer-to-peer BLE mesh network messaging.',
63
+ aliases: ['ble', 'mesh'],
64
+ },
65
+ capabilities: {
66
+ chatTypes: ['direct', 'group'],
67
+ media: false, // BLE bandwidth is limited
68
+ },
69
+ config: {
70
+ listAccountIds: () => ['default'],
71
+ resolveAccount: (cfg, accountId) => {
72
+ const config = resolveConfig(cfg);
73
+ return {
74
+ accountId: accountId ?? 'default',
75
+ enabled: config.enabled,
76
+ configured: Boolean(config.bridgeUrl),
77
+ config,
78
+ };
79
+ },
80
+ defaultAccountId: () => 'default',
81
+ isConfigured: (account) => account.configured ?? false,
82
+ describeAccount: (account) => ({
83
+ accountId: account.accountId,
84
+ enabled: account.enabled ?? true,
85
+ configured: account.configured ?? false,
86
+ }),
87
+ },
88
+ security: {
89
+ resolveDmPolicy: ({ account }) => ({
90
+ policy: String(account.config?.dmPolicy ?? 'open'),
91
+ allowFrom: account.config?.allowFrom ?? [],
92
+ policyPath: 'channels.bitchat.dmPolicy',
93
+ allowFromPath: 'channels.bitchat.allowFrom',
94
+ approveHint: 'Add peer ID to channels.bitchat.allowFrom',
95
+ normalizeEntry: (raw) => raw.trim().toLowerCase(),
96
+ }),
97
+ },
98
+ messaging: {
99
+ normalizeTarget: ({ target }) => {
100
+ // Accept peer ID or nickname
101
+ const cleaned = target.replace(/^bitchat:/i, '').trim();
102
+ return { target: cleaned, normalized: cleaned };
103
+ },
104
+ targetResolver: {
105
+ looksLikeId: (target) => /^[a-f0-9]{16}$/i.test(target),
106
+ hint: '<peerID|nickname>',
107
+ },
108
+ },
109
+ outbound: {
110
+ deliveryMode: 'direct',
111
+ sendText: async ({ text, target }) => {
112
+ if (!bridge) {
113
+ return { ok: false, error: 'Bitchat bridge not initialized' };
114
+ }
115
+ try {
116
+ // Determine if this is a DM or public message
117
+ const isDirect = target && target !== 'public' && target !== '*';
118
+ if (isDirect) {
119
+ await bridge.sendDirectMessage(target, text);
120
+ }
121
+ else {
122
+ await bridge.sendPublicMessage(text);
123
+ }
124
+ return { ok: true };
125
+ }
126
+ catch (err) {
127
+ const error = err instanceof Error ? err.message : String(err);
128
+ return { ok: false, error };
129
+ }
130
+ },
131
+ },
132
+ };
133
+ }
134
+ /**
135
+ * Main plugin registration
136
+ */
137
+ export default function register(api) {
138
+ const logger = api.logger;
139
+ // Register the channel
140
+ const plugin = createBitchatPlugin();
141
+ api.registerChannel({ plugin });
142
+ // Register background service to manage bridge connection
143
+ api.registerService({
144
+ id: 'bitchat-bridge',
145
+ start: async () => {
146
+ const cfg = api.config;
147
+ const config = resolveConfig(cfg);
148
+ if (!config.enabled) {
149
+ logger.info('[bitchat] Channel disabled');
150
+ return;
151
+ }
152
+ logger.info(`[bitchat] Starting bridge connection to ${config.bridgeUrl}`);
153
+ bridge = new BitchatBridge({
154
+ bridgeUrl: config.bridgeUrl,
155
+ nickname: config.nickname,
156
+ onMessage: async (msg) => {
157
+ // Check if sender is allowed
158
+ if (!isSenderAllowed(config, msg.senderPeerID)) {
159
+ logger.debug(`[bitchat] Ignoring message from unauthorized peer: ${msg.senderPeerID}`);
160
+ return;
161
+ }
162
+ // Route message to OpenClaw session
163
+ try {
164
+ await api.injectMessage({
165
+ channel: 'bitchat',
166
+ senderId: msg.senderPeerID,
167
+ senderName: msg.senderNickname,
168
+ text: msg.text,
169
+ messageId: msg.messageId,
170
+ chatType: msg.type === 'direct' ? 'direct' : 'group',
171
+ timestamp: msg.timestamp,
172
+ });
173
+ }
174
+ catch (err) {
175
+ logger.error('[bitchat] Failed to inject message:', err);
176
+ }
177
+ },
178
+ logger,
179
+ });
180
+ await bridge.connect();
181
+ logger.info('[bitchat] Bridge connected');
182
+ },
183
+ stop: async () => {
184
+ if (bridge) {
185
+ await bridge.disconnect();
186
+ bridge = null;
187
+ logger.info('[bitchat] Bridge disconnected');
188
+ }
189
+ },
190
+ });
191
+ // Register webhook handler for inbound messages
192
+ api.registerHttpHandler({
193
+ method: 'POST',
194
+ path: '/bitchat-webhook',
195
+ handler: async (req, res) => {
196
+ try {
197
+ const body = req.body;
198
+ if (!body || !body.senderPeerID || !body.text) {
199
+ res.status(400).json({ error: 'Invalid message format' });
200
+ return;
201
+ }
202
+ const cfg = api.config;
203
+ const config = resolveConfig(cfg);
204
+ if (!isSenderAllowed(config, body.senderPeerID)) {
205
+ res.status(403).json({ error: 'Sender not allowed' });
206
+ return;
207
+ }
208
+ await api.injectMessage({
209
+ channel: 'bitchat',
210
+ senderId: body.senderPeerID,
211
+ senderName: body.senderNickname,
212
+ text: body.text,
213
+ messageId: body.messageId,
214
+ chatType: body.type === 'direct' ? 'direct' : 'group',
215
+ timestamp: body.timestamp,
216
+ });
217
+ res.json({ ok: true });
218
+ }
219
+ catch (err) {
220
+ logger.error('[bitchat] Webhook error:', err);
221
+ res.status(500).json({ error: 'Internal error' });
222
+ }
223
+ },
224
+ });
225
+ // Register RPC methods for status
226
+ api.registerGatewayMethod('bitchat.status', async ({ respond }) => {
227
+ const cfg = api.config;
228
+ const config = resolveConfig(cfg);
229
+ const status = {
230
+ enabled: config.enabled,
231
+ bridgeUrl: config.bridgeUrl,
232
+ connected: bridge?.isConnected() ?? false,
233
+ nickname: config.nickname,
234
+ dmPolicy: config.dmPolicy,
235
+ };
236
+ respond(true, status);
237
+ });
238
+ logger.info('[bitchat] Plugin registered');
239
+ }
240
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Type definitions for OpenClaw plugin API
3
+ *
4
+ * These are simplified types based on the OpenClaw plugin interface.
5
+ * In production, these would come from the openclaw package types.
6
+ */
7
+ export interface Logger {
8
+ info: (...args: unknown[]) => void;
9
+ warn: (...args: unknown[]) => void;
10
+ error: (...args: unknown[]) => void;
11
+ debug: (...args: unknown[]) => void;
12
+ }
13
+ export interface InjectMessageOptions {
14
+ channel: string;
15
+ senderId: string;
16
+ senderName?: string;
17
+ text: string;
18
+ messageId?: string;
19
+ chatType?: 'direct' | 'group';
20
+ timestamp?: number;
21
+ replyToId?: string;
22
+ media?: {
23
+ type: string;
24
+ url?: string;
25
+ buffer?: Buffer;
26
+ filename?: string;
27
+ }[];
28
+ }
29
+ export interface HttpHandler {
30
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
31
+ path: string;
32
+ handler: (req: HttpRequest, res: HttpResponse) => Promise<void> | void;
33
+ }
34
+ export interface HttpRequest {
35
+ body: unknown;
36
+ query: Record<string, string>;
37
+ params: Record<string, string>;
38
+ headers: Record<string, string>;
39
+ }
40
+ export interface HttpResponse {
41
+ status: (code: number) => HttpResponse;
42
+ json: (data: unknown) => void;
43
+ send: (data: string) => void;
44
+ }
45
+ export interface ServiceDefinition {
46
+ id: string;
47
+ start: () => Promise<void> | void;
48
+ stop: () => Promise<void> | void;
49
+ }
50
+ export interface GatewayMethodContext {
51
+ respond: (success: boolean, data?: unknown) => void;
52
+ params?: Record<string, unknown>;
53
+ }
54
+ export interface ChannelMeta {
55
+ id: string;
56
+ label: string;
57
+ selectionLabel?: string;
58
+ docsPath?: string;
59
+ docsLabel?: string;
60
+ blurb?: string;
61
+ aliases?: string[];
62
+ }
63
+ export interface ChannelCapabilities {
64
+ chatTypes: readonly ('direct' | 'group')[];
65
+ media?: boolean;
66
+ threads?: boolean;
67
+ reactions?: boolean;
68
+ }
69
+ export interface ChannelAccount {
70
+ accountId: string;
71
+ enabled?: boolean;
72
+ configured?: boolean;
73
+ config?: Record<string, unknown>;
74
+ }
75
+ export interface DmPolicyResult {
76
+ policy: string;
77
+ allowFrom: string[];
78
+ policyPath: string;
79
+ allowFromPath: string;
80
+ approveHint: string;
81
+ normalizeEntry: (raw: string) => string;
82
+ }
83
+ export interface NormalizeTargetResult {
84
+ target: string;
85
+ normalized: string;
86
+ }
87
+ export interface SendResult {
88
+ ok: boolean;
89
+ error?: string;
90
+ messageId?: string;
91
+ }
92
+ export interface ChannelPlugin {
93
+ id: string;
94
+ meta: ChannelMeta;
95
+ capabilities: ChannelCapabilities;
96
+ config: {
97
+ listAccountIds: (cfg: Record<string, unknown>) => string[];
98
+ resolveAccount: (cfg: Record<string, unknown>, accountId?: string) => ChannelAccount;
99
+ defaultAccountId?: (cfg: Record<string, unknown>) => string;
100
+ isConfigured?: (account: ChannelAccount) => boolean;
101
+ describeAccount?: (account: ChannelAccount) => Record<string, unknown>;
102
+ };
103
+ security?: {
104
+ resolveDmPolicy?: (ctx: {
105
+ cfg: Record<string, unknown>;
106
+ account: ChannelAccount;
107
+ }) => DmPolicyResult;
108
+ };
109
+ messaging?: {
110
+ normalizeTarget?: (ctx: {
111
+ target: string;
112
+ cfg: Record<string, unknown>;
113
+ }) => NormalizeTargetResult;
114
+ targetResolver?: {
115
+ looksLikeId: (target: string) => boolean;
116
+ hint: string;
117
+ };
118
+ };
119
+ outbound?: {
120
+ deliveryMode: 'direct' | 'queued';
121
+ sendText: (ctx: {
122
+ text: string;
123
+ target: string;
124
+ cfg: Record<string, unknown>;
125
+ account: ChannelAccount;
126
+ }) => Promise<SendResult>;
127
+ sendMedia?: (ctx: {
128
+ media: {
129
+ type: string;
130
+ buffer: Buffer;
131
+ filename?: string;
132
+ };
133
+ target: string;
134
+ cfg: Record<string, unknown>;
135
+ account: ChannelAccount;
136
+ }) => Promise<SendResult>;
137
+ };
138
+ }
139
+ export interface PluginApi {
140
+ logger: Logger;
141
+ config: unknown;
142
+ registerChannel: (opts: {
143
+ plugin: ChannelPlugin;
144
+ }) => void;
145
+ registerService: (service: ServiceDefinition) => void;
146
+ registerHttpHandler: (handler: HttpHandler) => void;
147
+ registerGatewayMethod: (name: string, handler: (ctx: GatewayMethodContext) => Promise<void> | void) => void;
148
+ injectMessage: (opts: InjectMessageOptions) => Promise<void>;
149
+ }
150
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type definitions for OpenClaw plugin API
3
+ *
4
+ * These are simplified types based on the OpenClaw plugin interface.
5
+ * In production, these would come from the openclaw package types.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,58 @@
1
+ {
2
+ "id": "bitchat",
3
+ "name": "Bitchat Channel",
4
+ "version": "0.1.0",
5
+ "description": "Bitchat BLE mesh network channel plugin for OpenClaw",
6
+ "author": "Kyle Graves",
7
+ "configSchema": {
8
+ "type": "object",
9
+ "additionalProperties": false,
10
+ "properties": {
11
+ "enabled": {
12
+ "type": "boolean",
13
+ "default": true,
14
+ "description": "Enable/disable the Bitchat channel"
15
+ },
16
+ "nickname": {
17
+ "type": "string",
18
+ "description": "Display name on the mesh network"
19
+ },
20
+ "bridgeUrl": {
21
+ "type": "string",
22
+ "default": "http://localhost:3939",
23
+ "description": "URL of the bitchat-node HTTP bridge"
24
+ },
25
+ "webhookPath": {
26
+ "type": "string",
27
+ "default": "/bitchat-webhook",
28
+ "description": "Webhook endpoint path for incoming messages"
29
+ },
30
+ "autoStart": {
31
+ "type": "boolean",
32
+ "default": false,
33
+ "description": "Auto-start bitchat-node daemon (if installed locally)"
34
+ },
35
+ "dmPolicy": {
36
+ "type": "string",
37
+ "enum": ["open", "allowlist", "disabled"],
38
+ "default": "open",
39
+ "description": "DM access policy"
40
+ },
41
+ "allowFrom": {
42
+ "type": "array",
43
+ "items": { "type": "string" },
44
+ "default": [],
45
+ "description": "Allowed peer IDs (when dmPolicy=allowlist)"
46
+ }
47
+ }
48
+ },
49
+ "uiHints": {
50
+ "enabled": { "label": "Enabled" },
51
+ "nickname": { "label": "Nickname", "placeholder": "my-agent" },
52
+ "bridgeUrl": { "label": "Bridge URL", "placeholder": "http://localhost:3939" },
53
+ "webhookPath": { "label": "Webhook Path", "placeholder": "/bitchat-webhook" },
54
+ "autoStart": { "label": "Auto-start daemon" },
55
+ "dmPolicy": { "label": "DM Policy" },
56
+ "allowFrom": { "label": "Allowed Peer IDs" }
57
+ }
58
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "openclaw-bitchat",
3
+ "version": "0.1.0",
4
+ "description": "OpenClaw channel plugin for Bitchat BLE mesh network",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "openclaw": {
15
+ "extensions": ["./dist/index.js"],
16
+ "channel": {
17
+ "id": "bitchat",
18
+ "label": "Bitchat",
19
+ "selectionLabel": "Bitchat (BLE Mesh)",
20
+ "docsPath": "/channels/bitchat",
21
+ "docsLabel": "bitchat",
22
+ "blurb": "Peer-to-peer BLE mesh network messaging.",
23
+ "order": 90,
24
+ "aliases": ["ble", "mesh"]
25
+ },
26
+ "install": {
27
+ "npmSpec": "openclaw-bitchat",
28
+ "defaultChoice": "npm"
29
+ }
30
+ },
31
+ "scripts": {
32
+ "build": "tsc",
33
+ "dev": "tsc --watch",
34
+ "clean": "rm -rf dist",
35
+ "prepublishOnly": "npm run build"
36
+ },
37
+ "dependencies": {
38
+ "bitchat-node": "^0.1.0"
39
+ },
40
+ "peerDependencies": {
41
+ "openclaw": ">=2026.1.0"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^20.10.0",
45
+ "typescript": "^5.3.0"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/wkyleg/openclaw-bitchat.git"
50
+ },
51
+ "keywords": [
52
+ "openclaw",
53
+ "openclaw-plugin",
54
+ "bitchat",
55
+ "bluetooth",
56
+ "ble",
57
+ "mesh",
58
+ "p2p"
59
+ ],
60
+ "license": "Unlicense",
61
+ "engines": {
62
+ "node": ">=18"
63
+ }
64
+ }