solana-traderclaw 1.0.124 → 1.0.126
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.
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// src/alpha-ws.ts
|
|
2
|
-
var
|
|
2
|
+
var RECONNECT_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
3
3
|
var PING_INTERVAL_MS = 3e4;
|
|
4
4
|
var PONG_TIMEOUT_MS = 1e4;
|
|
5
|
+
var CIRCUIT_UNHEALTHY_THRESHOLD = 12;
|
|
6
|
+
var CIRCUIT_BACKOFF_MS = 3e5;
|
|
7
|
+
var ERROR_LOG_THROTTLE_MS = 6e4;
|
|
5
8
|
var ALPHA_INGESTION_STALE_MS = 20 * 60 * 1e3;
|
|
6
9
|
var ALPHA_STALE_GRACE_AFTER_CONNECT_MS = 3 * 60 * 1e3;
|
|
7
10
|
var AlphaStreamManager = class {
|
|
@@ -10,6 +13,8 @@ var AlphaStreamManager = class {
|
|
|
10
13
|
subscribed = false;
|
|
11
14
|
authenticated = false;
|
|
12
15
|
reconnectAttempt = 0;
|
|
16
|
+
/** Closes where we were not in subscribed state (e.g. handshake failures) — drives circuit backoff. */
|
|
17
|
+
unhealthyStreak = 0;
|
|
13
18
|
reconnectTimer = null;
|
|
14
19
|
intentionalClose = false;
|
|
15
20
|
messageCount = 0;
|
|
@@ -18,6 +23,7 @@ var AlphaStreamManager = class {
|
|
|
18
23
|
tier = "";
|
|
19
24
|
premiumAccess = false;
|
|
20
25
|
currentAccessToken = "";
|
|
26
|
+
lastErrorLogAt = /* @__PURE__ */ new Map();
|
|
21
27
|
constructor(config) {
|
|
22
28
|
this.config = config;
|
|
23
29
|
}
|
|
@@ -104,6 +110,8 @@ var AlphaStreamManager = class {
|
|
|
104
110
|
async unsubscribe() {
|
|
105
111
|
this.intentionalClose = true;
|
|
106
112
|
this.subscribed = false;
|
|
113
|
+
this.unhealthyStreak = 0;
|
|
114
|
+
this.reconnectAttempt = 0;
|
|
107
115
|
if (this.reconnectTimer) {
|
|
108
116
|
clearTimeout(this.reconnectTimer);
|
|
109
117
|
this.reconnectTimer = null;
|
|
@@ -138,7 +146,10 @@ var AlphaStreamManager = class {
|
|
|
138
146
|
messageCount: this.messageCount,
|
|
139
147
|
lastEventTs: this.lastEventTs,
|
|
140
148
|
connectedAt: this.connectedAt,
|
|
141
|
-
uptimeSeconds: this.connectedAt ? Math.floor((Date.now() - this.connectedAt) / 1e3) : 0
|
|
149
|
+
uptimeSeconds: this.connectedAt ? Math.floor((Date.now() - this.connectedAt) / 1e3) : 0,
|
|
150
|
+
reconnectAttempt: this.reconnectAttempt,
|
|
151
|
+
unhealthyStreak: this.unhealthyStreak,
|
|
152
|
+
circuitBackoff: this.unhealthyStreak >= CIRCUIT_UNHEALTHY_THRESHOLD
|
|
142
153
|
};
|
|
143
154
|
}
|
|
144
155
|
sendAlphaSubscribe() {
|
|
@@ -221,16 +232,22 @@ var AlphaStreamManager = class {
|
|
|
221
232
|
this.ws.on("close", () => {
|
|
222
233
|
clearTimeout(connectTimeout);
|
|
223
234
|
clearKeepalive();
|
|
235
|
+
const wasHealthy = this.subscribed;
|
|
224
236
|
this.subscribed = false;
|
|
225
237
|
this.authenticated = false;
|
|
226
238
|
this.log("info", "WebSocket closed");
|
|
227
239
|
if (!this.intentionalClose) {
|
|
240
|
+
if (wasHealthy) {
|
|
241
|
+
this.unhealthyStreak = 0;
|
|
242
|
+
} else {
|
|
243
|
+
this.unhealthyStreak++;
|
|
244
|
+
}
|
|
228
245
|
this.scheduleReconnect();
|
|
229
246
|
}
|
|
230
247
|
});
|
|
231
248
|
this.ws.on("error", (err) => {
|
|
232
249
|
clearTimeout(connectTimeout);
|
|
233
|
-
this.
|
|
250
|
+
this.logThrottledError(`ws:${err.message}`, `WebSocket error: ${err.message}`);
|
|
234
251
|
if (this.ws && this.ws.readyState !== 1) {
|
|
235
252
|
reject(err);
|
|
236
253
|
}
|
|
@@ -257,6 +274,7 @@ var AlphaStreamManager = class {
|
|
|
257
274
|
break;
|
|
258
275
|
case "alpha_stream_subscribed":
|
|
259
276
|
this.subscribed = true;
|
|
277
|
+
this.unhealthyStreak = 0;
|
|
260
278
|
this.tier = msg.tier || this.tier;
|
|
261
279
|
this.premiumAccess = msg.premiumAccess || false;
|
|
262
280
|
this.log("info", `Subscribed to alpha stream: tier=${this.tier}, premium=${this.premiumAccess}`);
|
|
@@ -308,18 +326,46 @@ var AlphaStreamManager = class {
|
|
|
308
326
|
}
|
|
309
327
|
scheduleReconnect() {
|
|
310
328
|
if (this.intentionalClose) return;
|
|
311
|
-
|
|
329
|
+
if (this.reconnectTimer) {
|
|
330
|
+
clearTimeout(this.reconnectTimer);
|
|
331
|
+
this.reconnectTimer = null;
|
|
332
|
+
}
|
|
333
|
+
const idx = Math.min(this.reconnectAttempt, RECONNECT_DELAYS_MS.length - 1);
|
|
334
|
+
let delay = RECONNECT_DELAYS_MS[idx];
|
|
335
|
+
if (this.unhealthyStreak >= CIRCUIT_UNHEALTHY_THRESHOLD) {
|
|
336
|
+
delay = Math.max(delay, CIRCUIT_BACKOFF_MS);
|
|
337
|
+
}
|
|
312
338
|
this.reconnectAttempt++;
|
|
313
|
-
|
|
339
|
+
if (this.shouldLogReconnectPlan()) {
|
|
340
|
+
const circuitNote = this.unhealthyStreak >= CIRCUIT_UNHEALTHY_THRESHOLD ? ` (circuit: ${Math.round(CIRCUIT_BACKOFF_MS / 1e3)}s backoff \u2014 orchestrator path unhealthy)` : "";
|
|
341
|
+
this.log("info", `Reconnecting in ${delay}ms (attempt ${this.reconnectAttempt}, unhealthyStreak=${this.unhealthyStreak})${circuitNote}`);
|
|
342
|
+
}
|
|
314
343
|
this.reconnectTimer = setTimeout(async () => {
|
|
344
|
+
this.reconnectTimer = null;
|
|
315
345
|
try {
|
|
316
346
|
await this.connect();
|
|
317
347
|
} catch (err) {
|
|
318
|
-
this.
|
|
319
|
-
|
|
348
|
+
this.logThrottledError(
|
|
349
|
+
"reconnect-failed",
|
|
350
|
+
`Reconnect failed: ${err instanceof Error ? err.message : String(err)}`
|
|
351
|
+
);
|
|
320
352
|
}
|
|
321
353
|
}, delay);
|
|
322
354
|
}
|
|
355
|
+
/** Reduce log spam when wedged (CPU + disk heavy with JSON file logging). */
|
|
356
|
+
shouldLogReconnectPlan() {
|
|
357
|
+
const n = this.reconnectAttempt;
|
|
358
|
+
if (n <= 3) return true;
|
|
359
|
+
if (n <= 30 && n % 5 === 0) return true;
|
|
360
|
+
return n % 25 === 0;
|
|
361
|
+
}
|
|
362
|
+
logThrottledError(key, msg) {
|
|
363
|
+
const now = Date.now();
|
|
364
|
+
const last = this.lastErrorLogAt.get(key) ?? 0;
|
|
365
|
+
if (now - last < ERROR_LOG_THROTTLE_MS) return;
|
|
366
|
+
this.lastErrorLogAt.set(key, now);
|
|
367
|
+
this.log("error", msg);
|
|
368
|
+
}
|
|
323
369
|
log(level, msg) {
|
|
324
370
|
if (this.config.logger) {
|
|
325
371
|
this.config.logger[level](`[alpha-stream] ${msg}`);
|
package/dist/index.js
CHANGED
package/dist/src/alpha-ws.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solana-traderclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.126",
|
|
4
4
|
"description": "TraderClaw V1-Upgraded — Solana trading for OpenClaw with intelligence lab, tool envelopes, prompt scrubbing, read-only X social intel, and split skill docs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|