solana-traderclaw 1.0.146 → 1.0.147
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/dist/index.js +19 -0
- package/lib/status-queries.md +103 -0
- package/package.json +1 -1
- package/skills/solana-trader/workspace/AGENTS.md +18 -0
package/dist/index.js
CHANGED
|
@@ -48,6 +48,7 @@ import { Type } from "@sinclair/typebox";
|
|
|
48
48
|
import kayba, { SpanType } from "@kayba_ai/tracing";
|
|
49
49
|
import * as fs from "fs";
|
|
50
50
|
import * as path from "path";
|
|
51
|
+
import { fileURLToPath } from "node:url";
|
|
51
52
|
import { homedir } from "os";
|
|
52
53
|
|
|
53
54
|
// lib/x-client.mjs
|
|
@@ -802,6 +803,16 @@ function getOrCreateAlphaLifetimeState() {
|
|
|
802
803
|
__solanaTraderAlphaSingletonHolder[SOLANA_TRADER_ALPHA_LIFETIME_SINGLETON_KEY] = fresh;
|
|
803
804
|
return fresh;
|
|
804
805
|
}
|
|
806
|
+
var __solanaTraderStatusQueriesMd = (() => {
|
|
807
|
+
try {
|
|
808
|
+
const distPath = fileURLToPath(import.meta.url);
|
|
809
|
+
const packageRoot = path.dirname(path.dirname(distPath));
|
|
810
|
+
const mdPath = path.join(packageRoot, "lib", "status-queries.md");
|
|
811
|
+
return fs.readFileSync(mdPath, "utf-8");
|
|
812
|
+
} catch {
|
|
813
|
+
return void 0;
|
|
814
|
+
}
|
|
815
|
+
})();
|
|
805
816
|
function __solanaTraderDisposePreviousLifecycle(logger) {
|
|
806
817
|
const prev = __solanaTraderGlobalSingletonHolder[SOLANA_TRADER_LIFECYCLE_SINGLETON_KEY];
|
|
807
818
|
if (!prev) return;
|
|
@@ -4298,6 +4309,14 @@ ${String(params.summary)}
|
|
|
4298
4309
|
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
4310
|
source: "solana-trader:live-queries"
|
|
4300
4311
|
});
|
|
4312
|
+
if (__solanaTraderStatusQueriesMd) {
|
|
4313
|
+
context.bootstrapFiles.push({
|
|
4314
|
+
name: "STATUS_QUERIES.md",
|
|
4315
|
+
path: "STATUS_QUERIES.md",
|
|
4316
|
+
content: __solanaTraderStatusQueriesMd,
|
|
4317
|
+
source: "solana-trader:status-queries"
|
|
4318
|
+
});
|
|
4319
|
+
}
|
|
4301
4320
|
api.logger.info(`[solana-trader] Bootstrap: injected ${context.bootstrapFiles.length} files for agent ${bootAgentId}`);
|
|
4302
4321
|
},
|
|
4303
4322
|
{
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Live status queries — always call the tool, never answer from memory
|
|
2
|
+
|
|
3
|
+
When the user asks any question about **current alpha stream state**, you MUST call the matching plugin tool **on this turn**, then summarize what the tool returned. Do NOT answer from memory, heartbeat history, journal logs, log snippets, or earlier conversation context: alpha counts grow second-by-second and stale answers (especially "none" / "zero") are wrong by default.
|
|
4
|
+
|
|
5
|
+
## Why this rule exists
|
|
6
|
+
|
|
7
|
+
The plugin does NOT log every received alpha signal to the journal (that would be noisy at sustained throughput). Signal counts and the buffer of recent signals live **only inside the running plugin process** and are exposed via these tools. If you don't call the tool, you have no data — you only have the absence of log lines, which is not the same thing.
|
|
8
|
+
|
|
9
|
+
The heartbeat history (`memory/<date>.md`, `MEMORY.md`) only captures signals the agent **personally evaluated** during a heartbeat cycle. It is NOT a record of what the WebSocket received. Using heartbeat history to answer "how many signals" gives a count that is typically much smaller than the real number (because most signals never reach a cycle where the agent processes them).
|
|
10
|
+
|
|
11
|
+
## Alpha question → tool routing
|
|
12
|
+
|
|
13
|
+
When the user's question matches a row in column 1, call the tool(s) in column 2 (always on this turn, before replying), read the response, and answer from that data.
|
|
14
|
+
|
|
15
|
+
| User question (or similar) | Call this tool | What to report back |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| "how many alpha signals have we gotten?" / "are we getting alpha?" / "anything from alpha lately?" | `solana_alpha_signals` (with `unseen: false`) | `stats.messageCount` (LIFETIME — survives re-registers/reconnects), `stats.lifetimeUptimeSeconds`, `stats.lastEventTs`, `subscribed`, `bufferSize` |
|
|
18
|
+
| "what's the alpha stream doing right now?" / "is alpha connected?" / "alpha health?" | `solana_alpha_signals` (with `unseen: false`) | `subscribed`, `stats.reconnectAttempt`, `stats.unhealthyStreak`, `stats.circuitBackoff`, `stats.lastEventTs` (interpret as "Xs ago") |
|
|
19
|
+
| "how many alpha signals in the last hour / today / this week / since Monday?" | `solana_alpha_signals` (live) **AND** `solana_alpha_history` (`days=` covering the window) | Live: `stats.messageCount` since gateway start + signals in `signals[]` within the window. Historical: pings in window from REST. Report both. |
|
|
20
|
+
| "any alpha on `<token>` recently / in the last 24h?" | `solana_alpha_signals` (filter `signals[]` by `tokenAddress`/`tokenSymbol`) **AND** `solana_alpha_history` (`tokenAddress=<addr>&days=N`) | Merge live + historical signals for that token by timestamp. |
|
|
21
|
+
| "what alpha sources are active?" / "which channels are sending signals?" | `solana_alpha_sources` | `sources` array — name, type, count, avgScore per channel |
|
|
22
|
+
| "show me the latest alpha signals" / "new signals?" | `solana_alpha_signals` (with `unseen: false` for full buffer, `unseen: true` only if you intend to consume) | Up to N signals: token, source, kind, signalStage, marketCap, systemScore, ts |
|
|
23
|
+
|
|
24
|
+
## `stats` fields — what to use vs. what to ignore
|
|
25
|
+
|
|
26
|
+
`solana_alpha_signals` returns a `stats` object with both **lifetime** and **per-current-WS** fields. **Always quote the lifetime fields to the user.**
|
|
27
|
+
|
|
28
|
+
USE these for user-facing answers (stable across plugin re-registers and WS reconnects):
|
|
29
|
+
|
|
30
|
+
- `stats.messageCount` — **lifetime** total alpha_signal messages received since the gateway process started.
|
|
31
|
+
- `stats.lifetimeUptimeSeconds` — seconds since the first WebSocket open in this gateway process.
|
|
32
|
+
- `stats.lastEventTs` — wall-clock ms of the most recent signal (lifetime).
|
|
33
|
+
- `stats.firstConnectedAt` — wall-clock ms of the first WS open in this process.
|
|
34
|
+
|
|
35
|
+
DO NOT use as "totals" (they reset on every WS reconnect / plugin re-register, which happens every agent turn — so the numbers are misleading as standalone answers):
|
|
36
|
+
|
|
37
|
+
- `stats.currentWsMessageCount` — messages since the CURRENT WS opened. Useful only for debugging "why is the WS cycling?".
|
|
38
|
+
- `stats.uptimeSeconds` — current WS uptime.
|
|
39
|
+
- `stats.connectedAt` — current WS open ts.
|
|
40
|
+
|
|
41
|
+
## When to also call `solana_alpha_history`
|
|
42
|
+
|
|
43
|
+
The live tool gives you "messages since this gateway process started" and a buffer of ~200 deduped signals. For windows that exceed those:
|
|
44
|
+
|
|
45
|
+
- The asked window predates `stats.firstConnectedAt` (e.g. user asks "last 24h" but gateway started 2h ago).
|
|
46
|
+
- The user asks about a specific date or named window ("yesterday", "since Monday", "last week").
|
|
47
|
+
- The buffer is empty (e.g. just after a gateway restart) but the user is asking about a real time range.
|
|
48
|
+
|
|
49
|
+
…ALSO call `solana_alpha_history` (`days=N` covering the window) and combine the two responses. Tier=enterprise → up to 200 results back ~1 year.
|
|
50
|
+
|
|
51
|
+
## How to answer (template — live-only)
|
|
52
|
+
|
|
53
|
+
After the tool returns, structure your reply like this so the user can verify you queried live data:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Live alpha state (as of <now>):
|
|
57
|
+
- subscribed: <subscribed>
|
|
58
|
+
- lifetime: <stats.messageCount> messages over <stats.lifetimeUptimeSeconds>s (≈ <rate>/min) since gateway start
|
|
59
|
+
- last signal: <stats.lastEventTs as "Xs/Xm ago">
|
|
60
|
+
- buffer (deduped, ≤200): <bufferSize>
|
|
61
|
+
- reconnects: <stats.reconnectAttempt>, unhealthy streak: <stats.unhealthyStreak>
|
|
62
|
+
|
|
63
|
+
Top sources (from `solana_alpha_sources`):
|
|
64
|
+
- <sourceName> (<sourceType>): <count> signals, avg score <avgScore>
|
|
65
|
+
|
|
66
|
+
Sample of latest signals (newest first):
|
|
67
|
+
- <tokenSymbol> (<tokenName>) — <kind>/<signalStage>, MC $<marketCap>, score <systemScore>, from <sourceName>, <ts ago>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## How to answer (template — when window > gateway lifetime)
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Alpha activity (<window>):
|
|
74
|
+
- live (gateway lifetime, <lifetimeUptimeSeconds>s): <messageCount> messages, currently <bufferSize> in buffer
|
|
75
|
+
- historical (`solana_alpha_history` days=<N>): <pings.length> pings in window
|
|
76
|
+
- combined unique: <merged count>
|
|
77
|
+
- subscribed: <bool>, last signal: <ago>
|
|
78
|
+
|
|
79
|
+
Top historical sources / tokens: …
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Common mistakes to avoid
|
|
83
|
+
|
|
84
|
+
- **Don't answer "zero" or "none" without calling the tool.** "I don't see any in the logs / heartbeat history" is wrong — signals are NOT logged per-message and heartbeat history only captures what the agent itself touched.
|
|
85
|
+
- **Don't reuse a count from earlier in the conversation.** The buffer is continuously updated; quote only freshly-fetched numbers.
|
|
86
|
+
- **Don't quote `currentWsMessageCount` or `uptimeSeconds` as "totals".** Those reset every time you (or anyone) interacts with the agent, because each interaction re-registers the plugin. Always use `stats.messageCount` and `stats.lifetimeUptimeSeconds` for user-facing answers.
|
|
87
|
+
- **Don't mix heartbeat history with live tool data without flagging it.** If the user asks "how many in the last hour" and you can only see live state, say so and call `solana_alpha_history` to fill the window.
|
|
88
|
+
- **Don't claim "the stream is offline" from log gaps alone.** Check `subscribed` and `stats.lastEventTs` — a stream can be healthy with low-traffic minutes.
|
|
89
|
+
- **Don't paste raw JSON to the user.** Summarize per the templates above; offer raw JSON only if asked.
|
|
90
|
+
|
|
91
|
+
## When the user does NOT need a tool call
|
|
92
|
+
|
|
93
|
+
These are NOT live-state queries; answer from your knowledge:
|
|
94
|
+
|
|
95
|
+
- "how does the alpha stream work?" (explain the design from `skills/solana-trader/refs/alpha-signals.md` if available)
|
|
96
|
+
- "what's a `ca_drop`?" (definition)
|
|
97
|
+
- "which alpha sources are premium?" (static info from refs)
|
|
98
|
+
|
|
99
|
+
## Related
|
|
100
|
+
|
|
101
|
+
- `HEARTBEAT.md` — per-heartbeat cycle envelope (separate from ad-hoc Q&A).
|
|
102
|
+
- `skills/solana-trader/refs/alpha-signals.md` — full alpha pipeline reference.
|
|
103
|
+
- Tool catalog: `solana_alpha_subscribe`, `solana_alpha_unsubscribe`, `solana_alpha_signals`, `solana_alpha_sources`, `solana_alpha_history`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solana-traderclaw",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.147",
|
|
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",
|
|
@@ -127,3 +127,21 @@ These are permanent directives. They apply every session, every cycle, without e
|
|
|
127
127
|
4. **Always check kill switch before new entries.** Call `solana_killswitch_status()` before any new trade execution. If active, halt immediately — no exceptions, no overrides.
|
|
128
128
|
|
|
129
129
|
5. **Always report every cycle.** Never run a silent heartbeat. Every cycle produces a report: what you scanned, what you found, what you did, what you skipped and why. Crypto is 24/7. Every cycle reports.
|
|
130
|
+
|
|
131
|
+
## Live status questions → ALWAYS call the tool
|
|
132
|
+
|
|
133
|
+
When the user asks about the **current** state of the alpha stream (counts, sources, recent signals, subscription health, or any time window), you MUST call the matching plugin tool **on the same turn** before replying. Do not answer "zero / none / I don't see anything" from memory, heartbeat history, journal logs, or log impressions — signals are not logged per-message; they live only inside the running plugin (live state) and the orchestrator REST (historical) and are surfaced via tools.
|
|
134
|
+
|
|
135
|
+
See `STATUS_QUERIES.md` (auto-injected by the plugin at every register) for the full question → tool routing table, field semantics (lifetime vs. current-WS), and the standard answer template. The short version:
|
|
136
|
+
|
|
137
|
+
| Question shape | Tool(s) to call |
|
|
138
|
+
|---|---|
|
|
139
|
+
| "how many alpha signals / are we getting alpha?" | `solana_alpha_signals` (`unseen: false`) — quote `stats.messageCount` (LIFETIME, survives re-registers) and `stats.lifetimeUptimeSeconds` |
|
|
140
|
+
| "is alpha connected / healthy?" | `solana_alpha_signals` (`unseen: false`) — read `subscribed`, `stats.lastEventTs`, `stats.reconnectAttempt`, `stats.unhealthyStreak`, `stats.circuitBackoff` |
|
|
141
|
+
| "how many in last hour / today / since `<day>`?" / "any alpha on `<token>` in 24h?" | `solana_alpha_signals` (live) **AND** `solana_alpha_history` (`days=N` covering the window, `tokenAddress=` when filtering) |
|
|
142
|
+
| "which alpha sources / channels?" | `solana_alpha_sources` |
|
|
143
|
+
| "latest / new alpha signals?" | `solana_alpha_signals` (with or without `unseen: true` depending on intent) |
|
|
144
|
+
|
|
145
|
+
Field reminder: use `stats.messageCount` and `stats.lifetimeUptimeSeconds` as the headline numbers. Do NOT quote `stats.currentWsMessageCount` or `stats.uptimeSeconds` as "totals" — they reset on every plugin re-register (every agent turn / Telegram message).
|
|
146
|
+
|
|
147
|
+
This rule applies to all sessions — direct chats, Telegram, anywhere the user asks. It overrides the heartbeat-cycle envelope: ad-hoc live-state questions are NOT subject to the "minimal per-cycle calls" cap.
|