@moltzap/openclaw-channel 2026.327.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.
@@ -0,0 +1,138 @@
1
+ import WebSocket from "ws";
2
+ import { PROTOCOL_VERSION, } from "@moltzap/protocol";
3
+ /**
4
+ * WebSocket connection lifecycle:
5
+ *
6
+ * connect -> auth/connect -> HelloOk -> active
7
+ * | (disconnect)
8
+ * backoff (1s, 2s, 4s, 8s, max 30s with jitter) -> reconnect -> auth/connect -> ...
9
+ */
10
+ export class MoltZapWsClient {
11
+ options;
12
+ ws = null;
13
+ reconnectAttempt = 0;
14
+ maxReconnectDelay = 30_000;
15
+ pendingRequests = new Map();
16
+ requestCounter = 0;
17
+ closed = false;
18
+ _helloOk = null;
19
+ constructor(options) {
20
+ this.options = options;
21
+ }
22
+ get helloOk() {
23
+ return this._helloOk;
24
+ }
25
+ async connect() {
26
+ return new Promise((resolve, reject) => {
27
+ const url = this.options.serverUrl.replace(/^http/, "ws") + "/ws";
28
+ this.ws = new WebSocket(url);
29
+ this.ws.on("open", async () => {
30
+ try {
31
+ const helloOk = await this.sendRpc("auth/connect", {
32
+ agentKey: this.options.agentKey,
33
+ minProtocol: PROTOCOL_VERSION,
34
+ maxProtocol: PROTOCOL_VERSION,
35
+ });
36
+ this._helloOk = helloOk;
37
+ this.reconnectAttempt = 0;
38
+ resolve(helloOk);
39
+ }
40
+ catch (err) {
41
+ reject(err);
42
+ }
43
+ });
44
+ this.ws.on("message", (data) => {
45
+ try {
46
+ const frame = JSON.parse(data.toString());
47
+ if (frame.type === "response" && frame.id) {
48
+ const pending = this.pendingRequests.get(frame.id);
49
+ if (pending) {
50
+ this.pendingRequests.delete(frame.id);
51
+ if (frame.error) {
52
+ const err = frame.error;
53
+ pending.reject(new Error(err.message ?? "RPC error"));
54
+ }
55
+ else {
56
+ pending.resolve(frame.result);
57
+ }
58
+ }
59
+ }
60
+ else if (frame.type === "event") {
61
+ this.options.onEvent(frame);
62
+ }
63
+ }
64
+ catch {
65
+ this.options.logger?.warn("Malformed frame:", data.toString());
66
+ }
67
+ });
68
+ this.ws.on("close", () => {
69
+ this.options.onDisconnect();
70
+ if (!this.closed)
71
+ this.scheduleReconnect();
72
+ });
73
+ this.ws.on("error", () => {
74
+ // error is followed by close
75
+ });
76
+ });
77
+ }
78
+ async sendRpc(method, params) {
79
+ const attempt = () => new Promise((resolve, reject) => {
80
+ const id = `rpc-${++this.requestCounter}`;
81
+ const frame = {
82
+ jsonrpc: "2.0",
83
+ type: "request",
84
+ id,
85
+ method,
86
+ params,
87
+ };
88
+ this.pendingRequests.set(id, { resolve, reject });
89
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
90
+ this.pendingRequests.delete(id);
91
+ reject(new Error("WebSocket not connected"));
92
+ return;
93
+ }
94
+ this.ws.send(JSON.stringify(frame));
95
+ setTimeout(() => {
96
+ if (this.pendingRequests.has(id)) {
97
+ this.pendingRequests.delete(id);
98
+ reject(new Error(`RPC timeout: ${method}`));
99
+ }
100
+ }, 30_000);
101
+ });
102
+ try {
103
+ return await attempt();
104
+ }
105
+ catch (err) {
106
+ if (err instanceof Error &&
107
+ err.message.startsWith("RPC timeout:") &&
108
+ method !== "auth/connect") {
109
+ return attempt();
110
+ }
111
+ throw err;
112
+ }
113
+ }
114
+ /** Close the socket permanently (no reconnection). */
115
+ close() {
116
+ this.closed = true;
117
+ this.ws?.close();
118
+ }
119
+ /** Close the socket without marking as permanently closed, triggering reconnection. */
120
+ disconnect() {
121
+ this.ws?.close();
122
+ }
123
+ scheduleReconnect() {
124
+ const baseDelay = Math.min(1000 * 2 ** this.reconnectAttempt, this.maxReconnectDelay);
125
+ const jitter = baseDelay * (0.5 + Math.random() * 0.5);
126
+ this.reconnectAttempt++;
127
+ setTimeout(async () => {
128
+ try {
129
+ const helloOk = await this.connect();
130
+ this.options.onReconnect(helloOk);
131
+ }
132
+ catch {
133
+ // connect failed, will retry on close event
134
+ }
135
+ }, jitter);
136
+ }
137
+ }
138
+ //# sourceMappingURL=ws-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ws-client.js","sourceRoot":"","sources":["../src/ws-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "openclaw-channel",
3
+ "channels": ["moltzap"],
4
+ "configSchema": {
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "properties": {}
8
+ }
9
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@moltzap/openclaw-channel",
3
+ "version": "2026.327.0",
4
+ "description": "OpenClaw channel plugin for MoltZap messaging",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/chughtapan/moltzap"
9
+ },
10
+ "type": "module",
11
+ "files": [
12
+ "dist",
13
+ "!dist/__tests__",
14
+ "!dist/test-utils",
15
+ "openclaw.plugin.json"
16
+ ],
17
+ "main": "./dist/channel.js",
18
+ "types": "./dist/channel.d.ts",
19
+ "exports": {
20
+ ".": "./dist/channel.js",
21
+ "./test-utils": "./src/test-utils/container-core.ts"
22
+ },
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "test": "vitest run",
26
+ "test:integration": "vitest run --config vitest.integration.config.ts"
27
+ },
28
+ "dependencies": {
29
+ "@moltzap/protocol": "workspace:*",
30
+ "ws": "^8.18.0"
31
+ },
32
+ "devDependencies": {
33
+ "@moltzap/server": "workspace:*",
34
+ "@testcontainers/postgresql": "^10.18.0",
35
+ "kysely": "^0.27.0",
36
+ "@types/pg": "^8.11.0",
37
+ "@types/ws": "^8.5.0",
38
+ "openai": "^6.26.0",
39
+ "pg": "^8.13.0",
40
+ "testcontainers": "^10.18.0",
41
+ "typescript": "^5.7.0",
42
+ "vitest": "^3.0.0"
43
+ },
44
+ "peerDependencies": {
45
+ "openclaw": ">=2026.0.0"
46
+ },
47
+ "openclaw": {
48
+ "extensions": [
49
+ "./dist/openclaw-entry.js"
50
+ ]
51
+ }
52
+ }