solana-traderclaw 1.0.145 → 1.0.146
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.
|
@@ -141,12 +141,19 @@ var AlphaStreamManager = class {
|
|
|
141
141
|
return this.subscribed && this.ws !== null && this.ws.readyState === 1;
|
|
142
142
|
}
|
|
143
143
|
getStats() {
|
|
144
|
+
const ls = this.config.lifetimeState;
|
|
145
|
+
const lifetimeMessageCount = ls ? ls.lifetimeMessageCount : this.messageCount;
|
|
146
|
+
const firstConnectedAt = ls && ls.firstConnectedAt > 0 ? ls.firstConnectedAt : this.connectedAt;
|
|
147
|
+
const lifetimeLastEventTs = ls && ls.lifetimeLastEventTs > 0 ? ls.lifetimeLastEventTs : this.lastEventTs;
|
|
144
148
|
return {
|
|
145
149
|
subscribed: this.isSubscribed(),
|
|
146
|
-
messageCount:
|
|
147
|
-
|
|
150
|
+
messageCount: lifetimeMessageCount,
|
|
151
|
+
currentWsMessageCount: this.messageCount,
|
|
152
|
+
lastEventTs: lifetimeLastEventTs,
|
|
148
153
|
connectedAt: this.connectedAt,
|
|
154
|
+
firstConnectedAt,
|
|
149
155
|
uptimeSeconds: this.connectedAt ? Math.floor((Date.now() - this.connectedAt) / 1e3) : 0,
|
|
156
|
+
lifetimeUptimeSeconds: firstConnectedAt ? Math.floor((Date.now() - firstConnectedAt) / 1e3) : 0,
|
|
150
157
|
reconnectAttempt: this.reconnectAttempt,
|
|
151
158
|
unhealthyStreak: this.unhealthyStreak,
|
|
152
159
|
circuitBackoff: this.unhealthyStreak >= CIRCUIT_UNHEALTHY_THRESHOLD
|
|
@@ -200,6 +207,9 @@ var AlphaStreamManager = class {
|
|
|
200
207
|
this.ws.on("open", () => {
|
|
201
208
|
clearTimeout(connectTimeout);
|
|
202
209
|
this.connectedAt = Date.now();
|
|
210
|
+
if (this.config.lifetimeState && this.config.lifetimeState.firstConnectedAt === 0) {
|
|
211
|
+
this.config.lifetimeState.firstConnectedAt = this.connectedAt;
|
|
212
|
+
}
|
|
203
213
|
this.reconnectAttempt = 0;
|
|
204
214
|
this.log("info", "WebSocket connected, waiting for server handshake...");
|
|
205
215
|
pingInterval = setInterval(() => {
|
|
@@ -286,6 +296,10 @@ var AlphaStreamManager = class {
|
|
|
286
296
|
case "alpha_signal": {
|
|
287
297
|
this.messageCount++;
|
|
288
298
|
this.lastEventTs = Date.now();
|
|
299
|
+
if (this.config.lifetimeState) {
|
|
300
|
+
this.config.lifetimeState.lifetimeMessageCount++;
|
|
301
|
+
this.config.lifetimeState.lifetimeLastEventTs = this.lastEventTs;
|
|
302
|
+
}
|
|
289
303
|
const data = msg.data;
|
|
290
304
|
if (data) {
|
|
291
305
|
const signal = {
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "./chunk-3UQIQJPQ.js";
|
|
20
20
|
import {
|
|
21
21
|
AlphaStreamManager
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-GX4HA22L.js";
|
|
23
23
|
import {
|
|
24
24
|
BitqueryStreamManager
|
|
25
25
|
} from "./chunk-S2DLZKMQ.js";
|
|
@@ -777,6 +777,31 @@ var SOLANA_TRADER_LIFECYCLE_SINGLETON_KEY = Symbol.for(
|
|
|
777
777
|
"openclaw.solana-trader.lifecycle.v1"
|
|
778
778
|
);
|
|
779
779
|
var __solanaTraderGlobalSingletonHolder = globalThis;
|
|
780
|
+
var SOLANA_TRADER_ALPHA_BUFFER_SINGLETON_KEY = Symbol.for(
|
|
781
|
+
"openclaw.solana-trader.alpha-buffer.v1"
|
|
782
|
+
);
|
|
783
|
+
var SOLANA_TRADER_ALPHA_LIFETIME_SINGLETON_KEY = Symbol.for(
|
|
784
|
+
"openclaw.solana-trader.alpha-lifetime.v1"
|
|
785
|
+
);
|
|
786
|
+
var __solanaTraderAlphaSingletonHolder = globalThis;
|
|
787
|
+
function getOrCreateAlphaBuffer() {
|
|
788
|
+
const existing = __solanaTraderAlphaSingletonHolder[SOLANA_TRADER_ALPHA_BUFFER_SINGLETON_KEY];
|
|
789
|
+
if (existing) return existing;
|
|
790
|
+
const fresh = new AlphaBuffer();
|
|
791
|
+
__solanaTraderAlphaSingletonHolder[SOLANA_TRADER_ALPHA_BUFFER_SINGLETON_KEY] = fresh;
|
|
792
|
+
return fresh;
|
|
793
|
+
}
|
|
794
|
+
function getOrCreateAlphaLifetimeState() {
|
|
795
|
+
const existing = __solanaTraderAlphaSingletonHolder[SOLANA_TRADER_ALPHA_LIFETIME_SINGLETON_KEY];
|
|
796
|
+
if (existing) return existing;
|
|
797
|
+
const fresh = {
|
|
798
|
+
lifetimeMessageCount: 0,
|
|
799
|
+
firstConnectedAt: 0,
|
|
800
|
+
lifetimeLastEventTs: 0
|
|
801
|
+
};
|
|
802
|
+
__solanaTraderAlphaSingletonHolder[SOLANA_TRADER_ALPHA_LIFETIME_SINGLETON_KEY] = fresh;
|
|
803
|
+
return fresh;
|
|
804
|
+
}
|
|
780
805
|
function __solanaTraderDisposePreviousLifecycle(logger) {
|
|
781
806
|
const prev = __solanaTraderGlobalSingletonHolder[SOLANA_TRADER_LIFECYCLE_SINGLETON_KEY];
|
|
782
807
|
if (!prev) return;
|
|
@@ -2572,11 +2597,13 @@ ${notes}
|
|
|
2572
2597
|
async () => get("/api/agents/active")
|
|
2573
2598
|
)
|
|
2574
2599
|
});
|
|
2575
|
-
const alphaBuffer =
|
|
2600
|
+
const alphaBuffer = getOrCreateAlphaBuffer();
|
|
2601
|
+
const alphaLifetimeState = getOrCreateAlphaLifetimeState();
|
|
2576
2602
|
const alphaStreamManager = new AlphaStreamManager({
|
|
2577
2603
|
wsUrl: orchestratorUrl.replace(/^http/, "ws").replace(/\/$/, "") + "/ws",
|
|
2578
2604
|
getAccessToken: () => sessionManager.getAccessToken(),
|
|
2579
2605
|
buffer: alphaBuffer,
|
|
2606
|
+
lifetimeState: alphaLifetimeState,
|
|
2580
2607
|
agentId: config.agentId,
|
|
2581
2608
|
logger: {
|
|
2582
2609
|
info: (msg) => api.logger.info(`[solana-trader] ${msg}`),
|
|
@@ -2799,7 +2826,7 @@ ${notes}
|
|
|
2799
2826
|
});
|
|
2800
2827
|
api.registerTool({
|
|
2801
2828
|
name: "solana_alpha_signals",
|
|
2802
|
-
description: "
|
|
2829
|
+
description: "Read the live alpha-stream state and buffered signals from the running plugin. **Single source of truth** for any 'how many alpha signals / are we getting alpha / is alpha connected / latest signals' question \u2014 call it on the same turn. Signals are NOT logged per-message, so the journal/heartbeat-history will look empty; only this tool returns the real count.\n\nReturned shape: { signals[], count, bufferSize, subscribed, stats }.\n\nHEADLINE FIELDS for live status answers:\n - stats.messageCount = total alpha_signal messages this gateway process has received (survives plugin re-registers and WS reconnects). Use this for 'how many signals so far' answers.\n - stats.lifetimeUptimeSeconds = seconds since the first WS connect in this gateway process. Divide messageCount/lifetimeUptimeSeconds to get rate.\n - stats.lastEventTs = wall-clock ms of the most recent alpha_signal (lifetime).\n - subscribed = current WS is in subscribed state.\n - stats.reconnectAttempt, stats.unhealthyStreak, stats.circuitBackoff = health signals.\n\nDebug-only fields (do NOT report to users as 'totals'):\n - stats.currentWsMessageCount = messages since the CURRENT WS connect (resets on every reconnect; misleading as a 'total').\n - stats.uptimeSeconds = uptime of the current WS connect.\n - stats.connectedAt = ts of the current WS open.\n\nFor windows beyond what bufferSize covers (\u2248200 signals), or after a gateway restart wiped the lifetime counters, fall through to `solana_alpha_history` (REST, tier=enterprise \u2192 up to 200 results, last 12+ months).\n\nParams: pass unseen:false when the user is asking about overall state (don't mutate _seen). Pass unseen:true (default) only during heartbeat polling to mark and consume new signals. Use minScore to filter low-quality. Returns signals sorted by ingestion time (newest last).",
|
|
2803
2830
|
parameters: Type.Object({
|
|
2804
2831
|
minScore: Type.Optional(Type.Number({ description: "Minimum systemScore threshold (0-100). Signals below this are excluded." })),
|
|
2805
2832
|
chain: Type.Optional(Type.String({ description: "Filter by chain (e.g., 'solana'). BSC is already filtered at ingestion." })),
|
|
@@ -2824,7 +2851,7 @@ ${notes}
|
|
|
2824
2851
|
});
|
|
2825
2852
|
api.registerTool({
|
|
2826
2853
|
name: "solana_alpha_history",
|
|
2827
|
-
description: "Query historical alpha signal data via the
|
|
2854
|
+
description: "Query historical alpha signal data via the orchestrator REST API (GET /api/pings). Use this whenever the user asks about an ALPHA window that extends beyond what `solana_alpha_signals` can cover, e.g.:\n - 'how many alpha signals in the last hour / today / this week / since Monday'\n - 'any alpha on <token> in the last 24h'\n - 'PAIN/$X signals from yesterday'\n - any time the live buffer is empty or just reconnected but the user is asking about a real time window.\n\nReturns up to 1 year of stored signals. Tier-gated by your account (starter=10, pro=50, enterprise=200 results). Combine with `solana_alpha_signals` (live state) to answer 'we've received N signals lifetime in this gateway, plus M historical in the window you asked about'.\n\nParams: tokenAddress, channelId, limit, days (lookback window). 99.99% of tokens are dead but source patterns are invaluable.",
|
|
2828
2855
|
parameters: Type.Object({
|
|
2829
2856
|
tokenAddress: Type.Optional(Type.String({ description: "Filter by token mint address" })),
|
|
2830
2857
|
channelId: Type.Optional(Type.String({ description: "Filter by source channel ID" })),
|
|
@@ -2848,7 +2875,7 @@ ${notes}
|
|
|
2848
2875
|
});
|
|
2849
2876
|
api.registerTool({
|
|
2850
2877
|
name: "solana_alpha_sources",
|
|
2851
|
-
description: "Get per-source statistics from the alpha signal buffer \u2014 signal count, average systemScore, and source type for each channel.
|
|
2878
|
+
description: "Get per-source statistics from the alpha signal buffer \u2014 signal count, average systemScore, and source type for each channel. Call this when the user asks 'which alpha sources / channels are active', 'where are signals coming from', or any breakdown-by-source question. Always live; never answer source breakdowns from memory. Use also for quick reputation checks during signal processing.",
|
|
2852
2879
|
parameters: Type.Object({}),
|
|
2853
2880
|
execute: wrapExecute("solana_alpha_sources", async () => ({
|
|
2854
2881
|
sources: alphaBuffer.getSourceStatsAll(),
|
|
@@ -4265,6 +4292,12 @@ ${String(params.summary)}
|
|
|
4265
4292
|
content: entitlementMd,
|
|
4266
4293
|
source: "solana-trader:entitlements-digest"
|
|
4267
4294
|
});
|
|
4295
|
+
context.bootstrapFiles.push({
|
|
4296
|
+
name: "live-queries.md",
|
|
4297
|
+
path: "live-queries.md",
|
|
4298
|
+
content: "# Live alpha status queries \u2014 always call the tool\n\nWhen the user asks anything about CURRENT alpha activity, call the matching tool **on this turn**. Do NOT answer from memory, heartbeat history, journal logs, or earlier turn context \u2014 alpha signals are not journalled per-message, so 'I don't see any / 0' is wrong by default.\n\n## Routing\n\n| User question shape | Tool(s) to call | Key fields in response |\n|---|---|---|\n| how many alpha signals / are we getting alpha / activity since gateway start | `solana_alpha_signals` (unseen:false) | stats.messageCount, stats.lifetimeUptimeSeconds, stats.lastEventTs, subscribed, bufferSize |\n| is alpha connected / healthy / stream status | `solana_alpha_signals` (unseen:false) | subscribed, stats.reconnectAttempt, stats.unhealthyStreak, stats.circuitBackoff, stats.lastEventTs |\n| how many alpha signals in last hour / today / this week / since <day> | `solana_alpha_signals` (live state) **AND** `solana_alpha_history` (days=\u2026 or compute from window) | live: stats.messageCount + bufferSize; historical: pings[] in window |\n| any alpha on token <X> (recent / historical) | `solana_alpha_signals` for in-buffer signals, then `solana_alpha_history` (tokenAddress=X, days=N) for older | both responses merged by ts |\n| what alpha sources / channels are active | `solana_alpha_sources` | sources[] (name, type, count, avgScore) |\n| latest signals / new signals | `solana_alpha_signals` (unseen:false) | signals[] sorted newest last |\n\n## Field meanings \u2014 IMPORTANT\n\n`solana_alpha_signals` returns `stats` with both lifetime and current-WS fields. Use LIFETIME fields for user-facing answers:\n\n- `stats.messageCount` = **lifetime** total alpha_signal messages received since the gateway process started. Survives plugin re-registers and WS reconnects. **This is the headline number.**\n- `stats.lifetimeUptimeSeconds` = seconds since the first WS open in this process.\n- `stats.lastEventTs` = wall-clock ms of the most recent signal (lifetime).\n- `stats.firstConnectedAt` = wall-clock ms of the first WS open in this process.\n\nDebug-only (do NOT report these as 'totals' \u2014 they reset on every WS reconnect / plugin re-register):\n\n- `stats.currentWsMessageCount` \u2014 messages since the current WS opened.\n- `stats.uptimeSeconds` \u2014 current WS uptime.\n- `stats.connectedAt` \u2014 current WS open ts.\n\n## When to also call `solana_alpha_history`\n\nCall `solana_alpha_history` in addition to `solana_alpha_signals` whenever the user's window pre-dates the current gateway-process lifetime (e.g. `stats.lifetimeUptimeSeconds` is shorter than the asked window, or `stats.messageCount` is 0 because the gateway just restarted). Tier=enterprise returns up to 200 pings, up to ~1 year back.\n\n## Reply template (live-only)\n\n```\nLive alpha state:\n- subscribed: <bool>\n- lifetime: <messageCount> messages over <lifetimeUptimeSeconds>s (\u2248 <rate>/min) since gateway start\n- last signal: <Xs/Xm ago> (lastEventTs)\n- buffer (deduped): <bufferSize>\n- reconnects: <reconnectAttempt>, unhealthy streak: <unhealthyStreak>\n```\n\n## Reply template (with historical window, e.g. 'last hour')\n\n```\nAlpha activity (<window>):\n- live (gateway lifetime): <messageCount> messages over <lifetimeUptimeSeconds>s\n- historical (`solana_alpha_history` days=<N>): <pings.length> pings\n- combined unique within <window>: <merged count>\n- subscribed: <bool>, last signal: <ago>\n```\n\nThis routing overrides any heartbeat-cycle 'minimal calls' cap: ad-hoc user status questions are NOT subject to per-cycle envelopes.\n",
|
|
4299
|
+
source: "solana-trader:live-queries"
|
|
4300
|
+
});
|
|
4268
4301
|
api.logger.info(`[solana-trader] Bootstrap: injected ${context.bootstrapFiles.length} files for agent ${bootAgentId}`);
|
|
4269
4302
|
},
|
|
4270
4303
|
{
|
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.146",
|
|
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",
|