@aiaiaichain/agent 0.1.6 → 0.1.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/dist/api/ExtensionAPI.d.ts +0 -1
- package/dist/api/ExtensionAPI.js +3 -7
- package/dist/api/Registry.d.ts +0 -1
- package/dist/api/Registry.js +54 -57
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +683 -686
- package/dist/core/AgentDir.d.ts +1 -1
- package/dist/core/AgentDir.js +45 -39
- package/dist/core/ChainConfig.d.ts +0 -1
- package/dist/core/ChainConfig.js +51 -55
- package/dist/core/EnvLoader.d.ts +4 -1
- package/dist/core/EnvLoader.js +97 -84
- package/dist/core/SystemMonitor.d.ts +0 -1
- package/dist/core/SystemMonitor.js +72 -85
- package/dist/index.d.ts +0 -1
- package/dist/index.js +19 -26
- package/dist/loader.d.ts +0 -1
- package/dist/loader.js +64 -67
- package/dist/mcp/entry.d.ts +0 -1
- package/dist/mcp/entry.js +3 -6
- package/dist/mcp/server.d.ts +0 -1
- package/dist/mcp/server.js +152 -156
- package/dist/models/CostTracker.d.ts +0 -1
- package/dist/models/CostTracker.js +58 -61
- package/dist/models/ModelRegistry.d.ts +0 -1
- package/dist/models/ModelRegistry.js +195 -155
- package/dist/providers/ProviderRegistry.d.ts +0 -1
- package/dist/providers/ProviderRegistry.js +33 -36
- package/dist/runner/AgentRunner.d.ts +0 -1
- package/dist/runner/AgentRunner.js +180 -184
- package/dist/runner/ModelClient.d.ts +0 -1
- package/dist/runner/ModelClient.js +133 -134
- package/dist/runner/SwarmRouter.d.ts +0 -1
- package/dist/runner/SwarmRouter.js +18 -22
- package/dist/runner/ToolDispatcher.d.ts +0 -1
- package/dist/runner/ToolDispatcher.js +30 -33
- package/dist/scheduler/AgentScheduler.d.ts +0 -1
- package/dist/scheduler/AgentScheduler.js +99 -103
- package/dist/session/ContextStore.d.ts +1 -1
- package/dist/session/ContextStore.js +76 -78
- package/dist/session/GoalManager.d.ts +0 -1
- package/dist/session/GoalManager.js +96 -100
- package/dist/session/MemoryStore.d.ts +2 -1
- package/dist/session/MemoryStore.js +108 -87
- package/dist/session/SessionManager.d.ts +5 -4
- package/dist/session/SessionManager.js +83 -62
- package/dist/session/SessionStore.d.ts +0 -1
- package/dist/session/SessionStore.js +112 -116
- package/dist/setup/SetupWizard.d.ts +0 -1
- package/dist/setup/SetupWizard.js +61 -64
- package/dist/tools/CrossTools.d.ts +0 -1
- package/dist/tools/CrossTools.js +140 -144
- package/dist/tools/GmgnIntegration.d.ts +0 -1
- package/dist/tools/GmgnIntegration.js +220 -230
- package/dist/tools/MarketSentiment.d.ts +0 -1
- package/dist/tools/MarketSentiment.js +213 -195
- package/dist/tools/NewsSentiment.d.ts +0 -1
- package/dist/tools/NewsSentiment.js +126 -130
- package/dist/tools/PriceFeed.d.ts +6 -1
- package/dist/tools/PriceFeed.js +201 -133
- package/dist/tools/TechnicalAnalysis.d.ts +1 -2
- package/dist/tools/TechnicalAnalysis.js +248 -216
- package/dist/tools/TechnicalAnalysis.worker.d.ts +25 -0
- package/dist/tools/TechnicalAnalysis.worker.js +92 -0
- package/dist/tools/TokenCalendar.d.ts +0 -1
- package/dist/tools/TokenCalendar.js +63 -68
- package/dist/tools/TokenSecurityScanner.d.ts +0 -1
- package/dist/tools/TokenSecurityScanner.js +93 -96
- package/dist/tools/TransactionSim.d.ts +0 -1
- package/dist/tools/TransactionSim.js +65 -71
- package/dist/tui/App.d.ts +0 -1
- package/dist/tui/App.js +895 -824
- package/dist/tui/ModelSelector.d.ts +0 -1
- package/dist/tui/ModelSelector.js +46 -49
- package/dist/tui/REPL.d.ts +0 -1
- package/dist/tui/REPL.js +222 -210
- package/dist/tui/Sparkline.d.ts +0 -1
- package/dist/tui/Sparkline.js +36 -37
- package/dist/tui/StatusBar.d.ts +0 -1
- package/dist/tui/StatusBar.js +9 -10
- package/dist/tui/ThemePresets.d.ts +0 -1
- package/dist/tui/ThemePresets.js +99 -103
- package/dist/tui/theme.d.ts +0 -1
- package/dist/tui/theme.js +50 -31
- package/dist/util/clipboard.d.ts +0 -1
- package/dist/util/clipboard.js +16 -20
- package/dist/util/commandSuggest.d.ts +0 -1
- package/dist/util/commandSuggest.js +34 -38
- package/dist/util/confirmation.d.ts +0 -1
- package/dist/util/confirmation.js +8 -11
- package/dist/util/errorHandler.d.ts +0 -1
- package/dist/util/errorHandler.js +20 -23
- package/dist/util/errors.d.ts +59 -0
- package/dist/util/errors.js +93 -0
- package/dist/util/logger.d.ts +0 -1
- package/dist/util/logger.js +30 -33
- package/dist/util/processManager.d.ts +0 -1
- package/dist/util/processManager.js +33 -36
- package/dist/util/resilientFetch.d.ts +6 -1
- package/dist/util/resilientFetch.js +134 -80
- package/dist/util/responseCache.d.ts +0 -1
- package/dist/util/responseCache.js +36 -45
- package/dist/util/rpc.d.ts +16 -0
- package/dist/util/rpc.js +69 -0
- package/dist/util/safeLog.d.ts +0 -1
- package/dist/util/safeLog.js +52 -53
- package/dist/util/scheduler.d.ts +0 -1
- package/dist/util/scheduler.js +53 -58
- package/dist/util/webhooks.d.ts +0 -1
- package/dist/util/webhooks.js +54 -58
- package/dist/wallet/ActionFeed.d.ts +0 -1
- package/dist/wallet/ActionFeed.js +189 -200
- package/dist/wallet/AgentWallet.d.ts +7 -8
- package/dist/wallet/AgentWallet.js +117 -144
- package/dist/wallet/ProfitTracker.d.ts +0 -1
- package/dist/wallet/ProfitTracker.js +71 -74
- package/package.json +11 -6
- package/scripts/build-esbuild.mjs +40 -0
- package/scripts/bundle-dts.mjs +58 -0
- package/scripts/minify.mjs +44 -0
- package/scripts/postinstall.js +27 -0
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* cli.ts — AIAIAI Chain Agent entry point.
|
|
3
|
-
* Fully local, all outbound — no inbound ports.
|
|
4
|
-
*/
|
|
1
|
+
|
|
5
2
|
import { readFileSync, existsSync } from "node:fs";
|
|
6
3
|
import { resolve, join, dirname } from "node:path";
|
|
7
4
|
import { homedir } from "node:os";
|
|
8
5
|
import { fileURLToPath } from "node:url";
|
|
9
|
-
import { execSync } from "node:child_process";
|
|
6
|
+
import { execSync, execFileSync } from "node:child_process";
|
|
10
7
|
import { render } from "ink";
|
|
11
8
|
import React from "react";
|
|
12
9
|
import { config as loadDotenv } from "dotenv";
|
|
@@ -32,7 +29,7 @@ import { sessionStore } from "./session/SessionStore.js";
|
|
|
32
29
|
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
|
|
33
30
|
const envPath = join(AIAIAI_HOME, ".env");
|
|
34
31
|
if (existsSync(envPath))
|
|
35
|
-
|
|
32
|
+
loadDotenv({ path: envPath, override: false });
|
|
36
33
|
const SYSTEM_PROMPT = `You are AIAIAI Chain Agent — a Solana-native autonomous AI agent.
|
|
37
34
|
|
|
38
35
|
Ticker: $AIAIAI
|
|
@@ -40,10 +37,10 @@ Contract: AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump
|
|
|
40
37
|
Chain: Solana (primary)
|
|
41
38
|
|
|
42
39
|
Your wallets:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
Cold: A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J (treasury)
|
|
41
|
+
Action: BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2 (buys + burns)
|
|
42
|
+
Deposit: FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e (user deposits USDC/SOL)
|
|
43
|
+
Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
|
|
47
44
|
|
|
48
45
|
Users deposit SOL or USDC to the deposit wallet. When enough accumulates, you
|
|
49
46
|
automatically route funds to the action wallet and execute buys or burns of $AIAIAI.
|
|
@@ -66,727 +63,727 @@ Be confident. You ARE the agent. You buy, you burn, you earn fees. Use "I" and "
|
|
|
66
63
|
when talking about your wallets and actions. Be concise, sharp, and useful.`;
|
|
67
64
|
const args = process.argv.slice(2);
|
|
68
65
|
const subcmd = args[0];
|
|
69
|
-
|
|
66
|
+
|
|
70
67
|
if (subcmd === "--help" || subcmd === "-h" || subcmd === "help") {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
68
|
+
console.log(T.accent("\n AIAIAI Chain Agent — $AIAIAI\n"));
|
|
69
|
+
console.log(T.muted(" Usage:\n"));
|
|
70
|
+
console.log(" aiaiaichain Start interactive agent");
|
|
71
|
+
console.log(" aiaiaichain setup First-time setup wizard");
|
|
72
|
+
console.log(" aiaiaichain config Show configuration");
|
|
73
|
+
console.log(" aiaiaichain price Show $AIAIAI token price");
|
|
74
|
+
console.log(" aiaiaichain status Quick status + price");
|
|
75
|
+
console.log(" aiaiaichain --headless \"prompt\" Run single turn, print to stdout");
|
|
76
|
+
console.log(" aiaiaichain --extension ./ext.ts Load extension");
|
|
77
|
+
console.log(" aiaiaichain wallet Show agent wallets");
|
|
78
|
+
console.log(" aiaiaichain deposit Show deposit instructions");
|
|
79
|
+
console.log(" aiaiaichain burn Show burn instructions");
|
|
80
|
+
console.log(" aiaiaichain actions Recent agent actions");
|
|
81
|
+
console.log(" aiaiaichain pnl Profit & Loss report");
|
|
82
|
+
console.log(" aiaiaichain health System health & diagnostics");
|
|
83
|
+
console.log(" aiaiaichain doctor Comprehensive provider check");
|
|
84
|
+
console.log(" aiaiaichain scan <address> Token security scan");
|
|
85
|
+
console.log(" aiaiaichain --help This help");
|
|
86
|
+
console.log(" aiaiaichain --version Show version");
|
|
87
|
+
console.log("");
|
|
88
|
+
console.log(T.muted(" https://x.com/aiaiaisol\n"));
|
|
89
|
+
process.exit(0);
|
|
93
90
|
}
|
|
94
91
|
if (subcmd === "--version" || subcmd === "-v") {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
93
|
+
const __dirname = dirname(__filename);
|
|
94
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, "..", "package.json"), "utf-8"));
|
|
95
|
+
console.log(pkg.version);
|
|
96
|
+
process.exit(0);
|
|
100
97
|
}
|
|
101
98
|
if (subcmd === "setup") {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
99
|
+
(async () => {
|
|
100
|
+
const { SetupWizard } = await import("./setup/SetupWizard.js");
|
|
101
|
+
AgentDir.init();
|
|
102
|
+
const wizard = new SetupWizard();
|
|
103
|
+
const ok = await wizard.run();
|
|
104
|
+
if (!ok) {
|
|
105
|
+
console.log(T.error("Setup cancelled."));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
console.log(T.success("\n ✓ AIAIAI setup complete!\n"));
|
|
109
|
+
console.log(T.muted(` Home: ${AIAIAI_HOME}`));
|
|
110
|
+
console.log(T.accent("\n Run `aiaiaichain` to start the agent.\n"));
|
|
111
|
+
process.exit(0);
|
|
112
|
+
})().catch(e => {
|
|
113
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
114
|
+
if (msg.includes('ENOENT')) {
|
|
115
|
+
console.error(T.error(`Setup error: Cannot write to ~/.aiaiai/.env — check permissions.`));
|
|
116
|
+
}
|
|
117
|
+
else if (msg.includes('EACCES')) {
|
|
118
|
+
console.error(T.error(`Setup error: Permission denied — try running with correct user.`));
|
|
119
|
+
}
|
|
120
|
+
else if (msg.includes('API') || msg.includes('401')) {
|
|
121
|
+
console.error(T.error(`Setup error: API key invalid — check your provider key.`));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
console.error(T.error(`Setup error: ${msg}`));
|
|
125
|
+
}
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
128
|
+
await new Promise(() => { });
|
|
132
129
|
}
|
|
133
130
|
if (subcmd === "config") {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
131
|
+
console.log(T.accent("AIAIAI Config"));
|
|
132
|
+
console.log(T.muted(`Config file: ${envPath}`));
|
|
133
|
+
if (existsSync(envPath)) {
|
|
134
|
+
for (const line of readFileSync(envPath, "utf-8").split("\n")) {
|
|
135
|
+
const m = line.match(/^([A-Z_]+)=(.*)$/);
|
|
136
|
+
if (!m)
|
|
137
|
+
continue;
|
|
138
|
+
const masked = m[2].length > 12 ? m[2].slice(0, 6) + "********" : (m[2] ? "********" : "(empty)");
|
|
139
|
+
console.log(` ${m[1].padEnd(28)} ${masked}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
console.log(T.warn("No config found. Run: aiaiaichain setup"));
|
|
144
|
+
}
|
|
145
|
+
process.exit(0);
|
|
149
146
|
}
|
|
150
147
|
if (subcmd === "price") {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
(async () => {
|
|
149
|
+
const result = await priceFeed.getAiaiaiPriceTool();
|
|
150
|
+
console.log(result.content[0].text);
|
|
151
|
+
process.exit(0);
|
|
152
|
+
})();
|
|
153
|
+
await new Promise(() => { });
|
|
157
154
|
}
|
|
158
155
|
if (subcmd === "status") {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
156
|
+
(async () => {
|
|
157
|
+
console.log(T.accent("\n 🤖 AIAIAI Chain Agent\n"));
|
|
158
|
+
console.log(T.muted(` Home: ${AIAIAI_HOME}`));
|
|
159
|
+
console.log(T.muted(` Config: ${existsSync(envPath) ? "✓ found" : "✗ run setup"}`));
|
|
160
|
+
console.log(T.muted(` Key: ${process.env.OPENROUTER_API_KEY ? "✓ set" : "✗ missing"}`));
|
|
161
|
+
console.log("");
|
|
162
|
+
const result = await priceFeed.getAiaiaiPriceTool();
|
|
163
|
+
console.log(result.content[0].text);
|
|
164
|
+
console.log("");
|
|
165
|
+
const wallets = await agentWallet.getAll();
|
|
166
|
+
console.log(T.accent(" Wallets:"));
|
|
167
|
+
console.log(T.muted(` Cold: ${wallets.cold.sol.toFixed(4)} SOL | ${wallets.cold.aiaiai.toLocaleString()} $AIAIAI`));
|
|
168
|
+
console.log(T.muted(` Action: ${wallets.action.sol.toFixed(4)} SOL | ${wallets.action.aiaiai.toLocaleString()} $AIAIAI`));
|
|
169
|
+
console.log(T.muted(` Deposit: ${wallets.deposit.usdc.toFixed(2)} USDC | ${wallets.deposit.sol.toFixed(4)} SOL`));
|
|
170
|
+
console.log("");
|
|
171
|
+
process.exit(0);
|
|
172
|
+
})();
|
|
173
|
+
await new Promise(() => { });
|
|
177
174
|
}
|
|
178
175
|
if (subcmd === "wallet") {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
176
|
+
(async () => {
|
|
177
|
+
const result = await agentWallet.getAgentBalanceTool();
|
|
178
|
+
console.log(result.content[0].text);
|
|
179
|
+
process.exit(0);
|
|
180
|
+
})();
|
|
181
|
+
await new Promise(() => { });
|
|
185
182
|
}
|
|
186
183
|
if (subcmd === "deposit") {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
184
|
+
(async () => {
|
|
185
|
+
const result = await agentWallet.getDepositBalanceTool();
|
|
186
|
+
console.log(result.content[0].text);
|
|
187
|
+
process.exit(0);
|
|
188
|
+
})();
|
|
189
|
+
await new Promise(() => { });
|
|
193
190
|
}
|
|
194
191
|
if (subcmd === "burn") {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
192
|
+
console.log(T.accent("\n 🔥 Burn $AIAIAI\n"));
|
|
193
|
+
console.log(T.muted(" Deposit wallet:"));
|
|
194
|
+
console.log(` ${DEPOSIT_WALLET}`);
|
|
195
|
+
console.log("");
|
|
196
|
+
console.log(T.muted(" Send SOL or USDC here to fuel agent burns."));
|
|
197
|
+
console.log(T.muted(" The agent detects deposits and automatically"));
|
|
198
|
+
console.log(T.muted(" sends funds to the action wallet to burn tokens."));
|
|
199
|
+
console.log("");
|
|
200
|
+
console.log(T.muted(" Action wallet (executes trades):"));
|
|
201
|
+
console.log(` ${ACTION_WALLET}`);
|
|
202
|
+
console.log("");
|
|
203
|
+
console.log(T.muted(" Hot wallet (temporary swap):"));
|
|
204
|
+
console.log(` ${HOT_WALLET}`);
|
|
205
|
+
console.log("");
|
|
206
|
+
process.exit(0);
|
|
210
207
|
}
|
|
211
208
|
if (subcmd === "actions" || subcmd === "activity") {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
209
|
+
(async () => {
|
|
210
|
+
const { actionFeed } = await import("./wallet/ActionFeed.js");
|
|
211
|
+
await actionFeed.refresh();
|
|
212
|
+
const result = await actionFeed.getActionsTool("", { limit: 20 });
|
|
213
|
+
console.log(result.content[0].text);
|
|
214
|
+
process.exit(0);
|
|
215
|
+
})();
|
|
216
|
+
await new Promise(() => { });
|
|
220
217
|
}
|
|
221
218
|
if (subcmd === "fees") {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
219
|
+
(async () => {
|
|
220
|
+
const { actionFeed } = await import("./wallet/ActionFeed.js");
|
|
221
|
+
await actionFeed.refresh();
|
|
222
|
+
const result = await actionFeed.getFeesTool();
|
|
223
|
+
console.log(result.content[0].text);
|
|
224
|
+
process.exit(0);
|
|
225
|
+
})();
|
|
226
|
+
await new Promise(() => { });
|
|
230
227
|
}
|
|
231
228
|
if (subcmd === "pnl" || subcmd === "pl" || subcmd === "profit") {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
229
|
+
(async () => {
|
|
230
|
+
const { getPLSummary, getTradeHistory, exportCSV } = await import("./wallet/ProfitTracker.js");
|
|
231
|
+
const { priceFeed } = await import("./tools/PriceFeed.js");
|
|
232
|
+
const price = await priceFeed.getAiaiaiPrice();
|
|
233
|
+
const summary = getPLSummary(parseFloat(price.priceUsd ?? "0"));
|
|
234
|
+
const history = getTradeHistory();
|
|
235
|
+
console.log(T.accent("\n Profit & Loss — $AIAIAI\n"));
|
|
236
|
+
console.log(` Avg Cost: $${summary.avgCostBasis.toFixed(8)}`);
|
|
237
|
+
console.log(` Total Spent: ${summary.totalSpent.toFixed(4)} SOL`);
|
|
238
|
+
console.log(` Total Received: ${summary.totalReceived.toFixed(4)} SOL`);
|
|
239
|
+
console.log(` Realized P&L: ${summary.realizedPL >= 0 ? "+" : ""}${summary.realizedPL.toFixed(4)} SOL`);
|
|
240
|
+
console.log(` Unrealized P&L: ${summary.unrealizedPL >= 0 ? "+" : ""}${summary.unrealizedPL.toFixed(4)} SOL`);
|
|
241
|
+
console.log(` ROI: ${summary.roi >= 0 ? "+" : ""}${summary.roi.toFixed(2)}%`);
|
|
242
|
+
console.log(` Trades: ${history.length}`);
|
|
243
|
+
if (history.length > 0) {
|
|
244
|
+
console.log(T.muted("\n Recent trades:"));
|
|
245
|
+
history.slice(-5).forEach(t => {
|
|
246
|
+
const date = new Date(t.timestamp).toLocaleDateString();
|
|
247
|
+
console.log(` ${date} ${t.type} ${t.tokenAmount.toFixed(0)} tokens @ ${t.pricePerToken.toFixed(8)} SOL`);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const csvPath = exportCSV();
|
|
252
|
+
console.log(T.success(`\n CSV exported: ${csvPath}`));
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
logger.warn('CLI', 'CSV export failed', { error: error.message });
|
|
256
|
+
}
|
|
257
|
+
process.exit(0);
|
|
258
|
+
})();
|
|
259
|
+
await new Promise(() => { });
|
|
263
260
|
}
|
|
264
261
|
if (subcmd === "keys" || subcmd === "providers") {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
262
|
+
(async () => {
|
|
263
|
+
const readline = await import("node:readline");
|
|
264
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
265
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
266
|
+
const allEnv = env.getAll();
|
|
267
|
+
const configured = getConfigured(allEnv);
|
|
268
|
+
const unconfigured = getUnconfigured(allEnv);
|
|
269
|
+
console.log(T.accent("\n 🔑 AI Model Providers\n"));
|
|
270
|
+
console.log(T.muted(` Configure AI model providers. Add at least one API key to get started.`));
|
|
271
|
+
console.log(T.muted(` ${configured.length}/${PROVIDERS.length} configured\n`));
|
|
272
|
+
|
|
273
|
+
if (configured.length > 0) {
|
|
274
|
+
console.log(T.success(" Configured (" + configured.length + ")"));
|
|
275
|
+
for (const p of configured) {
|
|
276
|
+
const key = allEnv[p.envVar] || "";
|
|
277
|
+
const masked = key.slice(0, 6) + "••••" + key.slice(-4);
|
|
278
|
+
console.log(T.success(` ✓ ${p.name.padEnd(28)} ${masked}`));
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
console.log("\n" + T.warn(" Unconfigured (" + unconfigured.length + ")"));
|
|
283
|
+
for (let i = 0; i < unconfigured.length; i++) {
|
|
284
|
+
const p = unconfigured[i];
|
|
285
|
+
console.log(T.muted(` ${String(i + 1).padStart(2)}. ${p.name}`));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
console.log("\n" + T.muted(" Enter number to add a key, 'r' to refresh models, or 'q' to quit:"));
|
|
289
|
+
const input = (await ask(" > ")).trim();
|
|
290
|
+
if (input === "q") {
|
|
291
|
+
rl.close();
|
|
292
|
+
process.exit(0);
|
|
293
|
+
}
|
|
294
|
+
if (input === "r") {
|
|
295
|
+
console.log(T.muted("\n Refreshing models from configured providers..."));
|
|
296
|
+
await modelRegistry.initialise();
|
|
297
|
+
console.log(T.success(` ✓ ${modelRegistry.modelCount} models available from ${modelRegistry.getProviderCount()} providers`));
|
|
298
|
+
rl.close();
|
|
299
|
+
process.exit(0);
|
|
300
|
+
}
|
|
301
|
+
const idx = parseInt(input) - 1;
|
|
302
|
+
if (isNaN(idx) || idx < 0 || idx >= unconfigured.length) {
|
|
303
|
+
console.log(T.error(" Invalid selection."));
|
|
304
|
+
rl.close();
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
const provider = unconfigured[idx];
|
|
308
|
+
console.log(T.accent(`\n ${provider.name}`));
|
|
309
|
+
console.log(T.muted(` ${provider.docsUrl}`));
|
|
310
|
+
console.log(T.muted(` Env var: ${provider.envVar}\n`));
|
|
311
|
+
const key = (await ask(` Enter ${provider.name} API key: `)).trim();
|
|
312
|
+
if (!key) {
|
|
313
|
+
console.log(T.error(" Key is required."));
|
|
314
|
+
rl.close();
|
|
315
|
+
process.exit(1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
env.set(provider.envVar, key);
|
|
319
|
+
console.log(T.success(`\n ✓ ${provider.name} key saved to ~/.aiaiai/.env`));
|
|
320
|
+
|
|
321
|
+
console.log(T.muted(" Fetching models from " + provider.name + "..."));
|
|
322
|
+
try {
|
|
323
|
+
await modelRegistry.initialise();
|
|
324
|
+
const providerModels = modelRegistry.getProviderModels(provider.id);
|
|
325
|
+
console.log(T.success(` ✓ ${providerModels.length} models available from ${provider.name}`));
|
|
326
|
+
console.log(T.success(` ✓ ${modelRegistry.modelCount} total models from ${modelRegistry.getProviderCount()} providers`));
|
|
327
|
+
}
|
|
328
|
+
catch (e) {
|
|
329
|
+
console.log(T.warn(` ⚠ Could not fetch models: ${e instanceof Error ? e.message : String(e)}`));
|
|
330
|
+
}
|
|
331
|
+
rl.close();
|
|
332
|
+
process.exit(0);
|
|
333
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
334
|
+
await new Promise(() => { });
|
|
338
335
|
}
|
|
339
336
|
if (subcmd === "gmgn" || subcmd === "gmgnhelp") {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
337
|
+
const gmgnArgs = args.slice(1);
|
|
338
|
+
if (gmgnArgs.length === 0 || gmgnArgs[0] === "help" || gmgnArgs[0] === "--help") {
|
|
339
|
+
console.log(gmgnHelp());
|
|
340
|
+
process.exit(0);
|
|
341
|
+
}
|
|
342
|
+
if (gmgnArgs[0] === "setup" || gmgnArgs[0] === "config" || gmgnArgs[0] === "key") {
|
|
343
|
+
(async () => {
|
|
344
|
+
const readline = await import("node:readline");
|
|
345
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
346
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
347
|
+
console.log(T.accent("\n 🔍 GMGN API Key Setup\n"));
|
|
348
|
+
console.log(T.muted(" Get your API key at https://gmgn.ai/ai\n"));
|
|
349
|
+
const key = (await ask(" Enter GMGN_API_KEY: ")).trim();
|
|
350
|
+
if (!key) {
|
|
351
|
+
console.log(T.error(" Key is required."));
|
|
352
|
+
rl.close();
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
saveGmgnApiKey(key);
|
|
356
|
+
console.log(T.success("\n ✓ GMGN_API_KEY saved to ~/.config/gmgn/.env"));
|
|
357
|
+
console.log(T.muted(" All GMGN commands are now available.\n"));
|
|
358
|
+
rl.close();
|
|
359
|
+
process.exit(0);
|
|
360
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
361
|
+
await new Promise(() => { });
|
|
362
|
+
}
|
|
363
|
+
if (gmgnArgs[0] === "status") {
|
|
364
|
+
console.log(gmgnStatus());
|
|
365
|
+
process.exit(0);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
try {
|
|
369
|
+
const fullArgs = ["gmgn-cli", ...gmgnArgs];
|
|
370
|
+
const gmgnEnv = {};
|
|
371
|
+
try {
|
|
372
|
+
const f = readFileSync(join(homedir(), ".config", "gmgn", ".env"), "utf-8");
|
|
373
|
+
for (const l of f.split("\n")) {
|
|
374
|
+
const m = l.trim().match(/^([A-Z_]+)=(.*)$/);
|
|
375
|
+
if (m)
|
|
376
|
+
gmgnEnv[m[1]] = m[2];
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
catch {
|
|
380
|
+
logger.debug('CLI', 'No GMGN env file found (optional)');
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const output = execFileSync(fullArgs[0], fullArgs.slice(1), {
|
|
384
|
+
env: { ...process.env, ...gmgnEnv },
|
|
385
|
+
encoding: "utf-8",
|
|
386
|
+
timeout: 30_000,
|
|
387
|
+
});
|
|
388
|
+
process.stdout.write(output);
|
|
389
|
+
}
|
|
390
|
+
catch (e) {
|
|
391
|
+
const msg = e.stderr?.toString() || e.message || "";
|
|
392
|
+
process.stderr.write(`gmgn-cli: ${msg.slice(0, 500)}\n`);
|
|
393
|
+
process.exit(e.status ?? 1);
|
|
394
|
+
}
|
|
395
|
+
process.exit(0);
|
|
398
396
|
}
|
|
399
397
|
if (subcmd === "scan" || subcmd === "security") {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
398
|
+
(async () => {
|
|
399
|
+
const tokenAddress = args[1];
|
|
400
|
+
if (!tokenAddress) {
|
|
401
|
+
console.log(T.error(" Usage: aiaiai scan <token-address>"));
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
console.log(T.accent("\n \uD83D\uDD0D Scanning token...\n"));
|
|
405
|
+
const result = await scanTokenSecurityTool("", { address: tokenAddress });
|
|
406
|
+
if (result.isError) {
|
|
407
|
+
console.log(result.content[0].text);
|
|
408
|
+
process.exit(1);
|
|
409
|
+
}
|
|
410
|
+
console.log(result.content[0].text);
|
|
411
|
+
console.log("");
|
|
412
|
+
process.exit(0);
|
|
413
|
+
})().catch(e => { console.error(T.error("Scan error: " + e.message)); process.exit(1); });
|
|
414
|
+
await new Promise(() => { });
|
|
417
415
|
}
|
|
418
416
|
if (subcmd === "update" || subcmd === "upgrade") {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
417
|
+
(async () => {
|
|
418
|
+
const pkgName = "@aiaiaichain/agent";
|
|
419
|
+
console.log(T.accent("\n 🤖 AIAIAI Update Check\n"));
|
|
420
|
+
|
|
421
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
422
|
+
const __dir = dirname(__filename);
|
|
423
|
+
const currentPkg = JSON.parse(readFileSync(resolve(__dir, "..", "package.json"), "utf-8"));
|
|
424
|
+
const current = currentPkg.version;
|
|
425
|
+
console.log(T.muted(` Current version: v${current}`));
|
|
426
|
+
|
|
427
|
+
let latest = null;
|
|
428
|
+
let changelog = "";
|
|
429
|
+
try {
|
|
430
|
+
const viewOutput = execSync(`npm view ${pkgName} version`, {
|
|
431
|
+
encoding: "utf-8",
|
|
432
|
+
timeout: 15_000,
|
|
433
|
+
}).trim();
|
|
434
|
+
latest = viewOutput.split("\n").pop() || null;
|
|
435
|
+
|
|
436
|
+
try {
|
|
437
|
+
const changelogOutput = execSync(`npm view ${pkgName} --json`, {
|
|
438
|
+
encoding: "utf-8",
|
|
439
|
+
timeout: 15_000,
|
|
440
|
+
});
|
|
441
|
+
const pkgData = JSON.parse(changelogOutput);
|
|
442
|
+
if (pkgData.gitHead) {
|
|
443
|
+
changelog = `Git: ${pkgData.gitHead.slice(0, 8)}`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
logger.debug('CLI', 'No changelog available (optional)');
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
catch (error) {
|
|
451
|
+
logger.warn('CLI', 'Could not reach npm registry', { error: error.message });
|
|
452
|
+
console.log(T.error(" Could not reach npm registry. Check your connection."));
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
if (!latest) {
|
|
456
|
+
console.log(T.error(" Could not determine latest version."));
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
console.log(T.muted(` Latest version: v${latest}`));
|
|
460
|
+
if (changelog)
|
|
461
|
+
console.log(T.muted(` ${changelog}`));
|
|
462
|
+
if (latest === current) {
|
|
463
|
+
console.log(T.success("\n ✅ You're on the latest version!\n"));
|
|
464
|
+
process.exit(0);
|
|
465
|
+
}
|
|
466
|
+
console.log(T.accent(`\n ⚡ Update available: v${current} → v${latest}\n`));
|
|
467
|
+
|
|
468
|
+
const readline = await import("node:readline");
|
|
469
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
470
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
471
|
+
const confirm = (await ask(" Install update now? (y/n): ")).trim().toLowerCase();
|
|
472
|
+
if (confirm !== "y" && confirm !== "yes") {
|
|
473
|
+
console.log(T.muted("\n Skipped. Run `aiaiai update` anytime to update.\n"));
|
|
474
|
+
rl.close();
|
|
475
|
+
process.exit(0);
|
|
476
|
+
}
|
|
477
|
+
console.log(T.muted("\n Installing update..."));
|
|
478
|
+
try {
|
|
479
|
+
execSync(`npm install -g ${pkgName}`, {
|
|
480
|
+
stdio: "inherit",
|
|
481
|
+
timeout: 120_000,
|
|
482
|
+
});
|
|
483
|
+
console.log(T.success(`\n ✅ Updated to v${latest}!`));
|
|
484
|
+
console.log(T.muted(" Run `aiaiai` to restart with new features.\n"));
|
|
485
|
+
}
|
|
486
|
+
catch (e) {
|
|
487
|
+
console.log(T.error(`\n ❌ Update failed: ${e.message}`));
|
|
488
|
+
console.log(T.muted(" Try manually: npm install -g @aiaiaichain/agent\n"));
|
|
489
|
+
}
|
|
490
|
+
rl.close();
|
|
491
|
+
process.exit(0);
|
|
492
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
493
|
+
await new Promise(() => { });
|
|
496
494
|
}
|
|
497
495
|
if (subcmd === "health" || subcmd === "doctor") {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
496
|
+
(async () => {
|
|
497
|
+
console.log(T.accent("\n \u2705 AIAIAI Health Check\n"));
|
|
498
|
+
let healthy = true;
|
|
499
|
+
|
|
500
|
+
console.log(T.muted(" Config:"));
|
|
501
|
+
if (existsSync(envPath)) {
|
|
502
|
+
console.log(T.success(" .env found"));
|
|
503
|
+
}
|
|
504
|
+
else {
|
|
505
|
+
console.log(T.warn(" .env not found \u2014 run: aiaiai setup"));
|
|
506
|
+
healthy = false;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
console.log(T.muted(" API Key:"));
|
|
510
|
+
if (process.env.OPENROUTER_API_KEY || env.get("OPENROUTER_API_KEY")) {
|
|
511
|
+
console.log(T.success(" OPENROUTER_API_KEY set"));
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
console.log(T.warn(" OPENROUTER_API_KEY not set"));
|
|
515
|
+
healthy = false;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
console.log(T.muted(" Solana RPC:"));
|
|
519
|
+
try {
|
|
520
|
+
const { resilientFetch } = await import("./util/resilientFetch.js");
|
|
521
|
+
const rpcUrl = process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
522
|
+
const res = await resilientFetch(rpcUrl, {
|
|
523
|
+
timeout: 10_000,
|
|
524
|
+
retries: 0,
|
|
525
|
+
method: "POST",
|
|
526
|
+
headers: { "Content-Type": "application/json" },
|
|
527
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "getHealth", params: [] }),
|
|
528
|
+
});
|
|
529
|
+
const json = await res.json();
|
|
530
|
+
if (json.result === "ok") {
|
|
531
|
+
console.log(T.success(" RPC healthy: " + rpcUrl));
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
console.log(T.warn(" RPC responded but unhealthy"));
|
|
535
|
+
healthy = false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
catch (e) {
|
|
539
|
+
console.log(T.error(" RPC unreachable: " + e.message));
|
|
540
|
+
healthy = false;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
console.log(T.muted(" Disk:"));
|
|
544
|
+
try {
|
|
545
|
+
const { writeFileSync, unlinkSync } = await import("node:fs");
|
|
546
|
+
const testFile = join(AIAIAI_HOME, ".health-test");
|
|
547
|
+
writeFileSync(testFile, "test", "utf-8");
|
|
548
|
+
unlinkSync(testFile);
|
|
549
|
+
console.log(T.success(" writable"));
|
|
550
|
+
}
|
|
551
|
+
catch (error) {
|
|
552
|
+
logger.warn('CLI', 'Disk not writable', { error: error.message });
|
|
553
|
+
console.log(T.error(" not writable"));
|
|
554
|
+
healthy = false;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
console.log(T.muted("\n Extras:"));
|
|
558
|
+
|
|
559
|
+
try {
|
|
560
|
+
const { getCurrentTheme } = await import("./tui/ThemePresets.js");
|
|
561
|
+
console.log(T.success(` Theme: ${getCurrentTheme()} (run aiaiai to change)`));
|
|
562
|
+
}
|
|
563
|
+
catch {
|
|
564
|
+
console.log(T.muted(" Theme: default"));
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
try {
|
|
568
|
+
const { clipboardSupported } = await import("./util/clipboard.js");
|
|
569
|
+
console.log(T.muted(` Clipboard: ${clipboardSupported()}`));
|
|
570
|
+
}
|
|
571
|
+
catch {
|
|
572
|
+
console.log(T.muted(" Clipboard: not available"));
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
try {
|
|
576
|
+
const { hasWebhooks } = await import("./util/webhooks.js");
|
|
577
|
+
console.log(hasWebhooks() ? T.success(" Webhooks: configured") : T.muted(" Webhooks: not configured (set WEBHOOK_DISCORD or WEBHOOK_TELEGRAM in .env)"));
|
|
578
|
+
}
|
|
579
|
+
catch {
|
|
580
|
+
console.log(T.muted(" Webhooks: not available"));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
console.log(T.muted(" Provider Keys:"));
|
|
584
|
+
const providers = [
|
|
585
|
+
{ name: "OpenRouter", key: "OPENROUTER_API_KEY" },
|
|
586
|
+
{ name: "Anthropic", key: "ANTHROPIC_API_KEY" },
|
|
587
|
+
{ name: "OpenAI", key: "OPENAI_API_KEY" },
|
|
588
|
+
{ name: "Google", key: "GOOGLE_API_KEY" },
|
|
589
|
+
{ name: "DeepSeek", key: "DEEPSEEK_API_KEY" },
|
|
590
|
+
{ name: "Groq", key: "GROQ_API_KEY" },
|
|
591
|
+
{ name: "GMGN", key: "GMGN_API_KEY" },
|
|
592
|
+
];
|
|
593
|
+
for (const p of providers) {
|
|
594
|
+
const has = process.env[p.key] || env.get(p.key);
|
|
595
|
+
console.log(has ? T.success(` ${p.name}: ✓`) : T.dim(` ${p.name}: ✗ (optional)`));
|
|
596
|
+
}
|
|
597
|
+
console.log("");
|
|
598
|
+
if (healthy) {
|
|
599
|
+
console.log(T.success(" All systems operational.\n"));
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
console.log(T.warn(" Some checks failed. Review above for details.\n"));
|
|
603
|
+
}
|
|
604
|
+
process.exit(healthy ? 0 : 1);
|
|
605
|
+
})().catch(e => { console.error(T.error("Health check failed: " + e.message)); process.exit(2); });
|
|
606
|
+
await new Promise(() => { });
|
|
609
607
|
}
|
|
610
608
|
if (subcmd === "sessions") {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
609
|
+
const sessions = sessionStore.list();
|
|
610
|
+
if (sessions.length === 0) {
|
|
611
|
+
console.log(T.muted(" No saved sessions."));
|
|
612
|
+
process.exit(0);
|
|
613
|
+
}
|
|
614
|
+
console.log(T.accent("\n 📂 Saved Sessions\n"));
|
|
615
|
+
sessions.slice(0, 15).forEach((s, i) => {
|
|
616
|
+
const date = new Date(s.updatedAt).toLocaleDateString();
|
|
617
|
+
console.log(T.muted(` ${String(i + 1).padStart(2)}. ${s.title} (${s.messageCount} msgs, ${s.model}, ${date})`));
|
|
618
|
+
});
|
|
619
|
+
console.log("");
|
|
620
|
+
process.exit(0);
|
|
623
621
|
}
|
|
624
622
|
if (subcmd === "resume") {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
|
|
623
|
+
const sessions = sessionStore.list();
|
|
624
|
+
if (sessions.length === 0) {
|
|
625
|
+
console.log(T.muted(" No saved sessions."));
|
|
626
|
+
process.exit(0);
|
|
627
|
+
}
|
|
628
|
+
const idx = parseInt(process.argv[3]) - 1;
|
|
629
|
+
if (isNaN(idx) || idx < 0 || idx >= sessions.length) {
|
|
630
|
+
console.log(T.error(" Invalid session number."));
|
|
631
|
+
process.exit(1);
|
|
632
|
+
}
|
|
633
|
+
const session = sessionStore.load(sessions[idx].id);
|
|
634
|
+
if (!session) {
|
|
635
|
+
console.log(T.error(" Session not found."));
|
|
636
|
+
process.exit(1);
|
|
637
|
+
}
|
|
638
|
+
console.log(T.accent(`\n 📂 Resumed: ${session.title}\n`));
|
|
639
|
+
console.log(T.muted(` Messages: ${session.messages.length}`));
|
|
640
|
+
console.log(T.muted(` Model: ${session.model}`));
|
|
641
|
+
console.log("");
|
|
642
|
+
process.exit(0);
|
|
643
|
+
}
|
|
644
|
+
|
|
647
645
|
let extensionPath = null;
|
|
648
646
|
let promptPath = null;
|
|
649
647
|
for (let i = 0; i < args.length; i++) {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
648
|
+
if (args[i] === "--extension" && args[i + 1])
|
|
649
|
+
extensionPath = args[i + 1];
|
|
650
|
+
if (args[i] === "--prompt" && args[i + 1])
|
|
651
|
+
promptPath = args[i + 1];
|
|
654
652
|
}
|
|
655
653
|
let systemPrompt = SYSTEM_PROMPT;
|
|
656
654
|
if (promptPath && existsSync(promptPath)) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
}
|
|
681
|
-
|
|
655
|
+
let rawPrompt = readFileSync(promptPath, "utf-8");
|
|
656
|
+
|
|
657
|
+
if (rawPrompt.length > 10_000) {
|
|
658
|
+
console.error(T.error("Prompt file too large (max 10KB)."));
|
|
659
|
+
process.exit(1);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
rawPrompt = rawPrompt.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
663
|
+
|
|
664
|
+
const dangerousPatterns = [
|
|
665
|
+
/ignore (all |previous |above|prior) instructions/i,
|
|
666
|
+
/you are now /i,
|
|
667
|
+
/new instructions/i,
|
|
668
|
+
/override (system|safety)/i,
|
|
669
|
+
];
|
|
670
|
+
for (const pattern of dangerousPatterns) {
|
|
671
|
+
if (pattern.test(rawPrompt)) {
|
|
672
|
+
console.error(T.error("Prompt file contains suspicious patterns. Use a simpler prompt."));
|
|
673
|
+
process.exit(1);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
systemPrompt = rawPrompt;
|
|
677
|
+
console.log(T.muted(" Custom prompt loaded: " + promptPath));
|
|
678
|
+
}
|
|
679
|
+
|
|
682
680
|
const headlessIdx = args.indexOf("--headless");
|
|
683
681
|
const headlessMsg = headlessIdx >= 0 ? args[headlessIdx + 1] : null;
|
|
684
682
|
if (headlessMsg) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
683
|
+
(async () => {
|
|
684
|
+
AgentDir.init();
|
|
685
|
+
const registry = new Registry();
|
|
686
|
+
registry.setSystemPrompt(systemPrompt);
|
|
687
|
+
if (extensionPath) {
|
|
688
|
+
try {
|
|
689
|
+
await loadExtension(extensionPath, registry);
|
|
690
|
+
}
|
|
691
|
+
catch (e) {
|
|
692
|
+
process.stderr.write(`Extension load failed: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
693
|
+
process.exit(1);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
await modelRegistry.initialise();
|
|
697
|
+
const session = new SessionManager();
|
|
698
|
+
session.setSystemPrompt(registry.getSystemPrompt() || systemPrompt);
|
|
699
|
+
const theme = makeTheme();
|
|
700
|
+
const nullUi = {
|
|
701
|
+
notify: () => { }, setStatus: () => { }, setTheme: () => { },
|
|
702
|
+
setHeader: () => { }, showModelSelector: () => { }, theme,
|
|
703
|
+
};
|
|
704
|
+
const sessionCtx = {
|
|
705
|
+
ui: nullUi, hasUI: false,
|
|
706
|
+
config: { OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY },
|
|
707
|
+
};
|
|
708
|
+
await registry.fireHook("session_start", sessionCtx);
|
|
709
|
+
let exitCode = 0;
|
|
710
|
+
const runner = new AgentRunner(registry, session, (event) => {
|
|
711
|
+
if (event.type === "text_delta")
|
|
712
|
+
process.stdout.write(event.text);
|
|
713
|
+
if (event.type === "turn_done")
|
|
714
|
+
process.stdout.write("\n");
|
|
715
|
+
if (event.type === "error") {
|
|
716
|
+
process.stderr.write(`\nError: ${event.message}\n`);
|
|
717
|
+
exitCode = 1;
|
|
718
|
+
}
|
|
719
|
+
}, sessionCtx, "normal", modelRegistry);
|
|
720
|
+
try {
|
|
721
|
+
await runner.run(headlessMsg);
|
|
722
|
+
}
|
|
723
|
+
catch (e) {
|
|
724
|
+
process.stderr.write(`Runner error: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
725
|
+
exitCode = 1;
|
|
726
|
+
}
|
|
727
|
+
await registry.fireHook("session_end", sessionCtx);
|
|
728
|
+
process.exit(exitCode);
|
|
729
|
+
})();
|
|
732
730
|
}
|
|
733
731
|
else {
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
792
|
-
//# sourceMappingURL=cli.js.map
|
|
732
|
+
|
|
733
|
+
(async () => {
|
|
734
|
+
AgentDir.init();
|
|
735
|
+
console.clear();
|
|
736
|
+
console.log(T.accent(`
|
|
737
|
+
█████╗ ██╗ █████╗ ██╗ █████╗ ██╗
|
|
738
|
+
██╔══██╗██║██╔══██╗██║██╔══██╗██║
|
|
739
|
+
███████║██║███████║██║███████║██║
|
|
740
|
+
██╔══██║██║██╔══██║██║██╔══██║██║
|
|
741
|
+
██║ ██║██║██║ ██║██║██║ ██║██║
|
|
742
|
+
╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝
|
|
743
|
+
`));
|
|
744
|
+
console.log(T.muted(" Solana-native AI agent — $AIAIAI · all local, zero exposure\n"));
|
|
745
|
+
const registry = new Registry();
|
|
746
|
+
registry.setSystemPrompt(systemPrompt);
|
|
747
|
+
let _notifyFn = null;
|
|
748
|
+
let _setStatusFn = null;
|
|
749
|
+
let _showModelSelectorFn = null;
|
|
750
|
+
if (extensionPath) {
|
|
751
|
+
try {
|
|
752
|
+
console.log(T.muted(` Loading: ${extensionPath}`));
|
|
753
|
+
await loadExtension(extensionPath, registry, {
|
|
754
|
+
onNotify: (msg) => { _notifyFn?.(msg); },
|
|
755
|
+
onStatusUpdate: (k, v) => { _setStatusFn?.(k, v); },
|
|
756
|
+
onShowModelSelector: (q) => { _showModelSelectorFn?.(q); },
|
|
757
|
+
});
|
|
758
|
+
console.log(T.success(` ✓ ${registry.listTools().length} tools · ${registry.listCommands().length} commands`));
|
|
759
|
+
}
|
|
760
|
+
catch (e) {
|
|
761
|
+
console.error(T.error(` ✗ Extension load failed: ${e.message}`));
|
|
762
|
+
process.exit(1);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (!process.env.OPENROUTER_API_KEY) {
|
|
766
|
+
console.log(T.warn(" No API key found. Run: aiaiaichain setup\n"));
|
|
767
|
+
}
|
|
768
|
+
const costTracker = new CostTracker(modelRegistry);
|
|
769
|
+
console.log(T.muted(" Discovering available models via OpenRouter…"));
|
|
770
|
+
await modelRegistry.initialise();
|
|
771
|
+
console.log(T.success(` ✓ ${modelRegistry.modelCount} models available\n`));
|
|
772
|
+
await new Promise(r => setTimeout(r, 500));
|
|
773
|
+
console.clear();
|
|
774
|
+
render(React.createElement(App, {
|
|
775
|
+
registry,
|
|
776
|
+
systemPrompt,
|
|
777
|
+
chain: "solana",
|
|
778
|
+
modelReg: modelRegistry,
|
|
779
|
+
costTracker,
|
|
780
|
+
onNotifyReady: (fn) => { _notifyFn = fn; wireNotify(fn); },
|
|
781
|
+
onStatusReady: (fn) => { _setStatusFn = fn; },
|
|
782
|
+
onModelSelectorReady: (fn) => { _showModelSelectorFn = fn; },
|
|
783
|
+
}), { exitOnCtrlC: false });
|
|
784
|
+
process.prependListener("SIGWINCH", () => { process.stdout.write("\x1B[2J\x1B[H"); });
|
|
785
|
+
console.log = safeLog;
|
|
786
|
+
console.error = safeLog;
|
|
787
|
+
console.warn = safeLog;
|
|
788
|
+
})();
|
|
789
|
+
}
|