@aiaiaichain/agent 0.1.4 → 0.1.5
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/cli.js +218 -5
- package/dist/core/ChainConfig.js +1 -1
- package/dist/core/SystemMonitor.d.ts +1 -4
- package/dist/core/SystemMonitor.js +20 -46
- package/dist/index.d.ts +10 -0
- package/dist/index.js +11 -0
- package/dist/models/ModelRegistry.js +12 -4
- package/dist/runner/AgentRunner.d.ts +2 -0
- package/dist/runner/AgentRunner.js +18 -1
- package/dist/runner/ModelClient.js +109 -48
- package/dist/session/SessionManager.d.ts +1 -0
- package/dist/session/SessionManager.js +8 -2
- package/dist/session/SessionStore.js +8 -3
- package/dist/tools/CrossTools.js +13 -5
- package/dist/tools/MarketSentiment.js +22 -13
- package/dist/tools/NewsSentiment.js +9 -3
- package/dist/tools/PriceFeed.js +11 -4
- package/dist/tools/TechnicalAnalysis.js +2 -1
- package/dist/tools/TokenCalendar.d.ts +24 -0
- package/dist/tools/TokenCalendar.js +81 -0
- package/dist/tools/TokenSecurityScanner.d.ts +22 -0
- package/dist/tools/TokenSecurityScanner.js +102 -0
- package/dist/tools/TransactionSim.d.ts +17 -0
- package/dist/tools/TransactionSim.js +78 -0
- package/dist/tui/App.js +143 -21
- package/dist/tui/REPL.js +2 -2
- package/dist/tui/Sparkline.d.ts +21 -0
- package/dist/tui/Sparkline.js +44 -0
- package/dist/tui/ThemePresets.d.ts +25 -0
- package/dist/tui/ThemePresets.js +117 -0
- package/dist/util/clipboard.d.ts +9 -0
- package/dist/util/clipboard.js +26 -0
- package/dist/util/commandSuggest.d.ts +7 -0
- package/dist/util/commandSuggest.js +44 -0
- package/dist/util/confirmation.d.ts +6 -0
- package/dist/util/confirmation.js +16 -0
- package/dist/util/errorHandler.d.ts +3 -0
- package/dist/util/errorHandler.js +28 -0
- package/dist/util/logger.d.ts +11 -0
- package/dist/util/logger.js +43 -0
- package/dist/util/processManager.d.ts +5 -0
- package/dist/util/processManager.js +39 -0
- package/dist/util/resilientFetch.d.ts +21 -0
- package/dist/util/resilientFetch.js +94 -0
- package/dist/util/responseCache.d.ts +27 -0
- package/dist/util/responseCache.js +54 -0
- package/dist/util/safeLog.d.ts +4 -5
- package/dist/util/safeLog.js +68 -30
- package/dist/util/scheduler.d.ts +14 -0
- package/dist/util/scheduler.js +75 -0
- package/dist/util/webhooks.d.ts +9 -0
- package/dist/util/webhooks.js +75 -0
- package/dist/wallet/ActionFeed.js +12 -4
- package/dist/wallet/AgentWallet.d.ts +1 -0
- package/dist/wallet/AgentWallet.js +30 -5
- package/dist/wallet/ProfitTracker.d.ts +30 -0
- package/dist/wallet/ProfitTracker.js +93 -0
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/TokenSecurityScanner.ts - honeypot/rugpull detection for Solana tokens
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
5
|
+
export interface TokenSecurityResult {
|
|
6
|
+
address: string;
|
|
7
|
+
symbol: string;
|
|
8
|
+
name: string;
|
|
9
|
+
isHoneypot: boolean;
|
|
10
|
+
isRugRisk: boolean;
|
|
11
|
+
mintAuthorityRenounced: boolean;
|
|
12
|
+
freezeAuthorityRenounced: boolean;
|
|
13
|
+
liquidityLocked: boolean;
|
|
14
|
+
top10HolderPct: number;
|
|
15
|
+
warnings: string[];
|
|
16
|
+
score: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const tokenSecurityParams: import("@sinclair/typebox").TObject<{
|
|
19
|
+
address: import("@sinclair/typebox").TString;
|
|
20
|
+
}>;
|
|
21
|
+
export declare function scanTokenSecurityTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
22
|
+
//# sourceMappingURL=TokenSecurityScanner.d.ts.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/TokenSecurityScanner.ts - honeypot/rugpull detection for Solana tokens
|
|
3
|
+
*/
|
|
4
|
+
import { Type } from "@sinclair/typebox";
|
|
5
|
+
import { resilientFetch } from "../util/resilientFetch.js";
|
|
6
|
+
import { logger } from "../util/logger.js";
|
|
7
|
+
export const tokenSecurityParams = Type.Object({
|
|
8
|
+
address: Type.String({ description: "Token mint address on Solana" }),
|
|
9
|
+
});
|
|
10
|
+
export async function scanTokenSecurityTool(_id, params) {
|
|
11
|
+
const address = params.address;
|
|
12
|
+
if (!address || address.length < 32 || address.length > 44) {
|
|
13
|
+
return {
|
|
14
|
+
content: [{ type: "text", text: "Invalid token address format." }],
|
|
15
|
+
isError: true,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const warnings = [];
|
|
19
|
+
let score = 100;
|
|
20
|
+
let isHoneypot = false;
|
|
21
|
+
let isRugRisk = false;
|
|
22
|
+
let dexData = null;
|
|
23
|
+
try {
|
|
24
|
+
const resp = await resilientFetch(`https://api.dexscreener.com/tokens/v1/solana/${address}`, {
|
|
25
|
+
timeout: 10_000,
|
|
26
|
+
retries: 1,
|
|
27
|
+
});
|
|
28
|
+
if (resp.ok) {
|
|
29
|
+
const data = await resp.json();
|
|
30
|
+
if (data && data.length > 0)
|
|
31
|
+
dexData = data[0];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
logger.warn("TokenSecurity", "DexScreener lookup failed", { address, error: error.message });
|
|
36
|
+
}
|
|
37
|
+
if (!dexData) {
|
|
38
|
+
warnings.push("No DEX liquidity found - token may be dead or not traded");
|
|
39
|
+
score -= 50;
|
|
40
|
+
isRugRisk = true;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const liquidity = dexData.liquidity?.usd ?? 0;
|
|
44
|
+
if (liquidity < 1000) {
|
|
45
|
+
warnings.push(`Low liquidity: $${liquidity.toFixed(0)}`);
|
|
46
|
+
score -= 30;
|
|
47
|
+
isRugRisk = true;
|
|
48
|
+
}
|
|
49
|
+
else if (liquidity < 10000) {
|
|
50
|
+
warnings.push(`Moderate liquidity: $${liquidity.toFixed(0)}`);
|
|
51
|
+
score -= 10;
|
|
52
|
+
}
|
|
53
|
+
const volume = dexData.volume?.h24 ?? 0;
|
|
54
|
+
if (volume < 100) {
|
|
55
|
+
warnings.push(`Very low 24h volume: $${volume.toFixed(0)}`);
|
|
56
|
+
score -= 20;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const rugResp = await resilientFetch(`https://api.rugcheck.xyz/v1/tokens/${address}/report`, {
|
|
61
|
+
timeout: 8_000,
|
|
62
|
+
retries: 0,
|
|
63
|
+
});
|
|
64
|
+
if (rugResp.ok) {
|
|
65
|
+
const report = await rugResp.json();
|
|
66
|
+
if (report.status === "WARNING" || report.status === "BLOCKED") {
|
|
67
|
+
warnings.push(`RugCheck status: ${report.status}`);
|
|
68
|
+
score -= 40;
|
|
69
|
+
isRugRisk = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger.warn('TokenSecurity', 'RugCheck lookup failed (optional)', { address, error: error.message });
|
|
75
|
+
}
|
|
76
|
+
const symbol = dexData?.baseToken?.symbol ?? "???";
|
|
77
|
+
const name = dexData?.baseToken?.name ?? "Unknown";
|
|
78
|
+
const scoreLabel = score >= 70 ? "SAFE" : score >= 40 ? "CAUTION" : "DANGEROUS";
|
|
79
|
+
const lines = [
|
|
80
|
+
"Token Security Scan",
|
|
81
|
+
"",
|
|
82
|
+
`Token: ${name} ($${symbol})`,
|
|
83
|
+
`Address: ${address.slice(0, 8)}...${address.slice(-6)}`,
|
|
84
|
+
`Score: ${scoreLabel} (${score}/100)`,
|
|
85
|
+
"",
|
|
86
|
+
];
|
|
87
|
+
if (warnings.length > 0) {
|
|
88
|
+
lines.push("Warnings:");
|
|
89
|
+
for (const w of warnings)
|
|
90
|
+
lines.push(" - " + w);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
lines.push("No immediate risks detected.");
|
|
94
|
+
}
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push("This is not financial advice. Always verify before trading.");
|
|
97
|
+
return {
|
|
98
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
99
|
+
details: { address, symbol, name, score, isHoneypot, isRugRisk, warnings },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=TokenSecurityScanner.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/TransactionSim.ts — Simulate Solana transactions before execution.
|
|
3
|
+
* Uses public RPC simulateTransaction for pre-flight checks.
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
6
|
+
export interface SimResult {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
logs: string[];
|
|
9
|
+
unitsConsumed: number;
|
|
10
|
+
fee: number;
|
|
11
|
+
error?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const simulateTxParams: import("@sinclair/typebox").TObject<{
|
|
14
|
+
transaction: import("@sinclair/typebox").TString;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function simulateTxTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
17
|
+
//# sourceMappingURL=TransactionSim.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tools/TransactionSim.ts — Simulate Solana transactions before execution.
|
|
3
|
+
* Uses public RPC simulateTransaction for pre-flight checks.
|
|
4
|
+
*/
|
|
5
|
+
import { Type } from "@sinclair/typebox";
|
|
6
|
+
import { resilientFetch } from "../util/resilientFetch.js";
|
|
7
|
+
import { logger } from "../util/logger.js";
|
|
8
|
+
function getRpcUrl() {
|
|
9
|
+
return process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
|
10
|
+
}
|
|
11
|
+
export const simulateTxParams = Type.Object({
|
|
12
|
+
transaction: Type.String({ description: "Base64-encoded transaction to simulate" }),
|
|
13
|
+
});
|
|
14
|
+
export async function simulateTxTool(_id, params) {
|
|
15
|
+
const tx = params.transaction || "";
|
|
16
|
+
if (!tx || tx.length < 10) {
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: "Invalid transaction: must be base64-encoded Solana transaction." }],
|
|
19
|
+
isError: true,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const body = JSON.stringify({
|
|
24
|
+
jsonrpc: "2.0", id: 1,
|
|
25
|
+
method: "simulateTransaction",
|
|
26
|
+
params: [
|
|
27
|
+
tx,
|
|
28
|
+
{ sigVerify: false, commitment: "processed", encoding: "base64" },
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
const response = await resilientFetch(getRpcUrl(), {
|
|
32
|
+
timeout: 15_000, retries: 1,
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
body,
|
|
36
|
+
});
|
|
37
|
+
const data = await response.json();
|
|
38
|
+
const result = data?.result?.value ?? data?.result;
|
|
39
|
+
if (!result) {
|
|
40
|
+
const errMsg = data?.error?.message ?? "Unknown simulation error";
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: `❌ Simulation failed: ${errMsg}` }],
|
|
43
|
+
isError: true,
|
|
44
|
+
details: { ok: false, error: errMsg, logs: [], unitsConsumed: 0, fee: 0 },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const ok = !result.err;
|
|
48
|
+
const unitsConsumed = result.unitsConsumed ?? 0;
|
|
49
|
+
const logs = (result.logs ?? []);
|
|
50
|
+
const fee = (result.fee ?? 0) / 1e9 * 0.000005; // rough estimate
|
|
51
|
+
const error = result.err ? JSON.stringify(result.err) : undefined;
|
|
52
|
+
const lines = [
|
|
53
|
+
ok ? "✅ Transaction simulation: SUCCESS" : "❌ Transaction simulation: FAILED",
|
|
54
|
+
"",
|
|
55
|
+
`Units: ${unitsConsumed.toLocaleString()}`,
|
|
56
|
+
`Est. Fee: ${fee.toFixed(6)} SOL`,
|
|
57
|
+
"",
|
|
58
|
+
];
|
|
59
|
+
if (logs.length > 0) {
|
|
60
|
+
lines.push("Logs:");
|
|
61
|
+
logs.slice(-8).forEach(l => lines.push(` ${l}`));
|
|
62
|
+
}
|
|
63
|
+
if (error)
|
|
64
|
+
lines.push(`Error: ${error}`);
|
|
65
|
+
return {
|
|
66
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
67
|
+
details: { ok, error: error, logs, unitsConsumed, fee },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
logger.warn("TransactionSim", "Simulation failed", { error: error.message });
|
|
72
|
+
return {
|
|
73
|
+
content: [{ type: "text", text: "⚠️ Transaction simulation unavailable (RPC may be rate-limited)." }],
|
|
74
|
+
isError: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=TransactionSim.js.map
|
package/dist/tui/App.js
CHANGED
|
@@ -30,6 +30,13 @@ import { actionFeed } from "../wallet/ActionFeed.js";
|
|
|
30
30
|
import { gmgnTool, gmgnToolParams, gmgnHelp, gmgnStatus, gmgnMarketTool, gmgnMarketToolParams } from "../tools/GmgnIntegration.js";
|
|
31
31
|
import { watchTokenTool, watchTokenParams, removeWatchTool, removeWatchParams, listWatchTool, listWatchParams, addAlertTool, addAlertParams, checkAlertsTool, checkAlertsParams, compareTokensTool, compareTokensParams, portfolioTool, portfolioParams, getWatchList as _getWatchList, checkAlerts as _checkAlerts, } from "../tools/CrossTools.js";
|
|
32
32
|
import { systemMonitor } from "../core/SystemMonitor.js";
|
|
33
|
+
import { Sparkline, PriceHistory } from "./Sparkline.js";
|
|
34
|
+
import { launchCalendarTool, getLaunchSummary } from "../tools/TokenCalendar.js";
|
|
35
|
+
import { simulateTxTool } from "../tools/TransactionSim.js";
|
|
36
|
+
import { getPresetColors, listThemes, setTheme as setThemePreset } from "./ThemePresets.js";
|
|
37
|
+
import { copyToClipboard, clipboardSupported } from "../util/clipboard.js";
|
|
38
|
+
import { suggestCommands } from "../util/commandSuggest.js";
|
|
39
|
+
import { notify as notifyWebhook, hasWebhooks } from "../util/webhooks.js";
|
|
33
40
|
function getContextBar(session) {
|
|
34
41
|
if (!session)
|
|
35
42
|
return { pct: 0, bar: "░".repeat(20), color: AIAIAI_COLORS.dim };
|
|
@@ -102,9 +109,11 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
102
109
|
const [uptime, setUptime] = useState("0m");
|
|
103
110
|
const [apiCalls, setApiCalls] = useState(0);
|
|
104
111
|
const [watchList, setWatchList] = useState([]);
|
|
112
|
+
const priceHistoryRef = useRef(new PriceHistory(40));
|
|
105
113
|
const runnerRef = useRef(null);
|
|
106
114
|
const sessionRef = useRef(null);
|
|
107
115
|
const sessionCtxRef = useRef(null);
|
|
116
|
+
const messagesRef = useRef([]);
|
|
108
117
|
const theme = makeTheme();
|
|
109
118
|
let modelName = "no-model";
|
|
110
119
|
try {
|
|
@@ -112,7 +121,11 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
112
121
|
}
|
|
113
122
|
catch { /* shown via banner */ }
|
|
114
123
|
const push = useCallback((msg) => {
|
|
115
|
-
setMessages(prev =>
|
|
124
|
+
setMessages(prev => {
|
|
125
|
+
const next = [...prev, { ...msg, id: nextId(), ts: Date.now() }];
|
|
126
|
+
messagesRef.current = next;
|
|
127
|
+
return next;
|
|
128
|
+
});
|
|
116
129
|
}, []);
|
|
117
130
|
const notify = useCallback((content) => { push({ role: "notify", content }); }, [push]);
|
|
118
131
|
const setStatus = useCallback((key, value) => {
|
|
@@ -187,13 +200,27 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
187
200
|
// ── Main effect: setup + intervals ──────────────────────────────────────
|
|
188
201
|
useEffect(() => {
|
|
189
202
|
registerBuiltinTools();
|
|
190
|
-
// Initial price fetch
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
203
|
+
// Initial price fetch with retry
|
|
204
|
+
const fetchPriceWithRetry = async (retries = 3, delay = 2000) => {
|
|
205
|
+
for (let i = 0; i < retries; i++) {
|
|
206
|
+
try {
|
|
207
|
+
const p = await priceFeed.getAiaiaiPrice();
|
|
208
|
+
setAiaiPrice({ priceUsd: p.priceUsd, change: p.priceChange24h, mcap: p.marketCap, liq: p.liquidityUsd });
|
|
209
|
+
if (p.priceUsd)
|
|
210
|
+
setPriceBadge(`$${parseFloat(p.priceUsd).toFixed(6)}`);
|
|
211
|
+
actionFeed.setPrice(parseFloat(p.priceUsd || "0.0004"));
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
if (i === retries - 1)
|
|
216
|
+
throw e;
|
|
217
|
+
await new Promise(r => setTimeout(r, delay * (i + 1)));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
fetchPriceWithRetry().catch(() => {
|
|
222
|
+
console.error('Initial price fetch failed after retries');
|
|
223
|
+
});
|
|
197
224
|
// Initial wallet fetches
|
|
198
225
|
agentWallet.getAll().then(w => {
|
|
199
226
|
setColdBalance({ sol: w.cold.sol, aiaiai: w.cold.aiaiai, usdc: w.cold.usdc });
|
|
@@ -226,8 +253,10 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
226
253
|
const priceInterval = setInterval(() => {
|
|
227
254
|
priceFeed.getAiaiaiPrice().then(p => {
|
|
228
255
|
setAiaiPrice({ priceUsd: p.priceUsd, change: p.priceChange24h, mcap: p.marketCap, liq: p.liquidityUsd });
|
|
229
|
-
if (p.priceUsd)
|
|
256
|
+
if (p.priceUsd) {
|
|
230
257
|
setPriceBadge(`$${parseFloat(p.priceUsd).toFixed(6)}`);
|
|
258
|
+
priceHistoryRef.current.push(parseFloat(p.priceUsd));
|
|
259
|
+
}
|
|
231
260
|
actionFeed.setPrice(parseFloat(p.priceUsd || "0.0004"));
|
|
232
261
|
systemMonitor.trackApiCall();
|
|
233
262
|
// Check alerts
|
|
@@ -235,6 +264,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
235
264
|
const triggered = _checkAlerts(parseFloat(p.priceUsd), "AIAIAI");
|
|
236
265
|
for (const alert of triggered) {
|
|
237
266
|
notify(`🔔 Alert triggered: ${alert.type} $${alert.price} — $AIAIAI is now $${p.priceUsd}`);
|
|
267
|
+
notifyWebhook(`🔔 **Alert**: ${alert.type} $${alert.price} — $AIAIAI now $${p.priceUsd}`).catch(() => { });
|
|
238
268
|
}
|
|
239
269
|
}
|
|
240
270
|
}).catch(() => { });
|
|
@@ -268,12 +298,12 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
268
298
|
setUptime(stats.uptime);
|
|
269
299
|
setApiCalls(systemMonitor.resetApiCounter());
|
|
270
300
|
}, 10_000);
|
|
271
|
-
// Session auto-save (30s)
|
|
272
|
-
sessionStore.startAutoSave(() =>
|
|
301
|
+
// Session auto-save (30s) — use ref to avoid stale closure
|
|
302
|
+
sessionStore.startAutoSave(() => messagesRef.current);
|
|
273
303
|
sessionStore.setCurrentId(sessionId);
|
|
274
304
|
const saveInterval = setInterval(() => {
|
|
275
|
-
if (
|
|
276
|
-
sessionStore.save(
|
|
305
|
+
if (messagesRef.current.length > 0)
|
|
306
|
+
sessionStore.save(messagesRef.current);
|
|
277
307
|
}, 30_000);
|
|
278
308
|
const session = new SessionManager();
|
|
279
309
|
session.setSystemPrompt(registry.getSystemPrompt() || systemPrompt || "You are AIAIAI Chain Agent.");
|
|
@@ -375,7 +405,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
375
405
|
return;
|
|
376
406
|
}
|
|
377
407
|
if (cmd === "help") {
|
|
378
|
-
notify("Commands:\n/token info|security|holders|traders\n/track kol|smartmoney|follow-wallet\n/market kline|trending|trenches|signal\n/watch /unwatch /watchlist /alerts /alert /compare /portfolio\n/keys /wallet /deposit /burn /actions /fees\n/models /cost /goals /schedule /update\n/sessions /resume /memory /clear /exit\n\nTab to auto-complete, ↑↓ for history, Shift+Enter for multi-line");
|
|
408
|
+
notify("Commands:\n/token info|security|holders|traders\n/track kol|smartmoney|follow-wallet\n/market kline|trending|trenches|signal\n/watch /unwatch /watchlist /alerts /alert /compare /portfolio\n/keys /wallet /deposit /burn /actions /fees\n/models /cost /goals /schedule /update /diff\n/sessions /resume /memory /clear /exit\n/launches /theme /copy /simulate /explain /webhook /clipboard\n\nTab to auto-complete, ↑↓ for history, Shift+Enter for multi-line");
|
|
379
409
|
return;
|
|
380
410
|
}
|
|
381
411
|
// ── GMGN direct commands ──────────────────────────────────────────
|
|
@@ -651,9 +681,103 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
651
681
|
notify(result.content[0].text);
|
|
652
682
|
return;
|
|
653
683
|
}
|
|
684
|
+
// ── New feature commands ─────────────────────────────────────────
|
|
685
|
+
if (cmd === "launches" || cmd === "calendar") {
|
|
686
|
+
const result = await launchCalendarTool("", { chain: args || "solana", limit: 15 });
|
|
687
|
+
notify(result.content[0].text);
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
if (cmd === "diff" || cmd === "compared") {
|
|
691
|
+
const sessions = sessionStore.list();
|
|
692
|
+
if (sessions.length < 2) {
|
|
693
|
+
notify("Need at least 2 saved sessions to compare. Start a new session with /exit and restart.");
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
const latest = sessions[0];
|
|
697
|
+
const prev = sessions[1];
|
|
698
|
+
if (!latest || !prev) {
|
|
699
|
+
notify("Could not load sessions for comparison.");
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const lines = [
|
|
703
|
+
`📊 Session Diff`,
|
|
704
|
+
`Current: ${latest.title} (${latest.messageCount} msgs)`,
|
|
705
|
+
`Previous: ${prev.title} (${prev.messageCount} msgs)`,
|
|
706
|
+
`Difference: ${latest.messageCount - prev.messageCount} messages`,
|
|
707
|
+
`Last active: ${new Date(latest.updatedAt).toLocaleString()}`,
|
|
708
|
+
];
|
|
709
|
+
notify(lines.join("\n"));
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (cmd === "copy" && args.trim()) {
|
|
713
|
+
const ok = copyToClipboard(args.trim());
|
|
714
|
+
notify(ok ? T.success(`✓ Copied to clipboard: ${args.slice(0, 30)}…`) : T.error("Clipboard not supported in this terminal. Try: " + clipboardSupported()));
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
if (cmd === "theme") {
|
|
718
|
+
if (!args || args === "list") {
|
|
719
|
+
const current = getPresetColors();
|
|
720
|
+
notify(`🎨 Themes\n${listThemes()}\n\nApply: /theme <name>`);
|
|
721
|
+
}
|
|
722
|
+
else if (setThemePreset(args)) {
|
|
723
|
+
notify(T.success(`✓ Theme set to "${args}". Restart to apply.`));
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
notify(T.error(`Unknown theme "${args}". Try: /theme list`));
|
|
727
|
+
}
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (cmd === "simulate" || cmd === "sim") {
|
|
731
|
+
if (!args.trim()) {
|
|
732
|
+
notify(T.error("Usage: /simulate <base64-tx>"));
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
const result = await simulateTxTool("", { transaction: args.trim() });
|
|
736
|
+
notify(result.content[0].text);
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (cmd === "explain") {
|
|
740
|
+
if (!modelReg) {
|
|
741
|
+
notify(T.error("Model registry not available"));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const lastAssistant = [...messages].reverse().find(m => m.role === "tool");
|
|
745
|
+
if (!lastAssistant) {
|
|
746
|
+
notify("No tool result to explain. Run a tool first.");
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
push({ role: "user", content: `Explain this tool result in simple terms:\n${lastAssistant.content.slice(0, 2000)}` });
|
|
750
|
+
setDisabled(true);
|
|
751
|
+
setStreaming("");
|
|
752
|
+
try {
|
|
753
|
+
await runnerRef.current.run(`Explain this tool result simply:\n${lastAssistant.content.slice(0, 2000)}`);
|
|
754
|
+
}
|
|
755
|
+
catch (e) {
|
|
756
|
+
setDisabled(false);
|
|
757
|
+
notify(T.error(`Error: ${e.message}`));
|
|
758
|
+
}
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
if (cmd === "webhook" || cmd === "webhooks") {
|
|
762
|
+
if (hasWebhooks()) {
|
|
763
|
+
notify("✅ Webhooks configured\n\nUsage: /webhook test\nConfig: WEBHOOK_DISCORD / WEBHOOK_TELEGRAM in ~/.aiaiai/.env");
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
notify("No webhooks configured.\nAdd WEBHOOK_DISCORD=... or WEBHOOK_TELEGRAM=... to ~/.aiaiai/.env");
|
|
767
|
+
}
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
if (cmd === "clipboard") {
|
|
771
|
+
notify(clipboardSupported());
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
654
774
|
const def = registry.getCommand(cmd);
|
|
655
775
|
if (!def) {
|
|
656
|
-
|
|
776
|
+
const suggestions = suggestCommands(cmd);
|
|
777
|
+
const tip = suggestions.length > 0
|
|
778
|
+
? `\nDid you mean: ${suggestions.map(s => `/${s}`).join(", ")}?`
|
|
779
|
+
: "";
|
|
780
|
+
notify(T.error(`Unknown: /${cmd} — try /help${tip}`));
|
|
657
781
|
return;
|
|
658
782
|
}
|
|
659
783
|
try {
|
|
@@ -717,10 +841,8 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
717
841
|
const SIDEBAR_MIN = 38;
|
|
718
842
|
const changeColor = (pct) => pct > 0 ? AIAIAI_COLORS.success : pct < 0 ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
719
843
|
const actionIcon = (type) => type === "buy" ? "↗" : type === "burn" ? "🔥" : "→";
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
}
|
|
723
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusBar, { model: modelName, chain: chain, price: priceBadge, toolRunning: toolRunning, connected: true, statusLine: statusLine, cpu: cpu, ram: ram, uptime: uptime, apiCalls: apiCalls }), _jsxs(Box, { flexDirection: "row", flexGrow: 1, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", width: SIDEBAR_W, minWidth: SIDEBAR_MIN, flexShrink: 0, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.accent, paddingX: 1, children: [_jsx(Text, { bold: true, color: AIAIAI_COLORS.accent, children: "\uD83E\uDD16 $AIAIAI" }), aiaiPrice ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: changeColor(aiaiPrice.change), children: [aiaiPrice.priceUsd ? `$${parseFloat(aiaiPrice.priceUsd).toFixed(8)}` : "N/A", " ", aiaiPrice.change > 0 ? "▲" : aiaiPrice.change < 0 ? "▼" : "─", Math.abs(aiaiPrice.change).toFixed(1), "%"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["MCap: ", aiaiPrice.mcap ? `$${(aiaiPrice.mcap / 1000).toFixed(1)}k` : "N/A"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Liq: $", (aiaiPrice.liq / 1000).toFixed(1), "k"] })] })) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDCBC Wallets" }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Cold: ", coldBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", coldBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Action: ", actionBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", actionBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Deposit: ", depositBalance.usdc.toFixed(2), " USDC"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" SOL: ", depositBalance.sol.toFixed(2)] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\u26A1 Actions" }), recentActions.length > 0 ? recentActions.map((a, i) => {
|
|
844
|
+
// Single StatusBar wrapper — shared across both views to prevent duplication
|
|
845
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(StatusBar, { model: modelName, chain: chain, price: priceBadge, toolRunning: toolRunning, connected: true, statusLine: statusLine, cpu: cpu, ram: ram, uptime: uptime, apiCalls: apiCalls }), showModelSelector ? (_jsx(ModelSelector, { models: modelList, currentModelId: process.env.DEFAULT_MODEL ?? "", onSelect: handleModelSelect, onCancel: handleModelCancel, initialQuery: modelSelectorInitialQuery })) : (_jsxs(Box, { flexDirection: "row", flexGrow: 1, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", width: SIDEBAR_W, minWidth: SIDEBAR_MIN, flexShrink: 0, overflow: "hidden", children: [_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.accent, paddingX: 1, children: [_jsx(Text, { bold: true, color: AIAIAI_COLORS.accent, children: "\uD83E\uDD16 $AIAIAI" }), aiaiPrice ? (_jsxs(_Fragment, { children: [_jsxs(Text, { color: changeColor(aiaiPrice.change), children: [aiaiPrice.priceUsd ? `$${parseFloat(aiaiPrice.priceUsd).toFixed(8)}` : "N/A", " ", aiaiPrice.change > 0 ? "▲" : aiaiPrice.change < 0 ? "▼" : "─", Math.abs(aiaiPrice.change).toFixed(1), "%"] }), _jsx(Sparkline, { data: priceHistoryRef.current.getData(), width: 38, color: changeColor(aiaiPrice.change), label: "" }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["MCap: ", aiaiPrice.mcap ? `$${(aiaiPrice.mcap / 1000).toFixed(1)}k` : "N/A"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Liq: $", (aiaiPrice.liq / 1000).toFixed(1), "k"] })] })) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDCBC Wallets" }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Cold: ", coldBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", coldBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Action: ", actionBalance.sol.toFixed(2), " SOL"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" AIAIAI: ", actionBalance.aiaiai.toLocaleString(undefined, { maximumFractionDigits: 0 })] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["Deposit: ", depositBalance.usdc.toFixed(2), " USDC"] }), _jsxs(Text, { color: AIAIAI_COLORS.muted, children: [" SOL: ", depositBalance.sol.toFixed(2)] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\u26A1 Actions" }), recentActions.length > 0 ? recentActions.map((a, i) => {
|
|
724
846
|
const col = a.type === "buy" ? AIAIAI_COLORS.success : a.type === "burn" ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
725
847
|
const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
726
848
|
return _jsxs(Text, { color: col, children: [actionIcon(a.type), " ", time, " ", a.type, " ", a.amount.toLocaleString()] }, i);
|
|
@@ -730,7 +852,7 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
730
852
|
const sentColor = n.sentiment > 0.3 ? AIAIAI_COLORS.success : n.sentiment < -0.3 ? AIAIAI_COLORS.error : AIAIAI_COLORS.muted;
|
|
731
853
|
const title = n.title.length > 30 ? n.title.slice(0, 28) + "…" : n.title;
|
|
732
854
|
return _jsx(Text, { color: sentColor, children: title }, i);
|
|
733
|
-
}) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "Context" }), _jsxs(Text, { color: ctx.color, children: [ctx.bar, " ", ctx.pct, "%"] })] })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, children: _jsx(REPL, { messages: messages, streamingText: streaming, toolRunning: toolRunning, onSubmit: handleSubmit, disabled: disabled, onAbort: () => {
|
|
855
|
+
}) : _jsx(Text, { color: AIAIAI_COLORS.muted, children: "Loading\u2026" })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "Context" }), _jsxs(Text, { color: ctx.color, children: [ctx.bar, " ", ctx.pct, "%"] })] }), _jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AIAIAI_COLORS.dim, paddingX: 1, marginTop: 1, children: [_jsx(Text, { bold: true, children: "\uD83D\uDE80 Recent" }), _jsx(Text, { color: AIAIAI_COLORS.muted, children: getLaunchSummary() })] })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, children: _jsx(REPL, { messages: messages, streamingText: streaming, toolRunning: toolRunning, onSubmit: handleSubmit, disabled: disabled, onAbort: () => {
|
|
734
856
|
runnerRef.current?.abort();
|
|
735
857
|
setDisabled(false);
|
|
736
858
|
setToolRunning(null);
|
|
@@ -740,6 +862,6 @@ export function App({ registry, systemPrompt, chain: initialChain = "solana", mo
|
|
|
740
862
|
return "";
|
|
741
863
|
});
|
|
742
864
|
push({ role: "system", content: T.dim("— stream interrupted —") });
|
|
743
|
-
} }) })] })] }));
|
|
865
|
+
} }) })] }))] }));
|
|
744
866
|
}
|
|
745
867
|
//# sourceMappingURL=App.js.map
|
package/dist/tui/REPL.js
CHANGED
|
@@ -208,7 +208,7 @@ function InputBox({ value, onChange, onSubmit, disabled, onAbort }) {
|
|
|
208
208
|
export function REPL({ messages, streamingText, toolRunning, onSubmit, onAbort, disabled }) {
|
|
209
209
|
const [input, setInput] = useState("");
|
|
210
210
|
const { stdout } = useStdout();
|
|
211
|
-
const termWidth = stdout?.columns ?? 80;
|
|
211
|
+
const termWidth = (stdout?.columns ?? 80) - 2;
|
|
212
212
|
const handleSubmit = useCallback((val) => {
|
|
213
213
|
onSubmit(val);
|
|
214
214
|
}, [onSubmit]);
|
|
@@ -217,6 +217,6 @@ export function REPL({ messages, streamingText, toolRunning, onSubmit, onAbort,
|
|
|
217
217
|
}, [onAbort]);
|
|
218
218
|
// Scrolling: show last N messages
|
|
219
219
|
const visible = messages.slice(-MAX_VISIBLE);
|
|
220
|
-
return (_jsxs(Box, { flexDirection: "column", width:
|
|
220
|
+
return (_jsxs(Box, { flexDirection: "column", width: "100%", children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [visible.map(m => _jsx(MessageLine, { msg: m }, m.id)), streamingText && (_jsxs(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: [_jsx(Text, { color: AIAIAI_COLORS.muted, children: " " }), _jsx(Text, { color: AIAIAI_COLORS.header, bold: true, children: "\uD83E\uDD16 " }), _jsx(Text, { wrap: "wrap", children: streamingText })] })), toolRunning && (_jsx(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: _jsxs(Text, { color: AIAIAI_COLORS.warn, children: ["\u2699 running ", toolRunning, "\u2026"] }) }))] }), _jsx(InputBox, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: !!disabled, onAbort: handleAbort })] }));
|
|
221
221
|
}
|
|
222
222
|
//# sourceMappingURL=REPL.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/Sparkline.tsx — Mini ASCII sparkline chart for sidebar.
|
|
3
|
+
* Uses Unicode block characters: ▁ ▂ ▃ ▄ ▅ ▆ ▇ █
|
|
4
|
+
*/
|
|
5
|
+
import React from "react";
|
|
6
|
+
export interface SparklineProps {
|
|
7
|
+
data: number[];
|
|
8
|
+
width?: number;
|
|
9
|
+
label?: string;
|
|
10
|
+
color?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function Sparkline({ data, width, label, color }: SparklineProps): React.JSX.Element | null;
|
|
13
|
+
/** Track a rolling price history for sparkline use */
|
|
14
|
+
export declare class PriceHistory {
|
|
15
|
+
private prices;
|
|
16
|
+
private maxLength;
|
|
17
|
+
constructor(maxLength?: number);
|
|
18
|
+
push(price: number): void;
|
|
19
|
+
getData(): number[];
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=Sparkline.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from "ink";
|
|
3
|
+
const CHARS = "▁▂▃▄▅▆▇█";
|
|
4
|
+
export function Sparkline({ data, width = 30, label, color }) {
|
|
5
|
+
if (!data || data.length < 2)
|
|
6
|
+
return null;
|
|
7
|
+
const min = Math.min(...data);
|
|
8
|
+
const max = Math.max(...data);
|
|
9
|
+
const range = max - min || 1;
|
|
10
|
+
// Normalize and compress to width
|
|
11
|
+
const compressed = [];
|
|
12
|
+
const step = data.length / width;
|
|
13
|
+
for (let i = 0; i < width; i++) {
|
|
14
|
+
const idx = Math.floor(i * step);
|
|
15
|
+
compressed.push(data[idx]);
|
|
16
|
+
}
|
|
17
|
+
const bars = compressed.map(v => {
|
|
18
|
+
const normalized = (v - min) / range;
|
|
19
|
+
const idx = Math.min(7, Math.floor(normalized * 8));
|
|
20
|
+
return CHARS[Math.max(0, idx)];
|
|
21
|
+
}).join("");
|
|
22
|
+
const trend = data[data.length - 1] > (data[0] ?? data[data.length - 1]) ? "▲" : "▼";
|
|
23
|
+
const minStr = min < 1 ? min.toFixed(6) : min < 100 ? min.toFixed(2) : min.toLocaleString();
|
|
24
|
+
const maxStr = max < 1 ? max.toFixed(6) : max < 100 ? max.toFixed(2) : max.toLocaleString();
|
|
25
|
+
return (_jsxs(Box, { flexDirection: "column", children: [label && _jsxs(Text, { dimColor: true, children: [label, " ", trend] }), _jsx(Text, { color: color, children: bars }), _jsxs(Text, { dimColor: true, children: ["$", minStr, " \u2013 $", maxStr] })] }));
|
|
26
|
+
}
|
|
27
|
+
/** Track a rolling price history for sparkline use */
|
|
28
|
+
export class PriceHistory {
|
|
29
|
+
prices = [];
|
|
30
|
+
maxLength;
|
|
31
|
+
constructor(maxLength = 50) {
|
|
32
|
+
this.maxLength = maxLength;
|
|
33
|
+
}
|
|
34
|
+
push(price) {
|
|
35
|
+
this.prices.push(price);
|
|
36
|
+
if (this.prices.length > this.maxLength) {
|
|
37
|
+
this.prices = this.prices.slice(-this.maxLength);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
getData() {
|
|
41
|
+
return [...this.prices];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=Sparkline.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/ThemePresets.ts — Theme presets system for AIAIAI TUI.
|
|
3
|
+
* 5 built-in presets + custom via ~/.aiaiai/config/theme.json
|
|
4
|
+
*/
|
|
5
|
+
export interface ThemeColors {
|
|
6
|
+
accent: string;
|
|
7
|
+
header: string;
|
|
8
|
+
muted: string;
|
|
9
|
+
dim: string;
|
|
10
|
+
success: string;
|
|
11
|
+
warn: string;
|
|
12
|
+
error: string;
|
|
13
|
+
background: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ThemePreset {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
colors: ThemeColors;
|
|
19
|
+
}
|
|
20
|
+
export declare const PRESETS: Record<string, ThemePreset>;
|
|
21
|
+
export declare function getCurrentTheme(): string;
|
|
22
|
+
export declare function setTheme(name: string): boolean;
|
|
23
|
+
export declare function getPresetColors(): ThemeColors;
|
|
24
|
+
export declare function listThemes(): string;
|
|
25
|
+
//# sourceMappingURL=ThemePresets.d.ts.map
|