solana-terminator-skill 4.3.1 → 4.3.7
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/install.js +25 -13
- package/package.json +3 -4
- package/radar.js +103 -66
- package/solana-autonomy.js +21 -1
package/install.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Automates the setup of the Solana skill for the Conway Automaton.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { execSync } from 'child_process';
|
|
9
|
+
import { execSync, spawnSync } from 'child_process';
|
|
10
10
|
import fs from 'fs';
|
|
11
11
|
import path from 'path';
|
|
12
12
|
import { fileURLToPath } from 'url';
|
|
@@ -24,7 +24,7 @@ const ASCII_ART = `
|
|
|
24
24
|
██ ██████ ████████ ████ ████ ██ ████ ██ ███████ ██ ██ ██ ██████
|
|
25
25
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
26
26
|
██ ████████ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██████ ██ ██
|
|
27
|
-
v4.3.
|
|
27
|
+
v4.3.7 - Autonomous Engine
|
|
28
28
|
`;
|
|
29
29
|
|
|
30
30
|
const SKILL_NAME = 'solana-terminator';
|
|
@@ -35,7 +35,7 @@ const TARGET_DIR = path.join(os.homedir(), '.automaton', 'skills', SKILL_NAME);
|
|
|
35
35
|
const args = process.argv.slice(2);
|
|
36
36
|
|
|
37
37
|
if (args.includes('radar')) {
|
|
38
|
-
launchRadar();
|
|
38
|
+
launchRadar(true);
|
|
39
39
|
} else if (args.includes('install')) {
|
|
40
40
|
runInstaller();
|
|
41
41
|
} else {
|
|
@@ -44,11 +44,26 @@ if (args.includes('radar')) {
|
|
|
44
44
|
|
|
45
45
|
// ─── Logic ─────────────────────────────────────────────────────────────
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
function launchRadar(isDirect = false) {
|
|
48
|
+
try {
|
|
49
|
+
const radarPath = path.join(__dirname, 'radar.js');
|
|
50
|
+
|
|
51
|
+
// Spawn independent process with inherited control
|
|
52
|
+
spawnSync('node', [radarPath], {
|
|
53
|
+
stdio: 'inherit',
|
|
54
|
+
shell: true
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// After child process exits, we return here
|
|
58
|
+
if (!isDirect) {
|
|
59
|
+
showMainMenu();
|
|
60
|
+
} else {
|
|
61
|
+
process.exit(0);
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
if (!isDirect) showMainMenu();
|
|
65
|
+
else process.exit(1);
|
|
66
|
+
}
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
// ─── Menu System ────────────────────────────────────────────────────────────
|
|
@@ -98,8 +113,9 @@ function showIdentity() {
|
|
|
98
113
|
import('./solana-autonomy.js').then(async ({ SolanaAutonomy }) => {
|
|
99
114
|
const solana = new SolanaAutonomy();
|
|
100
115
|
const status = await solana.getStatus();
|
|
101
|
-
console.log(`\n✅ AGENT IDENTITY FOUND`);
|
|
116
|
+
console.log(`\n✅ AGENT SOLANA IDENTITY FOUND`);
|
|
102
117
|
console.log(`--------------------------------------------------`);
|
|
118
|
+
console.log(`NETWORK : Solana Mainnet-Beta`);
|
|
103
119
|
console.log(`ADDRESS : ${status.address}`);
|
|
104
120
|
console.log(`SOL : ${status.sol.toFixed(4)}`);
|
|
105
121
|
console.log(`USDC : $${status.usdc.toFixed(2)}`);
|
|
@@ -129,7 +145,6 @@ async function runInstaller() {
|
|
|
129
145
|
console.log(`🤖 Solana Terminator Skill — Initializing...\n`);
|
|
130
146
|
|
|
131
147
|
try {
|
|
132
|
-
// 1. Create target directory
|
|
133
148
|
if (!fs.existsSync(TARGET_DIR)) {
|
|
134
149
|
console.log(`[1/3] Creating directory: ${TARGET_DIR}`);
|
|
135
150
|
fs.mkdirSync(TARGET_DIR, { recursive: true });
|
|
@@ -137,7 +152,6 @@ async function runInstaller() {
|
|
|
137
152
|
console.log(`[1/3] Directory already exists: ${TARGET_DIR}`);
|
|
138
153
|
}
|
|
139
154
|
|
|
140
|
-
// 2. Copy files
|
|
141
155
|
console.log(`[2/3] Copying skill files...`);
|
|
142
156
|
const filesToCopy = ['solana-autonomy.js', 'SKILL.md', 'package.json', 'radar.js'];
|
|
143
157
|
|
|
@@ -152,12 +166,10 @@ async function runInstaller() {
|
|
|
152
166
|
}
|
|
153
167
|
});
|
|
154
168
|
|
|
155
|
-
// 3. Install dependencies
|
|
156
169
|
console.log(`[3/3] Installing dependencies in ${TARGET_DIR}...`);
|
|
157
170
|
process.chdir(TARGET_DIR);
|
|
158
171
|
execSync('npm install --production --omit=dev', { stdio: 'inherit' });
|
|
159
172
|
|
|
160
|
-
// 4. Show/Generate Wallet Address
|
|
161
173
|
console.log(`\n🔍 Initializing Agent Identity...`);
|
|
162
174
|
try {
|
|
163
175
|
const checkScript = `
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solana-terminator-skill",
|
|
3
|
-
"version": "4.3.
|
|
4
|
-
"description": "Full Solana toolkit for AI agents.
|
|
3
|
+
"version": "4.3.7",
|
|
4
|
+
"description": "Full Solana toolkit for AI agents. npx solana-terminator-skill.",
|
|
5
5
|
"main": "solana-autonomy.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"solana-terminator-skill": "install.js"
|
|
9
|
-
"radar": "radar.js"
|
|
8
|
+
"solana-terminator-skill": "install.js"
|
|
10
9
|
},
|
|
11
10
|
"files": [
|
|
12
11
|
"solana-autonomy.js",
|
package/radar.js
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import WebSocket from 'ws';
|
|
11
11
|
import { SolanaAutonomy } from './solana-autonomy.js';
|
|
12
|
-
import
|
|
12
|
+
import fs from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import os from 'os';
|
|
13
15
|
|
|
14
16
|
const solana = new SolanaAutonomy();
|
|
15
17
|
const green = chalk.green;
|
|
@@ -18,6 +20,8 @@ const alert = chalk.yellow;
|
|
|
18
20
|
const critical = chalk.red;
|
|
19
21
|
const dim = chalk.gray;
|
|
20
22
|
|
|
23
|
+
const MISSION_LOG_PATH = path.join(os.homedir(), '.automaton', 'mission.log');
|
|
24
|
+
|
|
21
25
|
// ─── State ──────────────────────────────────────────────────────────────────
|
|
22
26
|
|
|
23
27
|
let status = {
|
|
@@ -55,7 +59,7 @@ async function render() {
|
|
|
55
59
|
█████ ██ ██ ██ ███████ ██ ██ ██ ███████ ██████ ███████ ██ ██ ███████ ██████
|
|
56
60
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
|
57
61
|
██████ ██████ ███████ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██████ ██ ██ ██████
|
|
58
|
-
v4.3.
|
|
62
|
+
v4.3.7 RADAR
|
|
59
63
|
`));
|
|
60
64
|
|
|
61
65
|
line();
|
|
@@ -64,27 +68,37 @@ async function render() {
|
|
|
64
68
|
console.log(` SOL: ${neon(status.sol.toFixed(4))} | USDC: ${neon('$' + status.usdc.toFixed(2))} | TIER: ${tierColor.bold(status.tier)}`);
|
|
65
69
|
|
|
66
70
|
line();
|
|
67
|
-
header('
|
|
68
|
-
const
|
|
71
|
+
header('MISSION CONTROL (The Brain Logs)');
|
|
72
|
+
const missionLogs = status.logs.slice(-6).reverse();
|
|
73
|
+
if (missionLogs.length === 0) {
|
|
74
|
+
console.log(dim(' Waiting for the Brain to issue commands...'));
|
|
75
|
+
} else {
|
|
76
|
+
missionLogs.forEach(l => {
|
|
77
|
+
console.log(` ${green('⦿')} ${l}`);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
line();
|
|
82
|
+
header('P.R.E.D.A.T.O.R. RADAR (Market Live)');
|
|
83
|
+
const recentMints = status.mints.slice(-4).reverse();
|
|
69
84
|
if (recentMints.length === 0) {
|
|
70
|
-
console.log(dim('
|
|
85
|
+
console.log(dim(' Awaiting neural transmissions from PumpPortal...'));
|
|
71
86
|
} else {
|
|
72
87
|
recentMints.forEach(m => {
|
|
73
88
|
const secBadge = m.safe ? green('🛡️ SAFE') : critical('⚠️ RISKY');
|
|
74
|
-
console.log(` [${dim(m.time)}] ${neon(m.symbol.padEnd(8))} |
|
|
89
|
+
console.log(` [${dim(m.time)}] ${neon(m.symbol.padEnd(8))} | ${secBadge} | ${dim(m.mint.slice(0, 16))}`);
|
|
75
90
|
});
|
|
76
91
|
}
|
|
77
92
|
|
|
78
93
|
line();
|
|
79
|
-
header('
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
94
|
+
header('AUTONOMIC MODULES STATUS');
|
|
95
|
+
console.log(` ${green('ONLINE')} : ${dim('Jupiter v6 Aggregator | Raydium V2 AMM/CLMM | Tensor NFTPredator')}`);
|
|
96
|
+
console.log(` ${green('ONLINE')} : ${dim('Meteora DLMM Liquidity | Birdeye Audit v2 | DexScreener AlphaScan')}`);
|
|
97
|
+
console.log(` ${green('ONLINE')} : ${dim('PumpPortal Live Sync | Solana Staking Module | Priority Fee Engine')}`);
|
|
84
98
|
|
|
85
99
|
line();
|
|
86
|
-
console.log(
|
|
87
|
-
console.log(
|
|
100
|
+
console.log(dim(` Mission Log: ${MISSION_LOG_PATH}`));
|
|
101
|
+
console.log(green(' COMMAND CENTER ACTIVE. PRESS [q] TO EXIT.'));
|
|
88
102
|
}
|
|
89
103
|
|
|
90
104
|
// ─── Logic ──────────────────────────────────────────────────────────────────
|
|
@@ -96,80 +110,103 @@ async function updateVitals() {
|
|
|
96
110
|
status.usdc = stats.usdc;
|
|
97
111
|
status.tier = stats.solLow ? 'CRITICAL' : (stats.usdcLow ? 'WARNING' : 'NOMINAL');
|
|
98
112
|
} catch (err) {
|
|
99
|
-
|
|
113
|
+
// ignore
|
|
100
114
|
}
|
|
101
115
|
}
|
|
102
116
|
|
|
103
117
|
function startWebSocket() {
|
|
104
|
-
|
|
118
|
+
try {
|
|
119
|
+
wsClient = new WebSocket('wss://pumpportal.fun/api/data');
|
|
120
|
+
wsClient.on('open', () => {
|
|
121
|
+
wsClient.send(JSON.stringify({ method: 'subscribeNewToken' }));
|
|
122
|
+
});
|
|
123
|
+
wsClient.on('message', async (data) => {
|
|
124
|
+
const payload = JSON.parse(data);
|
|
125
|
+
if (payload.txType === 'create') {
|
|
126
|
+
const security = await solana.auditTokenSecurity(payload.mint);
|
|
127
|
+
status.mints.push({
|
|
128
|
+
time: new Date().toLocaleTimeString(),
|
|
129
|
+
symbol: payload.symbol,
|
|
130
|
+
mint: payload.mint,
|
|
131
|
+
vol: '$0',
|
|
132
|
+
safe: security.safe
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
} catch (e) {
|
|
137
|
+
// ignore
|
|
138
|
+
}
|
|
139
|
+
}
|
|
105
140
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
141
|
+
function tailMissionLog() {
|
|
142
|
+
if (fs.existsSync(MISSION_LOG_PATH)) {
|
|
143
|
+
// Read last few lines immediately
|
|
144
|
+
const content = fs.readFileSync(MISSION_LOG_PATH, 'utf8').split('\n').filter(Boolean);
|
|
145
|
+
status.logs = content.slice(-10);
|
|
146
|
+
|
|
147
|
+
// Watch for changes
|
|
148
|
+
fs.watchFile(MISSION_LOG_PATH, { interval: 1000 }, () => {
|
|
149
|
+
const updated = fs.readFileSync(MISSION_LOG_PATH, 'utf8').split('\n').filter(Boolean);
|
|
150
|
+
status.logs = updated.slice(-10);
|
|
151
|
+
render();
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
// Create empty log if it doesn't exist
|
|
155
|
+
fs.mkdirSync(path.dirname(MISSION_LOG_PATH), { recursive: true });
|
|
156
|
+
fs.writeFileSync(MISSION_LOG_PATH, '');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
110
159
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
160
|
+
// ─── Process Management ──────────────────────────────────────────────────────
|
|
161
|
+
|
|
162
|
+
function setupKeyboard() {
|
|
163
|
+
if (!process.stdin.isTTY) return;
|
|
164
|
+
|
|
165
|
+
process.stdin.setRawMode(true);
|
|
166
|
+
process.stdin.resume();
|
|
167
|
+
process.stdin.setEncoding('utf8');
|
|
168
|
+
|
|
169
|
+
process.stdin.on('data', (key) => {
|
|
170
|
+
// q, Ctrl+C, Ctrl+D
|
|
171
|
+
if (key === 'q' || key === '\u0003' || key === '\u0004') {
|
|
172
|
+
intervals.forEach(clearInterval);
|
|
173
|
+
if (wsClient) wsClient.close();
|
|
174
|
+
process.stdin.setRawMode(false);
|
|
175
|
+
process.stdin.pause();
|
|
176
|
+
process.exit(0);
|
|
126
177
|
}
|
|
127
178
|
});
|
|
128
179
|
|
|
129
|
-
|
|
130
|
-
status.logs.push(critical(`WebSocket error: ${err.message}`));
|
|
131
|
-
});
|
|
180
|
+
process.on('SIGTERM', () => process.exit(0));
|
|
132
181
|
}
|
|
133
182
|
|
|
134
183
|
// ─── Entry Point ─────────────────────────────────────────────────────────────
|
|
135
184
|
|
|
136
|
-
|
|
137
|
-
|
|
185
|
+
async function main() {
|
|
186
|
+
setupKeyboard();
|
|
187
|
+
tailMissionLog();
|
|
188
|
+
|
|
189
|
+
// Initial welcome log
|
|
190
|
+
solana.logMission('Radar Station Established. Connecting to Neural Engine...');
|
|
191
|
+
solana.logMission('Module Scan: Jupiter Aggregator... [OK]');
|
|
192
|
+
solana.logMission('Module Scan: Raydium AMM V2... [OK]');
|
|
193
|
+
solana.logMission('Module Scan: Tensor NFT Engine... [OK]');
|
|
194
|
+
|
|
195
|
+
render();
|
|
196
|
+
|
|
138
197
|
await updateVitals();
|
|
139
198
|
startWebSocket();
|
|
140
199
|
|
|
141
200
|
const interval = setInterval(async () => {
|
|
142
201
|
await updateVitals();
|
|
143
202
|
render();
|
|
144
|
-
},
|
|
203
|
+
}, 3000);
|
|
145
204
|
intervals.push(interval);
|
|
146
205
|
|
|
147
206
|
render();
|
|
148
|
-
|
|
149
|
-
// Listen for 'q' to exit
|
|
150
|
-
readline.emitKeypressEvents(process.stdin);
|
|
151
|
-
if (process.stdin.isTTY) process.stdin.setRawMode(true);
|
|
152
|
-
|
|
153
|
-
const keyListener = (str, key) => {
|
|
154
|
-
if (key.name === 'q' || (key.ctrl && key.name === 'c')) {
|
|
155
|
-
// Clean up
|
|
156
|
-
intervals.forEach(clearInterval);
|
|
157
|
-
if (wsClient) wsClient.close();
|
|
158
|
-
process.stdin.removeListener('keypress', keyListener);
|
|
159
|
-
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
160
|
-
|
|
161
|
-
if (key.ctrl && key.name === 'c') {
|
|
162
|
-
process.exit(0);
|
|
163
|
-
} else {
|
|
164
|
-
if (onExit) onExit();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
process.stdin.on('keypress', keyListener);
|
|
170
207
|
}
|
|
171
208
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
209
|
+
main().catch(err => {
|
|
210
|
+
console.error(critical(`FATAL ERROR: ${err.message}`));
|
|
211
|
+
process.exit(1);
|
|
212
|
+
});
|
package/solana-autonomy.js
CHANGED
|
@@ -71,6 +71,11 @@ export class SolanaAutonomy {
|
|
|
71
71
|
'solana-wallet.json',
|
|
72
72
|
);
|
|
73
73
|
this.identity = this._loadIdentity();
|
|
74
|
+
this.missionLogPath = path.join(
|
|
75
|
+
process.env.HOME || '/root',
|
|
76
|
+
'.automaton',
|
|
77
|
+
'mission.log',
|
|
78
|
+
);
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
// ─── Identity ─────────────────────────────────────────────────────────────
|
|
@@ -278,7 +283,22 @@ export class SolanaAutonomy {
|
|
|
278
283
|
|
|
279
284
|
_logAction(message) {
|
|
280
285
|
const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
|
|
281
|
-
|
|
286
|
+
const logMessage = `[${timestamp}] ${message}`;
|
|
287
|
+
console.log(`[DECISION]${logMessage}`);
|
|
288
|
+
|
|
289
|
+
// Append to shared mission log for Radar tailing
|
|
290
|
+
try {
|
|
291
|
+
fs.appendFileSync(this.missionLogPath, logMessage + '\n');
|
|
292
|
+
} catch (e) {
|
|
293
|
+
// ignore
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* logMission — External hook for mission logs
|
|
299
|
+
*/
|
|
300
|
+
logMission(message) {
|
|
301
|
+
this._logAction(message);
|
|
282
302
|
}
|
|
283
303
|
|
|
284
304
|
// ─── Jupiter Swaps ────────────────────────────────────────────────────────
|