@aiaiaichain/agent 0.1.3 → 0.1.4
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/README.md +2 -2
- package/dist/cli.js +60 -25
- package/dist/core/SystemMonitor.d.ts +35 -0
- package/dist/core/SystemMonitor.js +115 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +7 -1
- package/dist/session/SessionStore.d.ts +45 -0
- package/dist/session/SessionStore.js +123 -0
- package/dist/tools/CrossTools.d.ts +52 -0
- package/dist/tools/CrossTools.js +182 -0
- package/dist/tui/App.d.ts +4 -3
- package/dist/tui/App.js +243 -112
- package/dist/tui/REPL.d.ts +2 -1
- package/dist/tui/REPL.js +189 -15
- package/dist/tui/StatusBar.d.ts +5 -1
- package/dist/tui/StatusBar.js +6 -4
- package/dist/wallet/AgentWallet.d.ts +1 -0
- package/dist/wallet/AgentWallet.js +1 -0
- package/docs/COMMANDS.md +40 -9
- package/docs/README.md +2 -0
- package/package.json +5 -3
- package/scripts/postinstall.js +34 -0
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
[](https://nodejs.org)
|
|
18
18
|
[](LICENSE)
|
|
19
19
|
|
|
20
|
-
[X / Twitter](https://x.com/aiaiaisol)
|
|
20
|
+
[X / Twitter](https://x.com/aiaiaisol) · [aiaiaichain.xyz](https://aiaiaichain.xyz)
|
|
21
21
|
|
|
22
22
|
</div>
|
|
23
23
|
|
|
@@ -149,7 +149,7 @@ Get an OpenRouter key at https://openrouter.ai/keys
|
|
|
149
149
|
|
|
150
150
|
## Links
|
|
151
151
|
|
|
152
|
-
- [X / Twitter](https://x.com/aiaiaisol)
|
|
152
|
+
- [X / Twitter](https://x.com/aiaiaisol) · [aiaiaichain.xyz](https://aiaiaichain.xyz)
|
|
153
153
|
- [npm](https://www.npmjs.com/package/@aiaiaichain/agent)
|
|
154
154
|
|
|
155
155
|
## License
|
package/dist/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import { readFileSync, existsSync } from "node:fs";
|
|
|
6
6
|
import { resolve, join, dirname } from "node:path";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { execSync } from "node:child_process";
|
|
9
10
|
import { render } from "ink";
|
|
10
11
|
import React from "react";
|
|
11
12
|
import { config as loadDotenv } from "dotenv";
|
|
@@ -25,6 +26,7 @@ import { agentWallet, DEPOSIT_WALLET, ACTION_WALLET, SIGNER } from "./wallet/Age
|
|
|
25
26
|
import { PROVIDERS, getConfigured, getUnconfigured } from "./providers/ProviderRegistry.js";
|
|
26
27
|
import { env } from "./core/EnvLoader.js";
|
|
27
28
|
import { gmgnHelp, gmgnStatus, saveGmgnApiKey } from "./tools/GmgnIntegration.js";
|
|
29
|
+
import { sessionStore } from "./session/SessionStore.js";
|
|
28
30
|
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
|
|
29
31
|
const envPath = join(AIAIAI_HOME, ".env");
|
|
30
32
|
if (existsSync(envPath))
|
|
@@ -310,37 +312,34 @@ if (subcmd === "gmgn" || subcmd === "gmgnhelp") {
|
|
|
310
312
|
process.exit(0);
|
|
311
313
|
}
|
|
312
314
|
// Forward to gmgn-cli
|
|
313
|
-
|
|
314
|
-
const { execSync } = await import("node:child_process");
|
|
315
|
+
try {
|
|
315
316
|
const fullArgs = ["gmgn-cli", ...gmgnArgs];
|
|
317
|
+
const gmgnEnv = {};
|
|
316
318
|
try {
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
e[m[1]] = m[2];
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
catch { } return e; })() },
|
|
327
|
-
encoding: "utf-8",
|
|
328
|
-
timeout: 30_000,
|
|
329
|
-
});
|
|
330
|
-
process.stdout.write(output);
|
|
331
|
-
}
|
|
332
|
-
catch (e) {
|
|
333
|
-
const msg = e.stderr?.toString() || e.message || "";
|
|
334
|
-
process.stderr.write(`gmgn-cli: ${msg.slice(0, 500)}\n`);
|
|
335
|
-
process.exit(e.status ?? 1);
|
|
319
|
+
const f = readFileSync(join(homedir(), ".config", "gmgn", ".env"), "utf-8");
|
|
320
|
+
for (const l of f.split("\n")) {
|
|
321
|
+
const m = l.trim().match(/^([A-Z_]+)=(.*)$/);
|
|
322
|
+
if (m)
|
|
323
|
+
gmgnEnv[m[1]] = m[2];
|
|
324
|
+
}
|
|
336
325
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
326
|
+
catch { /* no gmgn env */ }
|
|
327
|
+
const output = execSync(fullArgs.join(" "), {
|
|
328
|
+
env: { ...process.env, ...gmgnEnv },
|
|
329
|
+
encoding: "utf-8",
|
|
330
|
+
timeout: 30_000,
|
|
331
|
+
});
|
|
332
|
+
process.stdout.write(output);
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
const msg = e.stderr?.toString() || e.message || "";
|
|
336
|
+
process.stderr.write(`gmgn-cli: ${msg.slice(0, 500)}\n`);
|
|
337
|
+
process.exit(e.status ?? 1);
|
|
338
|
+
}
|
|
339
|
+
process.exit(0);
|
|
340
340
|
}
|
|
341
341
|
if (subcmd === "update" || subcmd === "upgrade") {
|
|
342
342
|
(async () => {
|
|
343
|
-
const { execSync } = await import("node:child_process");
|
|
344
343
|
const pkgName = "@aiaiaichain/agent";
|
|
345
344
|
console.log(T.accent("\n 🤖 AIAIAI Update Check\n"));
|
|
346
345
|
// Get current version
|
|
@@ -415,6 +414,42 @@ if (subcmd === "update" || subcmd === "upgrade") {
|
|
|
415
414
|
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
416
415
|
await new Promise(() => { });
|
|
417
416
|
}
|
|
417
|
+
if (subcmd === "sessions") {
|
|
418
|
+
const sessions = sessionStore.list();
|
|
419
|
+
if (sessions.length === 0) {
|
|
420
|
+
console.log(T.muted(" No saved sessions."));
|
|
421
|
+
process.exit(0);
|
|
422
|
+
}
|
|
423
|
+
console.log(T.accent("\n 📂 Saved Sessions\n"));
|
|
424
|
+
sessions.slice(0, 15).forEach((s, i) => {
|
|
425
|
+
const date = new Date(s.updatedAt).toLocaleDateString();
|
|
426
|
+
console.log(T.muted(` ${String(i + 1).padStart(2)}. ${s.title} (${s.messageCount} msgs, ${s.model}, ${date})`));
|
|
427
|
+
});
|
|
428
|
+
console.log("");
|
|
429
|
+
process.exit(0);
|
|
430
|
+
}
|
|
431
|
+
if (subcmd === "resume") {
|
|
432
|
+
const sessions = sessionStore.list();
|
|
433
|
+
if (sessions.length === 0) {
|
|
434
|
+
console.log(T.muted(" No saved sessions."));
|
|
435
|
+
process.exit(0);
|
|
436
|
+
}
|
|
437
|
+
const idx = parseInt(process.argv[3]) - 1;
|
|
438
|
+
if (isNaN(idx) || idx < 0 || idx >= sessions.length) {
|
|
439
|
+
console.log(T.error(" Invalid session number."));
|
|
440
|
+
process.exit(1);
|
|
441
|
+
}
|
|
442
|
+
const session = sessionStore.load(sessions[idx].id);
|
|
443
|
+
if (!session) {
|
|
444
|
+
console.log(T.error(" Session not found."));
|
|
445
|
+
process.exit(1);
|
|
446
|
+
}
|
|
447
|
+
console.log(T.accent(`\n 📂 Resumed: ${session.title}\n`));
|
|
448
|
+
console.log(T.muted(` Messages: ${session.messages.length}`));
|
|
449
|
+
console.log(T.muted(` Model: ${session.model}`));
|
|
450
|
+
console.log("");
|
|
451
|
+
process.exit(0);
|
|
452
|
+
}
|
|
418
453
|
// ── Resolve extension + prompt ────────────────────────────────────────────────
|
|
419
454
|
let extensionPath = null;
|
|
420
455
|
let promptPath = null;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SystemMonitor — tracks CPU, RAM, network, and agent stats.
|
|
3
|
+
* Uses Node.js built-in modules only (no external deps).
|
|
4
|
+
*/
|
|
5
|
+
export interface SystemStats {
|
|
6
|
+
cpuPercent: number;
|
|
7
|
+
ramPercent: number;
|
|
8
|
+
ramUsed: string;
|
|
9
|
+
ramTotal: string;
|
|
10
|
+
uptime: string;
|
|
11
|
+
netUp: string;
|
|
12
|
+
netDown: string;
|
|
13
|
+
apiCallsPerMin: number;
|
|
14
|
+
tokensUsed: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class SystemMonitor {
|
|
17
|
+
private apiCallCount;
|
|
18
|
+
private lastNetStats;
|
|
19
|
+
constructor();
|
|
20
|
+
private initNetStats;
|
|
21
|
+
/** Track an API call */
|
|
22
|
+
trackApiCall(): void;
|
|
23
|
+
/** Get current system stats */
|
|
24
|
+
getStats(tokenCount?: number): SystemStats;
|
|
25
|
+
private getCpuPercent;
|
|
26
|
+
private getRamPercent;
|
|
27
|
+
private getNetStats;
|
|
28
|
+
private getRawNetStats;
|
|
29
|
+
private formatBytes;
|
|
30
|
+
private formatUptime;
|
|
31
|
+
/** Reset API call counter (call every minute) */
|
|
32
|
+
resetApiCounter(): number;
|
|
33
|
+
}
|
|
34
|
+
export declare const systemMonitor: SystemMonitor;
|
|
35
|
+
//# sourceMappingURL=SystemMonitor.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SystemMonitor — tracks CPU, RAM, network, and agent stats.
|
|
3
|
+
* Uses Node.js built-in modules only (no external deps).
|
|
4
|
+
*/
|
|
5
|
+
import { cpus, totalmem, freemem, uptime, networkInterfaces } from 'node:os';
|
|
6
|
+
export class SystemMonitor {
|
|
7
|
+
apiCallCount = 0;
|
|
8
|
+
lastNetStats = { rx: 0, tx: 0, time: Date.now() };
|
|
9
|
+
constructor() {
|
|
10
|
+
this.initNetStats();
|
|
11
|
+
}
|
|
12
|
+
initNetStats() {
|
|
13
|
+
try {
|
|
14
|
+
const stats = this.getRawNetStats();
|
|
15
|
+
this.lastNetStats = { rx: stats.rx, tx: stats.tx, time: Date.now() };
|
|
16
|
+
}
|
|
17
|
+
catch { /* non-fatal */ }
|
|
18
|
+
}
|
|
19
|
+
/** Track an API call */
|
|
20
|
+
trackApiCall() {
|
|
21
|
+
this.apiCallCount++;
|
|
22
|
+
}
|
|
23
|
+
/** Get current system stats */
|
|
24
|
+
getStats(tokenCount = 0) {
|
|
25
|
+
return {
|
|
26
|
+
cpuPercent: this.getCpuPercent(),
|
|
27
|
+
ramPercent: this.getRamPercent(),
|
|
28
|
+
ramUsed: this.formatBytes(totalmem() - freemem()),
|
|
29
|
+
ramTotal: this.formatBytes(totalmem()),
|
|
30
|
+
uptime: this.formatUptime(uptime()),
|
|
31
|
+
...this.getNetStats(),
|
|
32
|
+
apiCallsPerMin: this.apiCallCount,
|
|
33
|
+
tokensUsed: tokenCount,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
getCpuPercent() {
|
|
37
|
+
try {
|
|
38
|
+
const cpuInfo = cpus();
|
|
39
|
+
let totalIdle = 0, totalTick = 0;
|
|
40
|
+
for (const cpu of cpuInfo) {
|
|
41
|
+
for (const type in cpu.times) {
|
|
42
|
+
totalTick += cpu.times[type];
|
|
43
|
+
}
|
|
44
|
+
totalIdle += cpu.times.idle;
|
|
45
|
+
}
|
|
46
|
+
const idle = totalIdle / cpuInfo.length;
|
|
47
|
+
const total = totalTick / cpuInfo.length;
|
|
48
|
+
return Math.round((1 - idle / total) * 100);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
getRamPercent() {
|
|
55
|
+
const used = totalmem() - freemem();
|
|
56
|
+
return Math.round((used / totalmem()) * 100);
|
|
57
|
+
}
|
|
58
|
+
getNetStats() {
|
|
59
|
+
try {
|
|
60
|
+
const current = this.getRawNetStats();
|
|
61
|
+
const elapsed = (Date.now() - this.lastNetStats.time) / 1000;
|
|
62
|
+
if (elapsed < 1)
|
|
63
|
+
return { netUp: '0 B/s', netDown: '0 B/s' };
|
|
64
|
+
const rxPerSec = Math.max(0, (current.rx - this.lastNetStats.rx) / elapsed);
|
|
65
|
+
const txPerSec = Math.max(0, (current.tx - this.lastNetStats.tx) / elapsed);
|
|
66
|
+
this.lastNetStats = { rx: current.rx, tx: current.tx, time: Date.now() };
|
|
67
|
+
return {
|
|
68
|
+
netUp: this.formatBytes(txPerSec) + '/s',
|
|
69
|
+
netDown: this.formatBytes(rxPerSec) + '/s',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return { netUp: 'N/A', netDown: 'N/A' };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
getRawNetStats() {
|
|
77
|
+
let rx = 0, tx = 0;
|
|
78
|
+
const interfaces = networkInterfaces();
|
|
79
|
+
for (const name of Object.keys(interfaces)) {
|
|
80
|
+
const iface = interfaces[name];
|
|
81
|
+
if (!iface)
|
|
82
|
+
continue;
|
|
83
|
+
for (const info of iface) {
|
|
84
|
+
if (info.internal)
|
|
85
|
+
continue;
|
|
86
|
+
// Node.js doesn't expose per-interface bytes by default
|
|
87
|
+
// This is a best-effort approximation
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { rx, tx };
|
|
91
|
+
}
|
|
92
|
+
formatBytes(bytes) {
|
|
93
|
+
if (bytes === 0)
|
|
94
|
+
return '0 B';
|
|
95
|
+
const k = 1024;
|
|
96
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
97
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
98
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
99
|
+
}
|
|
100
|
+
formatUptime(seconds) {
|
|
101
|
+
const h = Math.floor(seconds / 3600);
|
|
102
|
+
const m = Math.floor((seconds % 3600) / 60);
|
|
103
|
+
if (h > 0)
|
|
104
|
+
return `${h}h ${m}m`;
|
|
105
|
+
return `${m}m`;
|
|
106
|
+
}
|
|
107
|
+
/** Reset API call counter (call every minute) */
|
|
108
|
+
resetApiCounter() {
|
|
109
|
+
const count = this.apiCallCount;
|
|
110
|
+
this.apiCallCount = 0;
|
|
111
|
+
return count;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export const systemMonitor = new SystemMonitor();
|
|
115
|
+
//# sourceMappingURL=SystemMonitor.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export { PriceFeed, priceFeed } from "./tools/PriceFeed.js";
|
|
|
23
23
|
export { NewsFeed, newsFeed, getNewsTool, scoreSentiment } from "./tools/NewsSentiment.js";
|
|
24
24
|
export { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "./tools/MarketSentiment.js";
|
|
25
25
|
export type { OHLCV, AnalysisResult } from "./tools/TechnicalAnalysis.js";
|
|
26
|
-
export type { PriceResult, DexScreenerPair } from "./tools/PriceFeed.js";
|
|
26
|
+
export type { PriceResult, DexScreenerPair as DexScreenerData } from "./tools/PriceFeed.js";
|
|
27
27
|
export type { NewsItem, SentimentReport } from "./tools/NewsSentiment.js";
|
|
28
28
|
export { SessionManager } from "./session/SessionManager.js";
|
|
29
29
|
export { MemoryStore, memoryStore } from "./session/MemoryStore.js";
|
|
@@ -37,7 +37,12 @@ export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI
|
|
|
37
37
|
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
38
38
|
export type { WalletBalance, AgentWallets } from "./wallet/AgentWallet.js";
|
|
39
39
|
export type { AgentAction, ActionType, FeeTracker } from "./wallet/ActionFeed.js";
|
|
40
|
-
export { gmgnTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
40
|
+
export { gmgnTool, gmgnMarketTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
41
|
+
export { watchTokenTool, removeWatchTool, listWatchTool, addAlertTool, checkAlertsTool, compareTokensTool, portfolioTool, portfolioParams, getWatchList, checkAlerts, addAlert, getActiveAlerts, } from "./tools/CrossTools.js";
|
|
42
|
+
export { sessionStore } from "./session/SessionStore.js";
|
|
43
|
+
export type { Session, SessionMeta } from "./session/SessionStore.js";
|
|
44
|
+
export { systemMonitor } from "./core/SystemMonitor.js";
|
|
45
|
+
export type { SystemStats } from "./core/SystemMonitor.js";
|
|
41
46
|
export { MCPServer } from "./mcp/server.js";
|
|
42
47
|
export { AgentDir } from "./core/AgentDir.js";
|
|
43
48
|
export { EnvLoader, env } from "./core/EnvLoader.js";
|
package/dist/index.js
CHANGED
|
@@ -37,7 +37,13 @@ export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
|
37
37
|
export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI_MINT } from "./wallet/AgentWallet.js";
|
|
38
38
|
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
39
39
|
// GMGN
|
|
40
|
-
export { gmgnTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
40
|
+
export { gmgnTool, gmgnMarketTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
41
|
+
// Cross tools
|
|
42
|
+
export { watchTokenTool, removeWatchTool, listWatchTool, addAlertTool, checkAlertsTool, compareTokensTool, portfolioTool, portfolioParams, getWatchList, checkAlerts, addAlert, getActiveAlerts, } from "./tools/CrossTools.js";
|
|
43
|
+
// Session
|
|
44
|
+
export { sessionStore } from "./session/SessionStore.js";
|
|
45
|
+
// System
|
|
46
|
+
export { systemMonitor } from "./core/SystemMonitor.js";
|
|
41
47
|
// MCP
|
|
42
48
|
export { MCPServer } from "./mcp/server.js";
|
|
43
49
|
// Core
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionStore — saves/loads conversation sessions.
|
|
3
|
+
* Sessions stored as JSON in ~/.aiaiai/sessions/
|
|
4
|
+
*/
|
|
5
|
+
import type { ChatMessage } from '../tui/REPL.js';
|
|
6
|
+
export interface SessionMeta {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
createdAt: number;
|
|
10
|
+
updatedAt: number;
|
|
11
|
+
messageCount: number;
|
|
12
|
+
model: string;
|
|
13
|
+
}
|
|
14
|
+
export interface Session {
|
|
15
|
+
id: string;
|
|
16
|
+
title: string;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
updatedAt: number;
|
|
19
|
+
messages: ChatMessage[];
|
|
20
|
+
model: string;
|
|
21
|
+
chain: string;
|
|
22
|
+
}
|
|
23
|
+
export declare class SessionStore {
|
|
24
|
+
private currentId;
|
|
25
|
+
private autoSaveInterval;
|
|
26
|
+
constructor();
|
|
27
|
+
/** Start auto-saving every 30s */
|
|
28
|
+
startAutoSave(getMessages: () => ChatMessage[]): void;
|
|
29
|
+
stopAutoSave(): void;
|
|
30
|
+
/** Save current session */
|
|
31
|
+
save(messages: ChatMessage[], title?: string): string;
|
|
32
|
+
/** Load a session by ID */
|
|
33
|
+
load(id: string): Session | null;
|
|
34
|
+
/** List all sessions (most recent first) */
|
|
35
|
+
list(): SessionMeta[];
|
|
36
|
+
/** Delete a session */
|
|
37
|
+
delete(id: string): boolean;
|
|
38
|
+
/** Set current session ID (for resuming) */
|
|
39
|
+
setCurrentId(id: string): void;
|
|
40
|
+
getCurrentId(): string;
|
|
41
|
+
/** Generate a title from first user message */
|
|
42
|
+
private generateTitle;
|
|
43
|
+
}
|
|
44
|
+
export declare const sessionStore: SessionStore;
|
|
45
|
+
//# sourceMappingURL=SessionStore.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionStore — saves/loads conversation sessions.
|
|
3
|
+
* Sessions stored as JSON in ~/.aiaiai/sessions/
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';
|
|
6
|
+
import { resolve } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
const SESSIONS_DIR = resolve(homedir(), '.aiaiai', 'sessions');
|
|
9
|
+
function ensureDir() {
|
|
10
|
+
if (!existsSync(SESSIONS_DIR))
|
|
11
|
+
mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
function sessionId() {
|
|
14
|
+
return `session-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
15
|
+
}
|
|
16
|
+
export class SessionStore {
|
|
17
|
+
currentId;
|
|
18
|
+
autoSaveInterval = null;
|
|
19
|
+
constructor() {
|
|
20
|
+
ensureDir();
|
|
21
|
+
this.currentId = sessionId();
|
|
22
|
+
}
|
|
23
|
+
/** Start auto-saving every 30s */
|
|
24
|
+
startAutoSave(getMessages) {
|
|
25
|
+
this.stopAutoSave();
|
|
26
|
+
this.autoSaveInterval = setInterval(() => {
|
|
27
|
+
const msgs = getMessages();
|
|
28
|
+
if (msgs.length > 0)
|
|
29
|
+
this.save(msgs, 'current');
|
|
30
|
+
}, 30_000);
|
|
31
|
+
}
|
|
32
|
+
stopAutoSave() {
|
|
33
|
+
if (this.autoSaveInterval) {
|
|
34
|
+
clearInterval(this.autoSaveInterval);
|
|
35
|
+
this.autoSaveInterval = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Save current session */
|
|
39
|
+
save(messages, title) {
|
|
40
|
+
ensureDir();
|
|
41
|
+
const id = this.currentId;
|
|
42
|
+
const existing = this.load(id);
|
|
43
|
+
const session = {
|
|
44
|
+
id,
|
|
45
|
+
title: title || existing?.title || this.generateTitle(messages),
|
|
46
|
+
createdAt: existing?.createdAt || Date.now(),
|
|
47
|
+
updatedAt: Date.now(),
|
|
48
|
+
messages,
|
|
49
|
+
model: process.env.DEFAULT_MODEL || 'unknown',
|
|
50
|
+
chain: 'solana',
|
|
51
|
+
};
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(resolve(SESSIONS_DIR, `${id}.json`), JSON.stringify(session, null, 2), 'utf-8');
|
|
54
|
+
}
|
|
55
|
+
catch { /* non-fatal */ }
|
|
56
|
+
return id;
|
|
57
|
+
}
|
|
58
|
+
/** Load a session by ID */
|
|
59
|
+
load(id) {
|
|
60
|
+
try {
|
|
61
|
+
const path = resolve(SESSIONS_DIR, `${id}.json`);
|
|
62
|
+
if (!existsSync(path))
|
|
63
|
+
return null;
|
|
64
|
+
return JSON.parse(readFileSync(path, 'utf-8'));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** List all sessions (most recent first) */
|
|
71
|
+
list() {
|
|
72
|
+
ensureDir();
|
|
73
|
+
try {
|
|
74
|
+
const files = readdirSync(SESSIONS_DIR).filter(f => f.endsWith('.json'));
|
|
75
|
+
const sessions = [];
|
|
76
|
+
for (const file of files) {
|
|
77
|
+
try {
|
|
78
|
+
const data = JSON.parse(readFileSync(resolve(SESSIONS_DIR, file), 'utf-8'));
|
|
79
|
+
sessions.push({
|
|
80
|
+
id: data.id,
|
|
81
|
+
title: data.title,
|
|
82
|
+
createdAt: data.createdAt,
|
|
83
|
+
updatedAt: data.updatedAt,
|
|
84
|
+
messageCount: data.messages.length,
|
|
85
|
+
model: data.model,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch { /* skip bad files */ }
|
|
89
|
+
}
|
|
90
|
+
return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Delete a session */
|
|
97
|
+
delete(id) {
|
|
98
|
+
try {
|
|
99
|
+
unlinkSync(resolve(SESSIONS_DIR, `${id}.json`));
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Set current session ID (for resuming) */
|
|
107
|
+
setCurrentId(id) {
|
|
108
|
+
this.currentId = id;
|
|
109
|
+
}
|
|
110
|
+
getCurrentId() {
|
|
111
|
+
return this.currentId;
|
|
112
|
+
}
|
|
113
|
+
/** Generate a title from first user message */
|
|
114
|
+
generateTitle(messages) {
|
|
115
|
+
const firstUser = messages.find(m => m.role === 'user');
|
|
116
|
+
if (!firstUser)
|
|
117
|
+
return 'New Session';
|
|
118
|
+
const text = firstUser.content.trim();
|
|
119
|
+
return text.length > 40 ? text.slice(0, 37) + '…' : text;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export const sessionStore = new SessionStore();
|
|
123
|
+
//# sourceMappingURL=SessionStore.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CrossTools — automation tools that combine multiple data sources.
|
|
3
|
+
* Watch tokens, compare, portfolio tracking, price alerts.
|
|
4
|
+
*/
|
|
5
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
6
|
+
interface PriceAlert {
|
|
7
|
+
id: string;
|
|
8
|
+
token: string;
|
|
9
|
+
type: 'above' | 'below';
|
|
10
|
+
price: number;
|
|
11
|
+
active: boolean;
|
|
12
|
+
createdAt: number;
|
|
13
|
+
triggeredAt?: number;
|
|
14
|
+
}
|
|
15
|
+
export declare function addAlert(token: string, type: 'above' | 'below', price: number): PriceAlert;
|
|
16
|
+
export declare function checkAlerts(currentPrice: number, token: string): PriceAlert[];
|
|
17
|
+
export declare function getActiveAlerts(): PriceAlert[];
|
|
18
|
+
export declare function addToWatchList(tokenAddress: string): void;
|
|
19
|
+
export declare function removeFromWatchList(tokenAddress: string): void;
|
|
20
|
+
export declare function getWatchList(): string[];
|
|
21
|
+
export declare const watchTokenParams: import("@sinclair/typebox").TObject<{
|
|
22
|
+
address: import("@sinclair/typebox").TString;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const removeWatchParams: import("@sinclair/typebox").TObject<{
|
|
25
|
+
address: import("@sinclair/typebox").TString;
|
|
26
|
+
}>;
|
|
27
|
+
export declare const listWatchParams: import("@sinclair/typebox").TObject<{}>;
|
|
28
|
+
export declare const addAlertParams: import("@sinclair/typebox").TObject<{
|
|
29
|
+
token: import("@sinclair/typebox").TString;
|
|
30
|
+
type: import("@sinclair/typebox").TString;
|
|
31
|
+
price: import("@sinclair/typebox").TNumber;
|
|
32
|
+
}>;
|
|
33
|
+
export declare const checkAlertsParams: import("@sinclair/typebox").TObject<{}>;
|
|
34
|
+
export declare const compareTokensParams: import("@sinclair/typebox").TObject<{
|
|
35
|
+
address1: import("@sinclair/typebox").TString;
|
|
36
|
+
address2: import("@sinclair/typebox").TString;
|
|
37
|
+
}>;
|
|
38
|
+
export declare function watchTokenTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
39
|
+
export declare function removeWatchTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
40
|
+
export declare function listWatchTool(): Promise<ToolResult>;
|
|
41
|
+
export declare function addAlertTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
42
|
+
export declare function checkAlertsTool(): Promise<ToolResult>;
|
|
43
|
+
export declare function compareTokensTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
44
|
+
export declare const portfolioParams: import("@sinclair/typebox").TObject<{
|
|
45
|
+
address: import("@sinclair/typebox").TString;
|
|
46
|
+
}>;
|
|
47
|
+
export declare function portfolioTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
48
|
+
export declare const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
|
|
49
|
+
export declare const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
|
|
50
|
+
export declare const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=CrossTools.d.ts.map
|