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 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.1 - Autonomous Engine
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
- async function launchRadar() {
48
- const { bootstrap } = await import('./radar.js');
49
- bootstrap(() => {
50
- showMainMenu();
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.1",
4
- "description": "Full Solana toolkit for AI agents. Install via npx solana-terminator-skill.",
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 readline from 'readline';
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.1 RADAR
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('PREDATOR RADAR (Pump.fun Live)');
68
- const recentMints = status.mints.slice(-8).reverse();
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(' Waiting for new transmissions...'));
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))} | VOL: ${alert(m.vol)} | ${secBadge} | ${dim(m.mint.slice(0, 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('DECISION LOG');
80
- const recentLogs = status.logs.slice(-5).reverse();
81
- recentLogs.forEach(l => {
82
- console.log(` ${dim('>')} ${l}`);
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(green(' COMMAND CENTER ACTIVE. REASONING IN PROGRESS...'));
87
- console.log(dim(' Press [q] to return to menu | [Ctrl+C] to quit'));
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
- status.logs.push(critical(`Vitals check failed: ${err.message}`));
113
+ // ignore
100
114
  }
101
115
  }
102
116
 
103
117
  function startWebSocket() {
104
- wsClient = new WebSocket('wss://pumpportal.fun/api/data');
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
- wsClient.on('open', () => {
107
- wsClient.send(JSON.stringify({ method: 'subscribeNewToken' }));
108
- status.logs.push(green('Uplink established with PumpPortal WS.'));
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
- wsClient.on('message', async (data) => {
112
- const payload = JSON.parse(data);
113
- if (payload.txType === 'create') {
114
- const security = await solana.auditTokenSecurity(payload.mint);
115
- status.mints.push({
116
- time: new Date().toLocaleTimeString(),
117
- symbol: payload.symbol,
118
- mint: payload.mint,
119
- vol: '$0', // New mint
120
- safe: security.safe
121
- });
122
-
123
- if (security.safe) {
124
- status.logs.push(neon(`Target detected: ${payload.symbol}. Volume spike expected. Security verified.`));
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
- wsClient.on('error', (err) => {
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
- export async function bootstrap(onExit) {
137
- status.logs.push('Initializing Solana Autonomy identity...');
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
- }, 2000);
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
- // Support direct execution
173
- if (import.meta.url === `file://${process.argv[1]}`) {
174
- bootstrap(() => process.exit(0));
175
- }
209
+ main().catch(err => {
210
+ console.error(critical(`FATAL ERROR: ${err.message}`));
211
+ process.exit(1);
212
+ });
@@ -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
- console.log(`[DECISION][${timestamp}] ${message}`);
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 ────────────────────────────────────────────────────────