solana-traderclaw 1.0.99 → 1.0.101
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/README.md +4 -2
- package/dist/{chunk-ATWB7K63.js → chunk-JVQNXWBW.js} +66 -2
- package/dist/chunk-R24UDHQG.js +21 -0
- package/dist/index.js +76 -7
- package/dist/src/alpha-ws.js +5 -1
- package/dist/src/gateway-config-sync.js +8 -0
- package/package.json +2 -1
- package/skills/solana-trader/HEARTBEAT.md +1 -1
- package/skills/solana-trader/SKILL.md +1 -1
- package/skills/solana-trader/workspace/TOOLS.md +1 -1
package/README.md
CHANGED
|
@@ -113,6 +113,8 @@ Run mandatory startup sequence and report pass/fail for each:
|
|
|
113
113
|
6) solana_killswitch_status
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
+
If alpha signals stop but the gateway looks healthy, call `solana_alpha_subscribe({ force: true })` or inspect `solana_runtime_status` (alpha `stats.lastEventTs`, `subscribed`). The plugin also runs a background watchdog for stale ingestion and gateway forward probes.
|
|
117
|
+
|
|
116
118
|
### Non-interactive setup
|
|
117
119
|
|
|
118
120
|
```bash
|
|
@@ -379,7 +381,7 @@ Pay-as-you-go or Basic tier is required for the read-only social intel tools.
|
|
|
379
381
|
### Alpha Signal Processing
|
|
380
382
|
| Tool | Description |
|
|
381
383
|
|------|-------------|
|
|
382
|
-
| `solana_alpha_subscribe` | Subscribe to alpha
|
|
384
|
+
| `solana_alpha_subscribe` | Subscribe to alpha WebSocket feed (`force: true` reconnects if ingestion stalls) |
|
|
383
385
|
| `solana_alpha_unsubscribe` | Unsubscribe from alpha feed |
|
|
384
386
|
| `solana_alpha_signals` | Retrieve buffered alpha signals |
|
|
385
387
|
| `solana_alpha_history` | Query historical alpha signals |
|
|
@@ -413,7 +415,7 @@ Pay-as-you-go or Basic tier is required for the read-only social intel tools.
|
|
|
413
415
|
| `solana_gateway_forward_probe` | Probe gateway forwarding connectivity |
|
|
414
416
|
| `solana_agent_sessions` | View agent session diagnostics |
|
|
415
417
|
| `solana_startup_gate` | Run startup gate sequence |
|
|
416
|
-
| `solana_runtime_status` |
|
|
418
|
+
| `solana_runtime_status` | Runtime diagnostics (startup gate, alpha stats / `lastEventTs`, last forward probe) |
|
|
417
419
|
|
|
418
420
|
### Local Durable State
|
|
419
421
|
| Tool | Description |
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
var RECONNECT_DELAYS = [1e3, 2e3, 4e3, 8e3, 16e3, 3e4];
|
|
3
3
|
var PING_INTERVAL_MS = 3e4;
|
|
4
4
|
var PONG_TIMEOUT_MS = 1e4;
|
|
5
|
+
var ALPHA_INGESTION_STALE_MS = 20 * 60 * 1e3;
|
|
6
|
+
var ALPHA_STALE_GRACE_AFTER_CONNECT_MS = 3 * 60 * 1e3;
|
|
5
7
|
var AlphaStreamManager = class {
|
|
6
8
|
config;
|
|
7
9
|
ws = null;
|
|
@@ -19,10 +21,50 @@ var AlphaStreamManager = class {
|
|
|
19
21
|
constructor(config) {
|
|
20
22
|
this.config = config;
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* @param opts.force If true, drop the existing WebSocket (when connected) and subscribe again.
|
|
26
|
+
* Use when the socket looks healthy but alpha_signal delivery may have stalled.
|
|
27
|
+
*/
|
|
28
|
+
async subscribe(opts = {}) {
|
|
29
|
+
const force = Boolean(opts.force);
|
|
30
|
+
if (!force && this.subscribed && this.ws && this.ws.readyState === 1) {
|
|
24
31
|
return { subscribed: true, premiumAccess: this.premiumAccess, tier: this.tier };
|
|
25
32
|
}
|
|
33
|
+
if (force && this.ws) {
|
|
34
|
+
if (this.reconnectTimer) {
|
|
35
|
+
clearTimeout(this.reconnectTimer);
|
|
36
|
+
this.reconnectTimer = null;
|
|
37
|
+
}
|
|
38
|
+
const oldWs = this.ws;
|
|
39
|
+
this.intentionalClose = true;
|
|
40
|
+
this.log("info", "Force subscribe: closing WebSocket for clean reconnect");
|
|
41
|
+
await new Promise((resolve) => {
|
|
42
|
+
if (oldWs.readyState === 3) {
|
|
43
|
+
resolve();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const t = setTimeout(resolve, 5e3);
|
|
47
|
+
oldWs.once("close", () => {
|
|
48
|
+
clearTimeout(t);
|
|
49
|
+
resolve();
|
|
50
|
+
});
|
|
51
|
+
try {
|
|
52
|
+
if (oldWs.readyState === 1 || oldWs.readyState === 0) {
|
|
53
|
+
oldWs.close();
|
|
54
|
+
} else {
|
|
55
|
+
clearTimeout(t);
|
|
56
|
+
resolve();
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
clearTimeout(t);
|
|
60
|
+
resolve();
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
this.ws = null;
|
|
64
|
+
this.subscribed = false;
|
|
65
|
+
this.authenticated = false;
|
|
66
|
+
this.intentionalClose = false;
|
|
67
|
+
}
|
|
26
68
|
this.intentionalClose = false;
|
|
27
69
|
await this.connect();
|
|
28
70
|
return new Promise((resolve, reject) => {
|
|
@@ -39,6 +81,26 @@ var AlphaStreamManager = class {
|
|
|
39
81
|
}, 15e3);
|
|
40
82
|
});
|
|
41
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* True when the socket reports subscribed but no alpha_signal has been received for
|
|
86
|
+
* {@link ALPHA_INGESTION_STALE_MS} (after {@link ALPHA_STALE_GRACE_AFTER_CONNECT_MS}).
|
|
87
|
+
*/
|
|
88
|
+
isIngestionStale(now = Date.now()) {
|
|
89
|
+
if (!this.isSubscribed()) return false;
|
|
90
|
+
const uptime = now - this.connectedAt;
|
|
91
|
+
if (uptime < ALPHA_STALE_GRACE_AFTER_CONNECT_MS) return false;
|
|
92
|
+
const lastActivity = this.lastEventTs > 0 ? this.lastEventTs : this.connectedAt;
|
|
93
|
+
return now - lastActivity >= ALPHA_INGESTION_STALE_MS;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Re-send alpha_stream_subscribe on the existing connection (soft recovery).
|
|
97
|
+
* @returns true if the message was sent
|
|
98
|
+
*/
|
|
99
|
+
resendApplicationSubscribe() {
|
|
100
|
+
if (!this.authenticated || !this.ws || this.ws.readyState !== 1) return false;
|
|
101
|
+
this.sendAlphaSubscribe();
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
42
104
|
async unsubscribe() {
|
|
43
105
|
this.intentionalClose = true;
|
|
44
106
|
this.subscribed = false;
|
|
@@ -266,5 +328,7 @@ var AlphaStreamManager = class {
|
|
|
266
328
|
};
|
|
267
329
|
|
|
268
330
|
export {
|
|
331
|
+
ALPHA_INGESTION_STALE_MS,
|
|
332
|
+
ALPHA_STALE_GRACE_AFTER_CONNECT_MS,
|
|
269
333
|
AlphaStreamManager
|
|
270
334
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/gateway-config-sync.ts
|
|
2
|
+
function normalizeGatewayBaseUrl(url) {
|
|
3
|
+
return String(url || "").trim().replace(/\/+$/, "");
|
|
4
|
+
}
|
|
5
|
+
function shouldSyncGatewayCredentials(localBaseUrl, localToken, active) {
|
|
6
|
+
const gbu = String(localBaseUrl || "").trim();
|
|
7
|
+
const gt = String(localToken || "").trim();
|
|
8
|
+
if (!gbu || !gt || !active) return false;
|
|
9
|
+
const lUrl = normalizeGatewayBaseUrl(gbu);
|
|
10
|
+
const rUrl = normalizeGatewayBaseUrl(String(active.gatewayBaseUrl ?? ""));
|
|
11
|
+
if (lUrl !== rUrl) return true;
|
|
12
|
+
if (typeof active.gatewayToken === "string") {
|
|
13
|
+
return active.gatewayToken.trim() !== gt;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
normalizeGatewayBaseUrl,
|
|
20
|
+
shouldSyncGatewayCredentials
|
|
21
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readRecoverySecretFromDisk
|
|
3
|
+
} from "./chunk-SBYHSJLU.js";
|
|
1
4
|
import {
|
|
2
5
|
SessionManager
|
|
3
6
|
} from "./chunk-VVEKPKW3.js";
|
|
@@ -15,10 +18,13 @@ import {
|
|
|
15
18
|
} from "./chunk-3UQIQJPQ.js";
|
|
16
19
|
import {
|
|
17
20
|
AlphaStreamManager
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-JVQNXWBW.js";
|
|
19
22
|
import {
|
|
20
23
|
BitqueryStreamManager
|
|
21
24
|
} from "./chunk-S2DLZKMQ.js";
|
|
25
|
+
import {
|
|
26
|
+
shouldSyncGatewayCredentials
|
|
27
|
+
} from "./chunk-R24UDHQG.js";
|
|
22
28
|
import {
|
|
23
29
|
orchestratorRequest
|
|
24
30
|
} from "./chunk-6GSGHMUH.js";
|
|
@@ -35,9 +41,6 @@ import {
|
|
|
35
41
|
import {
|
|
36
42
|
scrubUntrustedText
|
|
37
43
|
} from "./chunk-AI6MTHUN.js";
|
|
38
|
-
import {
|
|
39
|
-
readRecoverySecretFromDisk
|
|
40
|
-
} from "./chunk-SBYHSJLU.js";
|
|
41
44
|
|
|
42
45
|
// index.ts
|
|
43
46
|
import { Type } from "@sinclair/typebox";
|
|
@@ -2593,6 +2596,18 @@ ${notes}
|
|
|
2593
2596
|
refreshed = await get("/api/agents/gateway-credentials");
|
|
2594
2597
|
activeCredential = getActiveCredential(refreshed);
|
|
2595
2598
|
}
|
|
2599
|
+
if (activeCredential && autoFixGateway && gbu && gt && shouldSyncGatewayCredentials(gbu, gt, activeCredential)) {
|
|
2600
|
+
const driftBody = {
|
|
2601
|
+
gatewayBaseUrl: gbu,
|
|
2602
|
+
gatewayToken: gt,
|
|
2603
|
+
active: true
|
|
2604
|
+
};
|
|
2605
|
+
if (config.agentId) driftBody.agentId = config.agentId;
|
|
2606
|
+
if (forwardChatId) driftBody.forwardTelegramChatId = forwardChatId;
|
|
2607
|
+
await put("/api/agents/gateway-credentials", driftBody);
|
|
2608
|
+
refreshed = await get("/api/agents/gateway-credentials");
|
|
2609
|
+
activeCredential = getActiveCredential(refreshed);
|
|
2610
|
+
}
|
|
2596
2611
|
gatewayStepOk = Boolean(activeCredential);
|
|
2597
2612
|
if (!gatewayStepOk) throw new Error("Gateway credentials are missing or inactive");
|
|
2598
2613
|
pushStep({
|
|
@@ -2697,10 +2712,13 @@ ${notes}
|
|
|
2697
2712
|
};
|
|
2698
2713
|
api.registerTool({
|
|
2699
2714
|
name: "solana_alpha_subscribe",
|
|
2700
|
-
description: "Subscribe to the SpyFly alpha signal stream via WebSocket. Signals are buffered locally and retrieved with solana_alpha_signals. The startup gate calls this automatically. Optionally set agentId and subscriberType for event-to-agent forwarding.",
|
|
2715
|
+
description: "Subscribe to the SpyFly alpha signal stream via WebSocket. Signals are buffered locally and retrieved with solana_alpha_signals. The startup gate calls this automatically. Optionally set agentId and subscriberType for event-to-agent forwarding. Use force=true to close an existing connection and resubscribe when the socket looks healthy but alpha_signal ingestion has stalled (zombie subscription).",
|
|
2701
2716
|
parameters: Type.Object({
|
|
2702
2717
|
agentId: Type.Optional(Type.String({ description: "Agent ID for event-to-agent forwarding. Uses plugin config agentId as default." })),
|
|
2703
|
-
subscriberType: Type.Optional(Type.String({ description: "Subscriber type: 'agent' or 'client'." }))
|
|
2718
|
+
subscriberType: Type.Optional(Type.String({ description: "Subscriber type: 'agent' or 'client'." })),
|
|
2719
|
+
force: Type.Optional(Type.Boolean({
|
|
2720
|
+
description: "If true, disconnect any existing WebSocket and subscribe again. Use when resubscribe would otherwise be a no-op but signals stopped arriving."
|
|
2721
|
+
}))
|
|
2704
2722
|
}),
|
|
2705
2723
|
execute: wrapExecute("solana_alpha_subscribe", async (_id, params) => {
|
|
2706
2724
|
const effectiveAgentId = params.agentId || config.agentId;
|
|
@@ -2711,7 +2729,7 @@ ${notes}
|
|
|
2711
2729
|
if (effectiveSubscriberType) {
|
|
2712
2730
|
alphaStreamManager.setSubscriberType(effectiveSubscriberType);
|
|
2713
2731
|
}
|
|
2714
|
-
return alphaStreamManager.subscribe();
|
|
2732
|
+
return alphaStreamManager.subscribe({ force: params.force === true });
|
|
2715
2733
|
})
|
|
2716
2734
|
});
|
|
2717
2735
|
api.registerTool({
|
|
@@ -2923,6 +2941,7 @@ ${notes}
|
|
|
2923
2941
|
startupGate: startupGateState,
|
|
2924
2942
|
alphaStream: {
|
|
2925
2943
|
subscribed: alphaStreamManager.isSubscribed(),
|
|
2944
|
+
ingestionStale: alphaStreamManager.isIngestionStale(),
|
|
2926
2945
|
stats: alphaStreamManager.getStats(),
|
|
2927
2946
|
bufferSize: alphaBuffer.getBufferSize()
|
|
2928
2947
|
},
|
|
@@ -4285,8 +4304,16 @@ Context compaction triggered. STATE.md synced from last persisted state. Decisio
|
|
|
4285
4304
|
api.logger.warn(`[solana-trader] Forward probe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4286
4305
|
}
|
|
4287
4306
|
const WATCHDOG_INTERVAL_MS = 9e4;
|
|
4307
|
+
const FORWARD_PROBE_WATCHDOG_MS = 7 * 60 * 1e3;
|
|
4308
|
+
const STARTUP_GATE_AFTER_PROBE_FAIL_COOLDOWN_MS = 10 * 60 * 1e3;
|
|
4309
|
+
let alphaStalePhase = 0;
|
|
4310
|
+
const watchdogStartedAt = Date.now();
|
|
4311
|
+
let lastForwardProbeWatchdogMs = watchdogStartedAt;
|
|
4312
|
+
let lastProbeFailureStartupGateMs = watchdogStartedAt;
|
|
4288
4313
|
const watchdogTimer = setInterval(async () => {
|
|
4314
|
+
const now = Date.now();
|
|
4289
4315
|
if (!alphaStreamManager.isSubscribed()) {
|
|
4316
|
+
alphaStalePhase = 0;
|
|
4290
4317
|
api.logger.warn("[watchdog] Alpha stream not subscribed \u2014 resubscribing...");
|
|
4291
4318
|
try {
|
|
4292
4319
|
await alphaStreamManager.subscribe();
|
|
@@ -4294,6 +4321,32 @@ Context compaction triggered. STATE.md synced from last persisted state. Decisio
|
|
|
4294
4321
|
} catch (err) {
|
|
4295
4322
|
api.logger.error(`[watchdog] Alpha resubscribe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4296
4323
|
}
|
|
4324
|
+
} else if (alphaStreamManager.isIngestionStale(now)) {
|
|
4325
|
+
if (alphaStalePhase === 0) {
|
|
4326
|
+
api.logger.warn("[watchdog] Alpha ingestion stale (no recent alpha_signal) \u2014 resending alpha_stream_subscribe");
|
|
4327
|
+
if (alphaStreamManager.resendApplicationSubscribe()) {
|
|
4328
|
+
alphaStalePhase = 1;
|
|
4329
|
+
} else {
|
|
4330
|
+
try {
|
|
4331
|
+
await alphaStreamManager.subscribe({ force: true });
|
|
4332
|
+
api.logger.info("[watchdog] Alpha force-resubscribe completed (soft send unavailable).");
|
|
4333
|
+
} catch (err) {
|
|
4334
|
+
api.logger.error(`[watchdog] Alpha force-resubscribe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4335
|
+
}
|
|
4336
|
+
alphaStalePhase = 0;
|
|
4337
|
+
}
|
|
4338
|
+
} else {
|
|
4339
|
+
api.logger.warn("[watchdog] Alpha still stale after soft recovery \u2014 forcing WebSocket reconnect");
|
|
4340
|
+
try {
|
|
4341
|
+
await alphaStreamManager.subscribe({ force: true });
|
|
4342
|
+
api.logger.info("[watchdog] Alpha force-resubscribe completed.");
|
|
4343
|
+
} catch (err) {
|
|
4344
|
+
api.logger.error(`[watchdog] Alpha force-resubscribe failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4345
|
+
}
|
|
4346
|
+
alphaStalePhase = 0;
|
|
4347
|
+
}
|
|
4348
|
+
} else {
|
|
4349
|
+
alphaStalePhase = 0;
|
|
4297
4350
|
}
|
|
4298
4351
|
try {
|
|
4299
4352
|
const creds = await get("/api/agents/gateway-credentials");
|
|
@@ -4304,6 +4357,22 @@ Context compaction triggered. STATE.md synced from last persisted state. Decisio
|
|
|
4304
4357
|
} catch (err) {
|
|
4305
4358
|
api.logger.warn(`[watchdog] Gateway credential check failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4306
4359
|
}
|
|
4360
|
+
if (now - lastForwardProbeWatchdogMs >= FORWARD_PROBE_WATCHDOG_MS) {
|
|
4361
|
+
lastForwardProbeWatchdogMs = now;
|
|
4362
|
+
try {
|
|
4363
|
+
const pr = await runForwardProbe({ agentId: config.agentId || "main", source: "watchdog" });
|
|
4364
|
+
if (!Boolean(pr.ok)) {
|
|
4365
|
+
api.logger.warn(`[watchdog] Gateway forward probe failed: ${JSON.stringify(pr)}`);
|
|
4366
|
+
if (now - lastProbeFailureStartupGateMs >= STARTUP_GATE_AFTER_PROBE_FAIL_COOLDOWN_MS) {
|
|
4367
|
+
lastProbeFailureStartupGateMs = now;
|
|
4368
|
+
api.logger.warn("[watchdog] Running startup gate after forward probe failure (cooldown elapsed)");
|
|
4369
|
+
await runStartupGate({ autoFixGateway: true, force: true });
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
} catch (err) {
|
|
4373
|
+
api.logger.warn(`[watchdog] Forward probe error: ${err instanceof Error ? err.message : String(err)}`);
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4307
4376
|
}, WATCHDOG_INTERVAL_MS);
|
|
4308
4377
|
if (watchdogTimer && typeof watchdogTimer === "object" && "unref" in watchdogTimer) {
|
|
4309
4378
|
watchdogTimer.unref();
|
package/dist/src/alpha-ws.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ALPHA_INGESTION_STALE_MS,
|
|
3
|
+
ALPHA_STALE_GRACE_AFTER_CONNECT_MS,
|
|
2
4
|
AlphaStreamManager
|
|
3
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-JVQNXWBW.js";
|
|
4
6
|
export {
|
|
7
|
+
ALPHA_INGESTION_STALE_MS,
|
|
8
|
+
ALPHA_STALE_GRACE_AFTER_CONNECT_MS,
|
|
5
9
|
AlphaStreamManager
|
|
6
10
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solana-traderclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.101",
|
|
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",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "node build.mjs",
|
|
20
|
+
"test": "npm run build && node scripts/gateway-config-sync-selftest.mjs",
|
|
20
21
|
"prepublishOnly": "npm run build",
|
|
21
22
|
"sync-cli": "node scripts/sync-cli-version.mjs",
|
|
22
23
|
"release:patch": "node scripts/release-patch.mjs"
|
|
@@ -60,7 +60,7 @@ Call `solana_scan_launches` for new launches and `solana_scan_hot_pairs` for hot
|
|
|
60
60
|
|
|
61
61
|
## STEP 1.5: ALPHA SIGNALS
|
|
62
62
|
|
|
63
|
-
Call `solana_alpha_signals` to poll the buffer. Score and classify each signal by priority. Check `calledAgainCount` — multiple independent callers on same token = high conviction.
|
|
63
|
+
Call `solana_alpha_signals` to poll the buffer. Score and classify each signal by priority. Check `calledAgainCount` — multiple independent callers on same token = high conviction. If buffer stays empty while live, `solana_runtime_status` then `solana_alpha_subscribe({ force: true })` or unsub+subscribe.
|
|
64
64
|
|
|
65
65
|
**Source trust check (mandatory before acting on any signal):**
|
|
66
66
|
```
|
|
@@ -162,7 +162,7 @@ After startup completes, deliver the welcome ceremony:
|
|
|
162
162
|
|
|
163
163
|
1. `solana_system_status()` — verify orchestrator reachable
|
|
164
164
|
2. `solana_gateway_credentials_get()` — verify gateway registered
|
|
165
|
-
3. `solana_alpha_subscribe({ agentId: "main" })` — start signal stream
|
|
165
|
+
3. `solana_alpha_subscribe({ agentId: "main" })` — start signal stream (`force: true` if the socket looks live but alpha ingestion stalled)
|
|
166
166
|
4. `solana_capital_status()` + `solana_positions()` + `solana_killswitch_status()` — portfolio health
|
|
167
167
|
5. `solana_gateway_forward_probe({ agentId: "main" })` — verify wake path
|
|
168
168
|
|
|
@@ -101,7 +101,7 @@ Every tool has a mandatory trigger — when the trigger condition is met, you MU
|
|
|
101
101
|
### Alpha Signals (5)
|
|
102
102
|
| Tool | Purpose | When to Call |
|
|
103
103
|
|---|---|---|
|
|
104
|
-
| `solana_alpha_subscribe` | Subscribe to alpha stream | Startup sequence; when stream disconnects |
|
|
104
|
+
| `solana_alpha_subscribe` | Subscribe to alpha stream (`force: true` forces reconnect) | Startup sequence; when stream disconnects or ingestion stalls |
|
|
105
105
|
| `solana_alpha_signals` | Poll buffered signals | Step 1.5 every heartbeat |
|
|
106
106
|
| `solana_alpha_history` | Historical signal data | Step 1.5 to check prior calls on a token; Step 7 to check source accuracy after exit |
|
|
107
107
|
| `solana_alpha_sources` | Per-source performance stats | Step 1.5 to check source win rates; `source_reputation_recalc` cron |
|