@omnixal/openclaw-nats-plugin 0.1.14 → 0.1.16
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
|
@@ -15,6 +15,7 @@ export interface GatewayInjectPayload {
|
|
|
15
15
|
export class GatewayClientService extends BaseService implements OnModuleInit, OnModuleDestroy {
|
|
16
16
|
private ws: WebSocket | null = null;
|
|
17
17
|
private connected = false;
|
|
18
|
+
private connectSent = false;
|
|
18
19
|
private reconnectAttempt = 0;
|
|
19
20
|
private reconnectTimer: Timer | null = null;
|
|
20
21
|
private requestId = 0;
|
|
@@ -31,21 +32,21 @@ export class GatewayClientService extends BaseService implements OnModuleInit, O
|
|
|
31
32
|
|
|
32
33
|
private connect(): void {
|
|
33
34
|
try {
|
|
34
|
-
|
|
35
|
-
this.ws = new WebSocket(
|
|
35
|
+
this.connectSent = false;
|
|
36
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
36
37
|
|
|
37
38
|
this.ws.onopen = () => {
|
|
38
|
-
this.logger.info('Gateway WebSocket connected');
|
|
39
39
|
this.reconnectAttempt = 0;
|
|
40
|
-
this.
|
|
40
|
+
this.logger.info('Gateway WebSocket opened, waiting for challenge');
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
this.ws.onmessage = (event) => {
|
|
44
|
-
this.handleMessage(event);
|
|
44
|
+
this.handleMessage(String(event.data));
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
this.ws.onclose = () => {
|
|
48
48
|
this.connected = false;
|
|
49
|
+
this.connectSent = false;
|
|
49
50
|
this.scheduleReconnect();
|
|
50
51
|
};
|
|
51
52
|
|
|
@@ -53,29 +54,79 @@ export class GatewayClientService extends BaseService implements OnModuleInit, O
|
|
|
53
54
|
this.logger.warn('Gateway WebSocket error');
|
|
54
55
|
this.connected = false;
|
|
55
56
|
};
|
|
56
|
-
} catch {
|
|
57
|
-
this.logger.warn('Failed to connect to Gateway WebSocket');
|
|
57
|
+
} catch (err) {
|
|
58
|
+
this.logger.warn('Failed to connect to Gateway WebSocket', err);
|
|
58
59
|
this.scheduleReconnect();
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
private handleMessage(
|
|
63
|
+
private handleMessage(data: string): void {
|
|
64
|
+
let frame: any;
|
|
63
65
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
frame = JSON.parse(data);
|
|
67
|
+
} catch {
|
|
68
|
+
this.logger.warn(`Failed to parse WebSocket message: ${data.slice(0, 200)}`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Server challenge — respond with connect frame
|
|
73
|
+
if (frame.type === 'event' && frame.event === 'connect.challenge') {
|
|
74
|
+
this.logger.debug('Received connect.challenge from server');
|
|
75
|
+
this.sendConnectFrame();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Some gateway versions send an event before challenge; treat any pre-connect event as trigger
|
|
80
|
+
if (!this.connectSent && frame.type === 'event') {
|
|
81
|
+
this.logger.debug('Received event before connect sent, sending connect frame');
|
|
82
|
+
this.sendConnectFrame();
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Successful connect response (hello-ok)
|
|
87
|
+
if (frame.type === 'res' && frame.ok === true) {
|
|
88
|
+
if (frame.payload?.type === 'hello-ok') {
|
|
66
89
|
this.connected = true;
|
|
90
|
+
this.logger.info('OpenClaw handshake complete — connected');
|
|
91
|
+
return;
|
|
67
92
|
}
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
// Regular RPC response — ignore for now
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Error response
|
|
98
|
+
if (frame.type === 'res' && frame.ok === false) {
|
|
99
|
+
this.logger.warn('Gateway RPC error', { id: frame.id, error: frame.error });
|
|
70
100
|
}
|
|
71
101
|
}
|
|
72
102
|
|
|
73
|
-
private
|
|
103
|
+
private sendConnectFrame(): void {
|
|
104
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN || this.connectSent) return;
|
|
105
|
+
this.connectSent = true;
|
|
106
|
+
this.logger.info('Sending connect frame');
|
|
107
|
+
|
|
74
108
|
this.send({
|
|
75
109
|
type: 'req',
|
|
76
|
-
id: ++this.requestId
|
|
110
|
+
id: `connect-${++this.requestId}`,
|
|
77
111
|
method: 'connect',
|
|
78
|
-
params: {
|
|
112
|
+
params: {
|
|
113
|
+
minProtocol: 3,
|
|
114
|
+
maxProtocol: 3,
|
|
115
|
+
client: {
|
|
116
|
+
id: 'nats-sidecar',
|
|
117
|
+
version: '1.0.0',
|
|
118
|
+
platform: 'linux',
|
|
119
|
+
mode: 'backend',
|
|
120
|
+
},
|
|
121
|
+
role: 'operator',
|
|
122
|
+
scopes: ['operator.read'],
|
|
123
|
+
caps: [],
|
|
124
|
+
commands: [],
|
|
125
|
+
permissions: {},
|
|
126
|
+
auth: { token: this.token },
|
|
127
|
+
locale: 'en-US',
|
|
128
|
+
userAgent: 'nats-sidecar/1.0.0',
|
|
129
|
+
},
|
|
79
130
|
});
|
|
80
131
|
}
|
|
81
132
|
|
|
@@ -87,7 +138,7 @@ export class GatewayClientService extends BaseService implements OnModuleInit, O
|
|
|
87
138
|
|
|
88
139
|
private scheduleReconnect(): void {
|
|
89
140
|
if (this.reconnectTimer) return;
|
|
90
|
-
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempt),
|
|
141
|
+
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempt), 30_000);
|
|
91
142
|
this.reconnectAttempt++;
|
|
92
143
|
this.logger.debug(`Reconnecting to Gateway in ${delay}ms (attempt ${this.reconnectAttempt})`);
|
|
93
144
|
this.reconnectTimer = setTimeout(() => {
|
|
@@ -102,7 +153,7 @@ export class GatewayClientService extends BaseService implements OnModuleInit, O
|
|
|
102
153
|
}
|
|
103
154
|
this.send({
|
|
104
155
|
type: 'req',
|
|
105
|
-
id: ++this.requestId
|
|
156
|
+
id: `rpc-${++this.requestId}`,
|
|
106
157
|
method: 'send',
|
|
107
158
|
params: {
|
|
108
159
|
target: payload.target,
|
|
@@ -127,5 +178,6 @@ export class GatewayClientService extends BaseService implements OnModuleInit, O
|
|
|
127
178
|
this.ws = null;
|
|
128
179
|
}
|
|
129
180
|
this.connected = false;
|
|
181
|
+
this.connectSent = false;
|
|
130
182
|
}
|
|
131
183
|
}
|