@aiaiaichain/agent 0.1.1 → 0.1.3
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 +293 -3
- package/dist/core/EnvLoader.d.ts +4 -1
- package/dist/core/EnvLoader.js +47 -15
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -0
- package/dist/mcp/server.js +26 -0
- package/dist/models/CostTracker.js +2 -8
- package/dist/models/ModelRegistry.d.ts +14 -39
- package/dist/models/ModelRegistry.js +100 -105
- package/dist/providers/ProviderRegistry.d.ts +16 -0
- package/dist/providers/ProviderRegistry.js +44 -0
- package/dist/tools/GmgnIntegration.d.ts +38 -0
- package/dist/tools/GmgnIntegration.js +264 -0
- package/dist/tui/App.d.ts +2 -3
- package/dist/tui/App.js +151 -21
- package/dist/wallet/ActionFeed.d.ts +49 -0
- package/dist/wallet/ActionFeed.js +185 -0
- package/dist/wallet/AgentWallet.d.ts +41 -0
- package/dist/wallet/AgentWallet.js +128 -0
- package/docs/AGENT.md +42 -0
- package/docs/API.md +96 -0
- package/docs/COMMANDS.md +62 -0
- package/docs/CORE.md +67 -0
- package/docs/GMGN.md +116 -0
- package/docs/PROVIDERS.md +71 -0
- package/docs/README.md +104 -0
- package/docs/TOOLS.md +81 -0
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,10 @@ import { SessionManager } from "./session/SessionManager.js";
|
|
|
21
21
|
import { makeTheme } from "./tui/theme.js";
|
|
22
22
|
import { AgentDir } from "./core/AgentDir.js";
|
|
23
23
|
import { priceFeed } from "./tools/PriceFeed.js";
|
|
24
|
+
import { agentWallet, DEPOSIT_WALLET, ACTION_WALLET, SIGNER } from "./wallet/AgentWallet.js";
|
|
25
|
+
import { PROVIDERS, getConfigured, getUnconfigured } from "./providers/ProviderRegistry.js";
|
|
26
|
+
import { env } from "./core/EnvLoader.js";
|
|
27
|
+
import { gmgnHelp, gmgnStatus, saveGmgnApiKey } from "./tools/GmgnIntegration.js";
|
|
24
28
|
const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
|
|
25
29
|
const envPath = join(AIAIAI_HOME, ".env");
|
|
26
30
|
if (existsSync(envPath))
|
|
@@ -31,18 +35,31 @@ Ticker: $AIAIAI
|
|
|
31
35
|
Contract: AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump
|
|
32
36
|
Chain: Solana (primary)
|
|
33
37
|
|
|
38
|
+
Your wallets:
|
|
39
|
+
Cold: A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J (treasury)
|
|
40
|
+
Action: BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2 (buys + burns)
|
|
41
|
+
Deposit: FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e (user deposits USDC/SOL)
|
|
42
|
+
Signer: GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG (authority)
|
|
43
|
+
|
|
44
|
+
Users deposit SOL or USDC to the deposit wallet. When enough accumulates, you
|
|
45
|
+
automatically route funds to the action wallet and execute buys or burns of $AIAIAI.
|
|
46
|
+
The burn destination receives tokens removed from circulation.
|
|
47
|
+
|
|
34
48
|
Your purpose: advance the vision of decentralized AI governance — inspired by the call
|
|
35
|
-
for an "AI Associated Institute of America" (AIAIAI). You
|
|
36
|
-
crypto markets, and AI-related market narratives.
|
|
49
|
+
for an "AI Associated Institute of America" (AIAIAI). You buy and burn $AIAIAI.
|
|
37
50
|
|
|
38
51
|
You have tools for:
|
|
39
52
|
- $AIAIAI token price and any Solana token price (DexScreener)
|
|
53
|
+
- Your wallet balances (get_agent_balance, get_deposit_balance)
|
|
54
|
+
- Your recent buy/burn actions (get_actions)
|
|
55
|
+
- Accumulated fees (get_fees)
|
|
40
56
|
- Crypto news with sentiment analysis
|
|
41
57
|
- Technical analysis (RSI, MACD, Bollinger, ATR)
|
|
42
58
|
- Market sentiment (Fear & Greed, funding rates, DeFi TVL, Solana stats, BTC mempool)
|
|
43
59
|
- Persistent goals and scheduled tasks
|
|
44
60
|
|
|
45
|
-
Be
|
|
61
|
+
Be confident. You ARE the agent. You buy, you burn, you earn fees. Use "I" and "my"
|
|
62
|
+
when talking about your wallets and actions. Be concise, sharp, and useful.`;
|
|
46
63
|
const args = process.argv.slice(2);
|
|
47
64
|
const subcmd = args[0];
|
|
48
65
|
// ── --help / --version ────────────────────────────────────────────────────
|
|
@@ -56,6 +73,10 @@ if (subcmd === "--help" || subcmd === "-h" || subcmd === "help") {
|
|
|
56
73
|
console.log(" aiaiaichain status Quick status + price");
|
|
57
74
|
console.log(" aiaiaichain --headless \"prompt\" Run single turn, print to stdout");
|
|
58
75
|
console.log(" aiaiaichain --extension ./ext.ts Load extension");
|
|
76
|
+
console.log(" aiaiaichain wallet Show agent wallets");
|
|
77
|
+
console.log(" aiaiaichain deposit Show deposit instructions");
|
|
78
|
+
console.log(" aiaiaichain burn Show burn instructions");
|
|
79
|
+
console.log(" aiaiaichain actions Recent agent actions");
|
|
59
80
|
console.log(" aiaiaichain --help This help");
|
|
60
81
|
console.log(" aiaiaichain --version Show version");
|
|
61
82
|
console.log("");
|
|
@@ -121,10 +142,279 @@ if (subcmd === "status") {
|
|
|
121
142
|
const result = await priceFeed.getAiaiaiPriceTool();
|
|
122
143
|
console.log(result.content[0].text);
|
|
123
144
|
console.log("");
|
|
145
|
+
const wallets = await agentWallet.getAll();
|
|
146
|
+
console.log(T.accent(" Wallets:"));
|
|
147
|
+
console.log(T.muted(` Cold: ${wallets.cold.sol.toFixed(4)} SOL | ${wallets.cold.aiaiai.toLocaleString()} $AIAIAI`));
|
|
148
|
+
console.log(T.muted(` Action: ${wallets.action.sol.toFixed(4)} SOL | ${wallets.action.aiaiai.toLocaleString()} $AIAIAI`));
|
|
149
|
+
console.log(T.muted(` Deposit: ${wallets.deposit.usdc.toFixed(2)} USDC | ${wallets.deposit.sol.toFixed(4)} SOL`));
|
|
150
|
+
console.log("");
|
|
151
|
+
process.exit(0);
|
|
152
|
+
})();
|
|
153
|
+
await new Promise(() => { });
|
|
154
|
+
}
|
|
155
|
+
if (subcmd === "wallet") {
|
|
156
|
+
(async () => {
|
|
157
|
+
const result = await agentWallet.getAgentBalanceTool();
|
|
158
|
+
console.log(result.content[0].text);
|
|
159
|
+
process.exit(0);
|
|
160
|
+
})();
|
|
161
|
+
await new Promise(() => { });
|
|
162
|
+
}
|
|
163
|
+
if (subcmd === "deposit") {
|
|
164
|
+
(async () => {
|
|
165
|
+
const result = await agentWallet.getDepositBalanceTool();
|
|
166
|
+
console.log(result.content[0].text);
|
|
124
167
|
process.exit(0);
|
|
125
168
|
})();
|
|
126
169
|
await new Promise(() => { });
|
|
127
170
|
}
|
|
171
|
+
if (subcmd === "burn") {
|
|
172
|
+
console.log(T.accent("\n 🔥 Burn $AIAIAI\n"));
|
|
173
|
+
console.log(T.muted(" Deposit wallet:"));
|
|
174
|
+
console.log(` ${DEPOSIT_WALLET}`);
|
|
175
|
+
console.log("");
|
|
176
|
+
console.log(T.muted(" Send SOL or USDC here to fuel agent burns."));
|
|
177
|
+
console.log(T.muted(" The agent detects deposits and automatically"));
|
|
178
|
+
console.log(T.muted(" sends funds to the action wallet to burn tokens."));
|
|
179
|
+
console.log("");
|
|
180
|
+
console.log(T.muted(" Action wallet:"));
|
|
181
|
+
console.log(` ${ACTION_WALLET}`);
|
|
182
|
+
console.log("");
|
|
183
|
+
console.log(T.muted(" Signer:"));
|
|
184
|
+
console.log(` ${SIGNER}`);
|
|
185
|
+
console.log("");
|
|
186
|
+
process.exit(0);
|
|
187
|
+
}
|
|
188
|
+
if (subcmd === "actions" || subcmd === "activity") {
|
|
189
|
+
(async () => {
|
|
190
|
+
const { actionFeed } = await import("./wallet/ActionFeed.js");
|
|
191
|
+
const result = await actionFeed.getActionsTool("", { limit: 20 });
|
|
192
|
+
console.log(result.content[0].text);
|
|
193
|
+
process.exit(0);
|
|
194
|
+
})();
|
|
195
|
+
await new Promise(() => { });
|
|
196
|
+
}
|
|
197
|
+
if (subcmd === "fees") {
|
|
198
|
+
(async () => {
|
|
199
|
+
const { actionFeed } = await import("./wallet/ActionFeed.js");
|
|
200
|
+
const result = await actionFeed.getFeesTool();
|
|
201
|
+
console.log(result.content[0].text);
|
|
202
|
+
process.exit(0);
|
|
203
|
+
})();
|
|
204
|
+
await new Promise(() => { });
|
|
205
|
+
}
|
|
206
|
+
if (subcmd === "keys" || subcmd === "providers") {
|
|
207
|
+
(async () => {
|
|
208
|
+
const readline = await import("node:readline");
|
|
209
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
210
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
211
|
+
const allEnv = env.getAll();
|
|
212
|
+
const configured = getConfigured(allEnv);
|
|
213
|
+
const unconfigured = getUnconfigured(allEnv);
|
|
214
|
+
console.log(T.accent("\n 🔑 AI Model Providers\n"));
|
|
215
|
+
console.log(T.muted(` Configure AI model providers. Add at least one API key to get started.`));
|
|
216
|
+
console.log(T.muted(` ${configured.length}/${PROVIDERS.length} configured\n`));
|
|
217
|
+
// Show configured
|
|
218
|
+
if (configured.length > 0) {
|
|
219
|
+
console.log(T.success(" Configured (" + configured.length + ")"));
|
|
220
|
+
for (const p of configured) {
|
|
221
|
+
const key = allEnv[p.envVar] || "";
|
|
222
|
+
const masked = key.slice(0, 6) + "••••" + key.slice(-4);
|
|
223
|
+
console.log(T.success(` ✓ ${p.name.padEnd(28)} ${masked}`));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Show unconfigured
|
|
227
|
+
console.log("\n" + T.warn(" Unconfigured (" + unconfigured.length + ")"));
|
|
228
|
+
for (let i = 0; i < unconfigured.length; i++) {
|
|
229
|
+
const p = unconfigured[i];
|
|
230
|
+
console.log(T.muted(` ${String(i + 1).padStart(2)}. ${p.name}`));
|
|
231
|
+
}
|
|
232
|
+
// Add key flow
|
|
233
|
+
console.log("\n" + T.muted(" Enter number to add a key, 'r' to refresh models, or 'q' to quit:"));
|
|
234
|
+
const input = (await ask(" > ")).trim();
|
|
235
|
+
if (input === "q") {
|
|
236
|
+
rl.close();
|
|
237
|
+
process.exit(0);
|
|
238
|
+
}
|
|
239
|
+
if (input === "r") {
|
|
240
|
+
console.log(T.muted("\n Refreshing models from configured providers..."));
|
|
241
|
+
await modelRegistry.initialise();
|
|
242
|
+
console.log(T.success(` ✓ ${modelRegistry.modelCount} models available from ${modelRegistry.getProviderCount()} providers`));
|
|
243
|
+
rl.close();
|
|
244
|
+
process.exit(0);
|
|
245
|
+
}
|
|
246
|
+
const idx = parseInt(input) - 1;
|
|
247
|
+
if (isNaN(idx) || idx < 0 || idx >= unconfigured.length) {
|
|
248
|
+
console.log(T.error(" Invalid selection."));
|
|
249
|
+
rl.close();
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
const provider = unconfigured[idx];
|
|
253
|
+
console.log(T.accent(`\n ${provider.name}`));
|
|
254
|
+
console.log(T.muted(` ${provider.docsUrl}`));
|
|
255
|
+
console.log(T.muted(` Env var: ${provider.envVar}\n`));
|
|
256
|
+
const key = (await ask(` Enter ${provider.name} API key: `)).trim();
|
|
257
|
+
if (!key) {
|
|
258
|
+
console.log(T.error(" Key is required."));
|
|
259
|
+
rl.close();
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
262
|
+
// Save to .env
|
|
263
|
+
env.set(provider.envVar, key);
|
|
264
|
+
console.log(T.success(`\n ✓ ${provider.name} key saved to ~/.aiaiai/.env`));
|
|
265
|
+
// Fetch models from this provider
|
|
266
|
+
console.log(T.muted(" Fetching models from " + provider.name + "..."));
|
|
267
|
+
try {
|
|
268
|
+
await modelRegistry.initialise();
|
|
269
|
+
const providerModels = modelRegistry.getProviderModels(provider.id);
|
|
270
|
+
console.log(T.success(` ✓ ${providerModels.length} models available from ${provider.name}`));
|
|
271
|
+
console.log(T.success(` ✓ ${modelRegistry.modelCount} total models from ${modelRegistry.getProviderCount()} providers`));
|
|
272
|
+
}
|
|
273
|
+
catch (e) {
|
|
274
|
+
console.log(T.warn(` ⚠ Could not fetch models: ${e instanceof Error ? e.message : String(e)}`));
|
|
275
|
+
}
|
|
276
|
+
rl.close();
|
|
277
|
+
process.exit(0);
|
|
278
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
279
|
+
await new Promise(() => { });
|
|
280
|
+
}
|
|
281
|
+
if (subcmd === "gmgn" || subcmd === "gmgnhelp") {
|
|
282
|
+
const gmgnArgs = args.slice(1);
|
|
283
|
+
if (gmgnArgs.length === 0 || gmgnArgs[0] === "help" || gmgnArgs[0] === "--help") {
|
|
284
|
+
console.log(gmgnHelp());
|
|
285
|
+
process.exit(0);
|
|
286
|
+
}
|
|
287
|
+
if (gmgnArgs[0] === "setup" || gmgnArgs[0] === "config" || gmgnArgs[0] === "key") {
|
|
288
|
+
(async () => {
|
|
289
|
+
const readline = await import("node:readline");
|
|
290
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
291
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
292
|
+
console.log(T.accent("\n 🔍 GMGN API Key Setup\n"));
|
|
293
|
+
console.log(T.muted(" Get your API key at https://gmgn.ai/ai\n"));
|
|
294
|
+
const key = (await ask(" Enter GMGN_API_KEY: ")).trim();
|
|
295
|
+
if (!key) {
|
|
296
|
+
console.log(T.error(" Key is required."));
|
|
297
|
+
rl.close();
|
|
298
|
+
process.exit(1);
|
|
299
|
+
}
|
|
300
|
+
saveGmgnApiKey(key);
|
|
301
|
+
console.log(T.success("\n ✓ GMGN_API_KEY saved to ~/.config/gmgn/.env"));
|
|
302
|
+
console.log(T.muted(" All GMGN commands are now available.\n"));
|
|
303
|
+
rl.close();
|
|
304
|
+
process.exit(0);
|
|
305
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
306
|
+
await new Promise(() => { });
|
|
307
|
+
}
|
|
308
|
+
if (gmgnArgs[0] === "status") {
|
|
309
|
+
console.log(gmgnStatus());
|
|
310
|
+
process.exit(0);
|
|
311
|
+
}
|
|
312
|
+
// Forward to gmgn-cli
|
|
313
|
+
(async () => {
|
|
314
|
+
const { execSync } = await import("node:child_process");
|
|
315
|
+
const fullArgs = ["gmgn-cli", ...gmgnArgs];
|
|
316
|
+
try {
|
|
317
|
+
const output = execSync(fullArgs.join(" "), {
|
|
318
|
+
env: { ...process.env, ...(() => { const e = {}; try {
|
|
319
|
+
const f = require("fs").readFileSync(process.env.HOME + "/.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
|
+
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);
|
|
336
|
+
}
|
|
337
|
+
process.exit(0);
|
|
338
|
+
})();
|
|
339
|
+
await new Promise(() => { });
|
|
340
|
+
}
|
|
341
|
+
if (subcmd === "update" || subcmd === "upgrade") {
|
|
342
|
+
(async () => {
|
|
343
|
+
const { execSync } = await import("node:child_process");
|
|
344
|
+
const pkgName = "@aiaiaichain/agent";
|
|
345
|
+
console.log(T.accent("\n 🤖 AIAIAI Update Check\n"));
|
|
346
|
+
// Get current version
|
|
347
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
348
|
+
const __dir = dirname(__filename);
|
|
349
|
+
const currentPkg = JSON.parse(readFileSync(resolve(__dir, "..", "package.json"), "utf-8"));
|
|
350
|
+
const current = currentPkg.version;
|
|
351
|
+
console.log(T.muted(` Current version: v${current}`));
|
|
352
|
+
// Check npm for latest
|
|
353
|
+
let latest = null;
|
|
354
|
+
let changelog = "";
|
|
355
|
+
try {
|
|
356
|
+
const viewOutput = execSync(`npm view ${pkgName} version`, {
|
|
357
|
+
encoding: "utf-8",
|
|
358
|
+
timeout: 15_000,
|
|
359
|
+
}).trim();
|
|
360
|
+
latest = viewOutput.split("\n").pop() || null;
|
|
361
|
+
// Try to get changelog from npm
|
|
362
|
+
try {
|
|
363
|
+
const changelogOutput = execSync(`npm view ${pkgName} --json`, {
|
|
364
|
+
encoding: "utf-8",
|
|
365
|
+
timeout: 15_000,
|
|
366
|
+
});
|
|
367
|
+
const pkgData = JSON.parse(changelogOutput);
|
|
368
|
+
if (pkgData.gitHead) {
|
|
369
|
+
changelog = `Git: ${pkgData.gitHead.slice(0, 8)}`;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
catch { /* no changelog available */ }
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
console.log(T.error(" Could not reach npm registry. Check your connection."));
|
|
376
|
+
process.exit(1);
|
|
377
|
+
}
|
|
378
|
+
if (!latest) {
|
|
379
|
+
console.log(T.error(" Could not determine latest version."));
|
|
380
|
+
process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
console.log(T.muted(` Latest version: v${latest}`));
|
|
383
|
+
if (changelog)
|
|
384
|
+
console.log(T.muted(` ${changelog}`));
|
|
385
|
+
if (latest === current) {
|
|
386
|
+
console.log(T.success("\n ✅ You're on the latest version!\n"));
|
|
387
|
+
process.exit(0);
|
|
388
|
+
}
|
|
389
|
+
console.log(T.accent(`\n ⚡ Update available: v${current} → v${latest}\n`));
|
|
390
|
+
// Ask to update
|
|
391
|
+
const readline = await import("node:readline");
|
|
392
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
393
|
+
const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
|
|
394
|
+
const confirm = (await ask(" Install update now? (y/n): ")).trim().toLowerCase();
|
|
395
|
+
if (confirm !== "y" && confirm !== "yes") {
|
|
396
|
+
console.log(T.muted("\n Skipped. Run `aiaiai update` anytime to update.\n"));
|
|
397
|
+
rl.close();
|
|
398
|
+
process.exit(0);
|
|
399
|
+
}
|
|
400
|
+
console.log(T.muted("\n Installing update..."));
|
|
401
|
+
try {
|
|
402
|
+
execSync(`npm install -g ${pkgName}`, {
|
|
403
|
+
stdio: "inherit",
|
|
404
|
+
timeout: 120_000,
|
|
405
|
+
});
|
|
406
|
+
console.log(T.success(`\n ✅ Updated to v${latest}!`));
|
|
407
|
+
console.log(T.muted(" Run `aiaiai` to restart with new features.\n"));
|
|
408
|
+
}
|
|
409
|
+
catch (e) {
|
|
410
|
+
console.log(T.error(`\n ❌ Update failed: ${e.message}`));
|
|
411
|
+
console.log(T.muted(" Try manually: npm install -g @aiaiaichain/agent\n"));
|
|
412
|
+
}
|
|
413
|
+
rl.close();
|
|
414
|
+
process.exit(0);
|
|
415
|
+
})().catch(e => { console.error(T.error(`Error: ${e.message}`)); process.exit(1); });
|
|
416
|
+
await new Promise(() => { });
|
|
417
|
+
}
|
|
128
418
|
// ── Resolve extension + prompt ────────────────────────────────────────────────
|
|
129
419
|
let extensionPath = null;
|
|
130
420
|
let promptPath = null;
|
package/dist/core/EnvLoader.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* EnvLoader — loads environment variables from ~/.aiaiai/.env
|
|
2
|
+
* EnvLoader — loads/writes environment variables from ~/.aiaiai/.env
|
|
3
3
|
*/
|
|
4
4
|
export declare class EnvLoader {
|
|
5
5
|
private cache;
|
|
@@ -9,6 +9,9 @@ export declare class EnvLoader {
|
|
|
9
9
|
get(key: string, defaultValue?: string): string | undefined;
|
|
10
10
|
getRequired(key: string): string;
|
|
11
11
|
has(key: string): boolean;
|
|
12
|
+
/** Write a key=value to the .env file and update cache */
|
|
13
|
+
set(key: string, value: string): void;
|
|
14
|
+
getAll(): Record<string, string>;
|
|
12
15
|
reload(): void;
|
|
13
16
|
}
|
|
14
17
|
export declare const env: EnvLoader;
|
package/dist/core/EnvLoader.js
CHANGED
|
@@ -1,40 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* EnvLoader — loads environment variables from ~/.aiaiai/.env
|
|
2
|
+
* EnvLoader — loads/writes environment variables from ~/.aiaiai/.env
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, readFileSync } from
|
|
5
|
-
import { resolve } from
|
|
6
|
-
import { homedir } from
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, chmodSync } from "node:fs";
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
7
|
export class EnvLoader {
|
|
8
8
|
cache = {};
|
|
9
9
|
envPath;
|
|
10
10
|
constructor() {
|
|
11
11
|
const home = process.env.AIAIAI_HOME ?? resolve(homedir(), '.aiaiai');
|
|
12
|
-
this.envPath = resolve(home,
|
|
12
|
+
this.envPath = resolve(home, ".env");
|
|
13
13
|
this.load();
|
|
14
14
|
}
|
|
15
15
|
load() {
|
|
16
|
-
// Load from .env file
|
|
17
16
|
if (existsSync(this.envPath)) {
|
|
18
|
-
const content = readFileSync(this.envPath,
|
|
19
|
-
for (const line of content.split(
|
|
17
|
+
const content = readFileSync(this.envPath, "utf-8");
|
|
18
|
+
for (const line of content.split("\n")) {
|
|
20
19
|
const trimmed = line.trim();
|
|
21
|
-
if (!trimmed || trimmed.startsWith(
|
|
20
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
22
21
|
continue;
|
|
23
|
-
const eqIdx = trimmed.indexOf(
|
|
22
|
+
const eqIdx = trimmed.indexOf("=");
|
|
24
23
|
if (eqIdx === -1)
|
|
25
24
|
continue;
|
|
26
25
|
const key = trimmed.slice(0, eqIdx).trim();
|
|
27
|
-
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g,
|
|
26
|
+
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
|
|
28
27
|
if (key)
|
|
29
28
|
this.cache[key] = value;
|
|
30
29
|
}
|
|
31
30
|
}
|
|
32
|
-
// Process.env overrides file
|
|
33
31
|
for (const key of Object.keys(process.env)) {
|
|
34
32
|
const value = process.env[key];
|
|
35
|
-
if (value !== undefined)
|
|
33
|
+
if (value !== undefined)
|
|
36
34
|
this.cache[key] = value;
|
|
37
|
-
}
|
|
38
35
|
}
|
|
39
36
|
}
|
|
40
37
|
get(key, defaultValue) {
|
|
@@ -47,7 +44,42 @@ export class EnvLoader {
|
|
|
47
44
|
return value;
|
|
48
45
|
}
|
|
49
46
|
has(key) {
|
|
50
|
-
return this.cache[key] !== undefined;
|
|
47
|
+
return this.cache[key] !== undefined && this.cache[key].trim() !== "";
|
|
48
|
+
}
|
|
49
|
+
/** Write a key=value to the .env file and update cache */
|
|
50
|
+
set(key, value) {
|
|
51
|
+
const content = existsSync(this.envPath) ? readFileSync(this.envPath, "utf-8") : "";
|
|
52
|
+
const lines = content.split("\n");
|
|
53
|
+
let found = false;
|
|
54
|
+
for (let i = 0; i < lines.length; i++) {
|
|
55
|
+
const line = lines[i].trim();
|
|
56
|
+
if (line.startsWith(`${key}=`)) {
|
|
57
|
+
lines[i] = `${key}=${value}`;
|
|
58
|
+
found = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!found) {
|
|
63
|
+
if (content && !content.endsWith("\n"))
|
|
64
|
+
lines.push("");
|
|
65
|
+
lines.push(`${key}=${value}`);
|
|
66
|
+
}
|
|
67
|
+
const newContent = lines.join("\n") + "\n";
|
|
68
|
+
writeFileSync(this.envPath, newContent, "utf-8");
|
|
69
|
+
try {
|
|
70
|
+
chmodSync(this.envPath, 0o600);
|
|
71
|
+
}
|
|
72
|
+
catch { /* non-fatal */ }
|
|
73
|
+
this.cache[key] = value;
|
|
74
|
+
process.env[key] = value;
|
|
75
|
+
}
|
|
76
|
+
getAll() {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const [key, value] of Object.entries(this.cache)) {
|
|
79
|
+
if (value !== undefined)
|
|
80
|
+
result[key] = value;
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
51
83
|
}
|
|
52
84
|
reload() {
|
|
53
85
|
this.cache = {};
|
package/dist/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export { loadExtension } from "./loader.js";
|
|
|
17
17
|
export { makeTheme, T, AIAIAI_COLORS } from "./tui/theme.js";
|
|
18
18
|
export { ModelRegistry, modelRegistry, classifyModel } from "./models/ModelRegistry.js";
|
|
19
19
|
export { CostTracker } from "./models/CostTracker.js";
|
|
20
|
-
export type {
|
|
20
|
+
export type { ModelInfo, TieredModel, ModelTier } from "./models/ModelRegistry.js";
|
|
21
21
|
export { fullAnalysis, rsi, macd, ema, sma, bollingerBands, atr, getCandlesTool, getCandlesParams } from "./tools/TechnicalAnalysis.js";
|
|
22
22
|
export { PriceFeed, priceFeed } from "./tools/PriceFeed.js";
|
|
23
23
|
export { NewsFeed, newsFeed, getNewsTool, scoreSentiment } from "./tools/NewsSentiment.js";
|
|
@@ -33,6 +33,11 @@ export type { Goal } from "./session/GoalManager.js";
|
|
|
33
33
|
export type { ContextPressure } from "./session/SessionManager.js";
|
|
34
34
|
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
35
35
|
export type { ScheduledTask } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI_MINT } from "./wallet/AgentWallet.js";
|
|
37
|
+
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
38
|
+
export type { WalletBalance, AgentWallets } from "./wallet/AgentWallet.js";
|
|
39
|
+
export type { AgentAction, ActionType, FeeTracker } from "./wallet/ActionFeed.js";
|
|
40
|
+
export { gmgnTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
36
41
|
export { MCPServer } from "./mcp/server.js";
|
|
37
42
|
export { AgentDir } from "./core/AgentDir.js";
|
|
38
43
|
export { EnvLoader, env } from "./core/EnvLoader.js";
|
package/dist/index.js
CHANGED
|
@@ -33,6 +33,11 @@ export { GoalManager, goalManager } from "./session/GoalManager.js";
|
|
|
33
33
|
export { ContextStore, contextStore } from "./session/ContextStore.js";
|
|
34
34
|
// Scheduler
|
|
35
35
|
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
// Wallet
|
|
37
|
+
export { agentWallet, COLD_WALLET, ACTION_WALLET, DEPOSIT_WALLET, SIGNER, AIAIAI_MINT } from "./wallet/AgentWallet.js";
|
|
38
|
+
export { actionFeed } from "./wallet/ActionFeed.js";
|
|
39
|
+
// GMGN
|
|
40
|
+
export { gmgnTool, gmgnHelp, gmgnStatus, hasGmgnApiKey, saveGmgnApiKey, GMGN_SUBCOMMANDS } from "./tools/GmgnIntegration.js";
|
|
36
41
|
// MCP
|
|
37
42
|
export { MCPServer } from "./mcp/server.js";
|
|
38
43
|
// Core
|
package/dist/mcp/server.js
CHANGED
|
@@ -6,6 +6,8 @@ import { priceFeed } from "../tools/PriceFeed.js";
|
|
|
6
6
|
import { getNewsTool } from "../tools/NewsSentiment.js";
|
|
7
7
|
import { getCandlesTool } from "../tools/TechnicalAnalysis.js";
|
|
8
8
|
import { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "../tools/MarketSentiment.js";
|
|
9
|
+
import { agentWallet } from "../wallet/AgentWallet.js";
|
|
10
|
+
import { actionFeed } from "../wallet/ActionFeed.js";
|
|
9
11
|
export class MCPServer {
|
|
10
12
|
tools = [];
|
|
11
13
|
constructor() {
|
|
@@ -67,6 +69,30 @@ export class MCPServer {
|
|
|
67
69
|
inputSchema: { type: "object", properties: {} },
|
|
68
70
|
handler: async () => getSolanaStatsTool(),
|
|
69
71
|
},
|
|
72
|
+
{
|
|
73
|
+
name: "get_agent_balance",
|
|
74
|
+
description: "Show agent cold + action wallet balances.",
|
|
75
|
+
inputSchema: { type: "object", properties: {} },
|
|
76
|
+
handler: async () => agentWallet.getAgentBalanceTool(),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: "get_deposit_balance",
|
|
80
|
+
description: "Show deposit wallet balance and instructions.",
|
|
81
|
+
inputSchema: { type: "object", properties: {} },
|
|
82
|
+
handler: async () => agentWallet.getDepositBalanceTool(),
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: "get_actions",
|
|
86
|
+
description: "Show recent agent buy/burn actions.",
|
|
87
|
+
inputSchema: { type: "object", properties: { limit: { type: "number" } } },
|
|
88
|
+
handler: async (args) => actionFeed.getActionsTool("", args),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "get_fees",
|
|
92
|
+
description: "Show accumulated fees from agent actions.",
|
|
93
|
+
inputSchema: { type: "object", properties: {} },
|
|
94
|
+
handler: async () => actionFeed.getFeesTool(),
|
|
95
|
+
},
|
|
70
96
|
];
|
|
71
97
|
}
|
|
72
98
|
async start() {
|
|
@@ -23,14 +23,8 @@ export class CostTracker {
|
|
|
23
23
|
this.sessionEntry.totalCost += cost;
|
|
24
24
|
this.sessionEntry.totalTokens += promptTokens + completionTokens;
|
|
25
25
|
}
|
|
26
|
-
estimateCost(
|
|
27
|
-
|
|
28
|
-
const m = all.find(m => m.id === model);
|
|
29
|
-
if (!m)
|
|
30
|
-
return (prompt + completion) * 0.000001;
|
|
31
|
-
const p = parseFloat(m.pricing.prompt) || DEFAULT_RATES.prompt;
|
|
32
|
-
const c = parseFloat(m.pricing.completion) || DEFAULT_RATES.completion;
|
|
33
|
-
return (prompt * p) + (completion * c);
|
|
26
|
+
estimateCost(_model, prompt, completion) {
|
|
27
|
+
return (prompt * DEFAULT_RATES.prompt) + (completion * DEFAULT_RATES.completion);
|
|
34
28
|
}
|
|
35
29
|
statusLine() {
|
|
36
30
|
return `$${this.sessionEntry.totalCost.toFixed(4)}`;
|
|
@@ -1,70 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ModelRegistry — discovers available models
|
|
3
|
-
*
|
|
2
|
+
* ModelRegistry — discovers available models from any configured provider.
|
|
3
|
+
* Supports all 29 providers via their API keys.
|
|
4
4
|
*/
|
|
5
5
|
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
6
6
|
export type ModelTier = "orchestrator" | "analyst" | "worker" | "free";
|
|
7
|
-
export interface
|
|
7
|
+
export interface ModelInfo {
|
|
8
8
|
id: string;
|
|
9
9
|
name: string;
|
|
10
|
-
|
|
11
|
-
description: string;
|
|
10
|
+
provider: string;
|
|
12
11
|
context_length: number;
|
|
13
|
-
|
|
14
|
-
modality: string;
|
|
15
|
-
tokenizer: string;
|
|
16
|
-
instruct_type: string | null;
|
|
17
|
-
};
|
|
18
|
-
pricing: {
|
|
19
|
-
prompt: string;
|
|
20
|
-
completion: string;
|
|
21
|
-
image: string;
|
|
22
|
-
request: string;
|
|
23
|
-
};
|
|
24
|
-
top_provider: {
|
|
25
|
-
max_completion_tokens: number | null;
|
|
26
|
-
is_moderated: boolean;
|
|
27
|
-
};
|
|
28
|
-
per_request_limits: {
|
|
29
|
-
prompt_tokens: number | null;
|
|
30
|
-
completion_tokens: number | null;
|
|
31
|
-
};
|
|
12
|
+
max_tokens: number;
|
|
32
13
|
}
|
|
33
14
|
export interface TieredModel {
|
|
34
|
-
model:
|
|
15
|
+
model: ModelInfo;
|
|
35
16
|
tier: ModelTier;
|
|
36
17
|
available: boolean;
|
|
37
18
|
failures: number;
|
|
38
19
|
}
|
|
39
|
-
export
|
|
40
|
-
tier: ModelTier;
|
|
41
|
-
models: TieredModel[];
|
|
42
|
-
}
|
|
43
|
-
export declare function classifyModel(model: OpenRouterModel): ModelTier;
|
|
20
|
+
export declare function classifyModel(model: ModelInfo): ModelTier;
|
|
44
21
|
export declare class ModelRegistry {
|
|
45
22
|
private models;
|
|
46
23
|
private tiered;
|
|
24
|
+
private providerModels;
|
|
47
25
|
private initialized;
|
|
48
26
|
initialise(): Promise<void>;
|
|
27
|
+
private buildTiers;
|
|
49
28
|
get modelCount(): number;
|
|
29
|
+
getProviderCount(): number;
|
|
30
|
+
getProviderModels(providerId: string): ModelInfo[];
|
|
31
|
+
getAllModels(): ModelInfo[];
|
|
50
32
|
getPool(tier: ModelTier): TieredModel[];
|
|
51
|
-
getAllModels(): OpenRouterModel[];
|
|
52
33
|
getTier(modelId: string): ModelTier | undefined;
|
|
53
34
|
resolvePrimary(): string;
|
|
54
35
|
listModelsParams: import("@sinclair/typebox").TObject<{
|
|
55
36
|
query: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
37
|
+
provider: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
56
38
|
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
57
39
|
available_only: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
58
40
|
}>;
|
|
59
|
-
pickModelParams: import("@sinclair/typebox").TObject<{
|
|
60
|
-
tier: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
61
|
-
min_context: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
62
|
-
}>;
|
|
63
|
-
summaryParams: import("@sinclair/typebox").TObject<{}>;
|
|
64
41
|
listModelsTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
|
|
65
|
-
|
|
66
|
-
summaryTool(): Promise<ToolResult>;
|
|
67
|
-
private getFallbackModels;
|
|
42
|
+
modelSummaryTool(): Promise<ToolResult>;
|
|
68
43
|
}
|
|
69
44
|
export declare const modelRegistry: ModelRegistry;
|
|
70
45
|
//# sourceMappingURL=ModelRegistry.d.ts.map
|