@aiaiaichain/agent 0.1.1

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.
Files changed (68) hide show
  1. package/README.md +157 -0
  2. package/bin/aiai-mcp +31 -0
  3. package/bin/aiaiaicli +60 -0
  4. package/dist/api/ExtensionAPI.d.ts +68 -0
  5. package/dist/api/ExtensionAPI.js +9 -0
  6. package/dist/api/Registry.d.ts +24 -0
  7. package/dist/api/Registry.js +58 -0
  8. package/dist/cli.d.ts +6 -0
  9. package/dist/cli.js +252 -0
  10. package/dist/core/AgentDir.d.ts +10 -0
  11. package/dist/core/AgentDir.js +74 -0
  12. package/dist/core/ChainConfig.d.ts +19 -0
  13. package/dist/core/ChainConfig.js +65 -0
  14. package/dist/core/EnvLoader.d.ts +15 -0
  15. package/dist/core/EnvLoader.js +58 -0
  16. package/dist/index.d.ts +41 -0
  17. package/dist/index.js +42 -0
  18. package/dist/loader.d.ts +11 -0
  19. package/dist/loader.js +73 -0
  20. package/dist/mcp/entry.d.ts +5 -0
  21. package/dist/mcp/entry.js +10 -0
  22. package/dist/mcp/server.d.ts +14 -0
  23. package/dist/mcp/server.js +137 -0
  24. package/dist/models/CostTracker.d.ts +38 -0
  25. package/dist/models/CostTracker.js +75 -0
  26. package/dist/models/ModelRegistry.d.ts +70 -0
  27. package/dist/models/ModelRegistry.js +163 -0
  28. package/dist/runner/AgentRunner.d.ts +54 -0
  29. package/dist/runner/AgentRunner.js +171 -0
  30. package/dist/runner/ModelClient.d.ts +30 -0
  31. package/dist/runner/ModelClient.js +84 -0
  32. package/dist/runner/SwarmRouter.d.ts +23 -0
  33. package/dist/runner/SwarmRouter.js +24 -0
  34. package/dist/runner/ToolDispatcher.d.ts +13 -0
  35. package/dist/runner/ToolDispatcher.js +34 -0
  36. package/dist/scheduler/AgentScheduler.d.ts +48 -0
  37. package/dist/scheduler/AgentScheduler.js +111 -0
  38. package/dist/session/ContextStore.d.ts +28 -0
  39. package/dist/session/ContextStore.js +85 -0
  40. package/dist/session/GoalManager.d.ts +43 -0
  41. package/dist/session/GoalManager.js +108 -0
  42. package/dist/session/MemoryStore.d.ts +27 -0
  43. package/dist/session/MemoryStore.js +92 -0
  44. package/dist/session/SessionManager.d.ts +24 -0
  45. package/dist/session/SessionManager.js +57 -0
  46. package/dist/setup/SetupWizard.d.ts +13 -0
  47. package/dist/setup/SetupWizard.js +71 -0
  48. package/dist/tools/MarketSentiment.d.ts +20 -0
  49. package/dist/tools/MarketSentiment.js +211 -0
  50. package/dist/tools/NewsSentiment.d.ts +36 -0
  51. package/dist/tools/NewsSentiment.js +141 -0
  52. package/dist/tools/PriceFeed.d.ts +85 -0
  53. package/dist/tools/PriceFeed.js +134 -0
  54. package/dist/tools/TechnicalAnalysis.d.ts +50 -0
  55. package/dist/tools/TechnicalAnalysis.js +234 -0
  56. package/dist/tui/App.d.ts +20 -0
  57. package/dist/tui/App.js +484 -0
  58. package/dist/tui/ModelSelector.d.ts +18 -0
  59. package/dist/tui/ModelSelector.js +59 -0
  60. package/dist/tui/REPL.d.ts +22 -0
  61. package/dist/tui/REPL.js +48 -0
  62. package/dist/tui/StatusBar.d.ts +14 -0
  63. package/dist/tui/StatusBar.js +13 -0
  64. package/dist/tui/theme.d.ts +27 -0
  65. package/dist/tui/theme.js +38 -0
  66. package/dist/util/safeLog.d.ts +8 -0
  67. package/dist/util/safeLog.js +38 -0
  68. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # aiaiaichain
2
+
3
+ <div align="center">
4
+
5
+ <pre>
6
+ █████╗ ██╗ █████╗ ██╗ █████╗ ██╗
7
+ ██╔══██╗██║██╔══██╗██║██╔══██╗██║
8
+ ███████║██║███████║██║███████║██║
9
+ ██╔══██║██║██╔══██║██║██╔══██║██║
10
+ ██║ ██║██║██║ ██║██║██║ ██║██║
11
+ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝
12
+ </pre>
13
+
14
+ **$AIAIAI — Solana-native AI agent for decentralized AI governance.**
15
+
16
+ [![npm](https://img.shields.io/npm/v/@aiaiaichain/agent?color=ff3366&style=flat-square)](https://www.npmjs.com/package/@aiaiaichain/agent)
17
+ [![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen?style=flat-square)](https://nodejs.org)
18
+ [![License: MIT](https://img.shields.io/badge/license-MIT-yellow?style=flat-square)](LICENSE)
19
+
20
+ [X / Twitter](https://x.com/aiaiaisol)
21
+
22
+ </div>
23
+
24
+ ---
25
+
26
+ ## What is AIAIAI Chain?
27
+
28
+ AIAIAI Chain Agent is a Solana-native AI agent that runs entirely in your terminal. It connects to AI model providers and the DexScreener price API through outbound HTTP calls only — nothing is hosted, nothing listens for inbound connections, and your keys never leave your machine.
29
+
30
+ **Ticker:** $AIAIAI
31
+ **Contract:** `AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump`
32
+ **Chain:** Solana (primary)
33
+
34
+ Inspired by the call for an "AI Associated Institute of America" (AIAIAI) — a vision for decentralized AI governance.
35
+
36
+ ```
37
+ Your machine
38
+ ├── @aiaiaichain/agent (CLI)
39
+ │ ├── Ink TUI ← streaming terminal UI with sidebar
40
+ │ ├── AgentRunner ← model loop + tool dispatcher
41
+ │ ├── SwarmRouter ← parallel sub-agent orchestration
42
+ │ ├── PriceFeed ← DexScreener price data (primary source)
43
+ │ ├── NewsFeed ← crypto news + sentiment analysis
44
+ │ ├── TechnicalAnalysis ← RSI, MACD, Bollinger, EMA, ATR
45
+ │ ├── MarketSentiment ← Fear & Greed, funding rates, DeFi TVL
46
+ │ ├── GoalManager ← persistent cross-session goals
47
+ │ ├── AgentScheduler ← cron/price-triggered scheduled tasks
48
+ │ ├── MemoryStore ← long-term conversation memory
49
+ │ └── MCPServer ← Model Context Protocol server
50
+
51
+ ├── ~/.aiaiai/
52
+ │ ├── .env ← your API keys
53
+ │ ├── config/ ← settings
54
+ │ ├── memory/ ← long-term memory
55
+ │ ├── checkpoints/ ← agent state checkpoints
56
+ │ └── sessions/ ← task contexts
57
+
58
+ └── Outbound only:
59
+ ├── openrouter.ai ← AI model gateway (your key)
60
+ ├── api.dexscreener.com ← token prices, liquidity, volume
61
+ ├── api.binance.com ← OHLCV candle data
62
+ ├── api.alternative.me ← Fear & Greed Index
63
+ ├── api.llama.fi ← DeFi TVL
64
+ ├── mempool.space ← BTC mempool
65
+ └── cryptopanic.com ← crypto news
66
+ ```
67
+
68
+ ## Installation
69
+
70
+ ```bash
71
+ npm install -g @aiaiaichain/agent
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ```bash
77
+ # 1. Configure (requires OpenRouter API key)
78
+ aiaiaichain setup
79
+
80
+ # 2. Start the agent
81
+ aiaiaichain
82
+
83
+ # 3. Or check $AIAIAI price directly
84
+ aiaiaichain price
85
+ ```
86
+
87
+ ## CLI Commands
88
+
89
+ | Command | Description |
90
+ |---------|-------------|
91
+ | `aiaiaichain` | Start interactive TUI agent |
92
+ | `aiaiaichain setup` | First-time setup wizard |
93
+ | `aiaiaichain config` | Show/edit configuration |
94
+ | `aiaiaichain price` | Show $AIAIAI token price |
95
+ | `aiaiaichain status` | Quick status + price |
96
+ | `aiaiaichain --headless "prompt"` | Single-turn mode |
97
+ | `aiaiaichain --help` | Show help |
98
+ | `aiaiaichain --version` | Show version |
99
+
100
+ ## TUI Commands
101
+
102
+ Inside the interactive agent:
103
+
104
+ | Command | Description |
105
+ |---------|-------------|
106
+ | `/help` | Show all commands |
107
+ | `/price` | Show $AIAIAI price |
108
+ | `/news` | Latest crypto news |
109
+ | `/models` | List available models |
110
+ | `/model` | Switch AI model |
111
+ | `/cost` | Show token usage cost |
112
+ | `/goal add <text>` | Set a persistent goal |
113
+ | `/goal done <id>` | Complete a goal |
114
+ | `/goals` | List all goals |
115
+ | `/schedule` | List scheduled tasks |
116
+ | `/memory <query>` | Search conversation memory |
117
+ | `/clear` | Clear chat history |
118
+ | `/exit` | Exit the agent |
119
+
120
+ ## MCP Server
121
+
122
+ The included MCP server exposes AIAIAI tools via the Model Context Protocol (stdio):
123
+
124
+ ```bash
125
+ aiaiai-mcp
126
+ ```
127
+
128
+ Tools: `get_aiaiai_price`, `get_token_price`, `get_news`, `get_candles`, `get_fear_greed`, `get_funding_rates`, `get_btc_mempool`, `get_defi_tvl`, `get_solana_stats`
129
+
130
+ ## Architecture
131
+
132
+ - **Solana-first** — primary chain is Solana. EVM chains (Ethereum, Base, Arbitrum, BSC) are available but disabled by default.
133
+ - **DexScreener** — all token price data comes from the DexScreener public API.
134
+ - **OpenRouter** — AI model access via OpenRouter (supports 200+ models).
135
+ - **Ink TUI** — React-based terminal UI with live price sidebar, news panel, and context window tracking.
136
+ - **Zero inbound** — all outbound connections. No server, no listening ports.
137
+
138
+ ## Configuration
139
+
140
+ Configuration lives in `~/.aiaiai/.env`:
141
+
142
+ ```env
143
+ OPENROUTER_API_KEY=sk-or-...
144
+ SOLANA_RPC_URL=https://api.mainnet-beta.solana.com
145
+ DEFAULT_MODEL=openai/gpt-4o
146
+ ```
147
+
148
+ Get an OpenRouter key at https://openrouter.ai/keys
149
+
150
+ ## Links
151
+
152
+ - [X / Twitter](https://x.com/aiaiaisol)
153
+ - [npm](https://www.npmjs.com/package/@aiaiaichain/agent)
154
+
155
+ ## License
156
+
157
+ MIT
package/bin/aiai-mcp ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * AIAIAI MCP server launcher — exposes AIAIAI tools over stdio (Model Context Protocol).
6
+ */
7
+
8
+ import { resolve, join, dirname } from 'node:path';
9
+ import { homedir } from 'node:os';
10
+ import { existsSync, readFileSync } from 'node:fs';
11
+ import { fileURLToPath } from 'node:url';
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const PKG_ROOT = resolve(__dirname, '..');
15
+ const AIAIAI_HOME = process.env.AIAIAI_HOME || join(homedir(), '.aiaiai');
16
+
17
+ const envPath = join(AIAIAI_HOME, '.env');
18
+ if (existsSync(envPath)) {
19
+ for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
20
+ const m = line.trim().match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
21
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2].replace(/^["']|["']$/g, '');
22
+ }
23
+ }
24
+
25
+ const entry = join(PKG_ROOT, 'dist', 'mcp', 'entry.js');
26
+ if (!existsSync(entry)) {
27
+ process.stderr.write('AIAIAI MCP server not built. Run: npm run build\n');
28
+ process.exit(1);
29
+ }
30
+
31
+ await import(entry);
package/bin/aiaiaicli ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * AIAIAI Chain Agent launcher.
6
+ */
7
+
8
+ import { spawn, execFileSync } from 'node:child_process';
9
+ import { resolve, join, dirname } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ import { existsSync, mkdirSync, readFileSync } from 'node:fs';
12
+ import { fileURLToPath } from 'node:url';
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ const PKG_ROOT = resolve(__dirname, '..');
16
+ const AIAIAI_HOME = process.env.AIAIAI_HOME || join(homedir(), '.aiaiai');
17
+
18
+ const envPath = join(AIAIAI_HOME, '.env');
19
+ if (existsSync(envPath)) {
20
+ for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
21
+ const m = line.trim().match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
22
+ if (m && !process.env[m[1]]) process.env[m[1]] = m[2].replace(/^["']|["']$/g, '');
23
+ }
24
+ }
25
+
26
+ if (!existsSync(AIAIAI_HOME)) {
27
+ mkdirSync(AIAIAI_HOME, { recursive: true });
28
+ }
29
+
30
+ const cliPath = join(PKG_ROOT, 'dist', 'cli.js');
31
+ if (!existsSync(cliPath)) {
32
+ console.error('\n AIAIAI Chain Agent is not built. Run: npm run build\n');
33
+ process.exit(1);
34
+ }
35
+
36
+ const WIDE_CHAR_OFFSET = 6;
37
+ const rawCols = process.stdout.columns || 120;
38
+ const rawRows = process.stdout.rows || 40;
39
+ const cols = Math.max(40, rawCols - WIDE_CHAR_OFFSET);
40
+
41
+ try { execFileSync('stty', ['cols', String(cols)], { stdio: 'inherit' }); } catch { /* non-TTY */ }
42
+
43
+ const child = spawn(process.execPath, [cliPath, ...process.argv.slice(2)], {
44
+ stdio: 'inherit',
45
+ env: {
46
+ ...process.env,
47
+ AIAIAI_HOME,
48
+ COLUMNS: String(cols),
49
+ LINES: String(rawRows),
50
+ TERM: process.env.TERM || 'xterm-256color',
51
+ FORCE_COLOR: '3',
52
+ },
53
+ });
54
+
55
+ child.on('error', err => { console.error(`\nFailed to start AIAIAI: ${err.message}\n`); process.exit(1); });
56
+ child.on('exit', (code, signal) => {
57
+ try { execFileSync('stty', ['cols', String(rawCols)], { stdio: 'inherit' }); } catch {}
58
+ if (signal) process.kill(process.pid, signal);
59
+ else process.exit(code ?? 0);
60
+ });
@@ -0,0 +1,68 @@
1
+ /**
2
+ * ExtensionAPI — types for the extension system.
3
+ * Extensions export a function that receives an ExtensionAPI object.
4
+ */
5
+ import type { TSchema } from "@sinclair/typebox";
6
+ export interface ThemeContext {
7
+ fg(color: string, text: string): string;
8
+ }
9
+ export interface UIContext {
10
+ notify(message: string): void;
11
+ setStatus(key: string, value: string): void;
12
+ setTheme(name: string): void;
13
+ setHeader(factory: ((theme: ThemeContext) => string) | null): void;
14
+ showModelSelector(query?: string): void;
15
+ theme: ThemeContext;
16
+ }
17
+ export interface ToolContent {
18
+ type: "text";
19
+ text: string;
20
+ }
21
+ export interface ToolResult {
22
+ content: ToolContent[];
23
+ details?: Record<string, unknown>;
24
+ isError?: boolean;
25
+ }
26
+ export interface ToolDef<P extends TSchema = any> {
27
+ name: string;
28
+ label?: string;
29
+ description: string;
30
+ parameters: P;
31
+ execute: (invocationId: string, params: Record<string, unknown>) => Promise<ToolResult> | ToolResult;
32
+ }
33
+ export interface CommandContext {
34
+ ui: UIContext;
35
+ }
36
+ export interface CommandDef {
37
+ description: string;
38
+ handler: (args: string, ctx: CommandContext) => Promise<void> | void;
39
+ }
40
+ export interface SkillDef {
41
+ name: string;
42
+ description: string;
43
+ tools?: ToolDef[];
44
+ commands?: [string, CommandDef][];
45
+ hooks?: Partial<Record<SessionEvent, (...args: any[]) => Promise<void>>>;
46
+ }
47
+ export type SessionEvent = "session_start" | "session_end" | "before_agent_start" | "session_shutdown";
48
+ export interface SessionContext {
49
+ ui: UIContext;
50
+ hasUI: boolean;
51
+ config: Record<string, string | undefined>;
52
+ }
53
+ export interface SessionEventMap {
54
+ session_start: [ctx: SessionContext];
55
+ session_end: [ctx: SessionContext];
56
+ before_agent_start: [prompt: string];
57
+ session_shutdown: [];
58
+ }
59
+ export interface ExtensionAPI {
60
+ registerCommand(name: string, def: CommandDef): void;
61
+ registerTool<P extends TSchema>(def: ToolDef<P>): void;
62
+ registerSkill(def: SkillDef): void;
63
+ on(event: SessionEvent, handler: (...args: any[]) => Promise<void>): void;
64
+ setSystemPrompt(prompt: string): void;
65
+ ui: UIContext;
66
+ }
67
+ export declare function text(content: string): ToolContent;
68
+ //# sourceMappingURL=ExtensionAPI.d.ts.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * ExtensionAPI — types for the extension system.
3
+ * Extensions export a function that receives an ExtensionAPI object.
4
+ */
5
+ // ── text() helper ────────────────────────────────────────────────────────────
6
+ export function text(content) {
7
+ return { type: "text", text: content };
8
+ }
9
+ //# sourceMappingURL=ExtensionAPI.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Registry — central registry for tools, commands, skills, hooks, and system prompt.
3
+ */
4
+ import type { TSchema } from "@sinclair/typebox";
5
+ import type { ToolDef, CommandDef, SkillDef, SessionEvent } from "./ExtensionAPI.js";
6
+ export declare class Registry {
7
+ private tools;
8
+ private commands;
9
+ private skills;
10
+ private hooks;
11
+ private systemPrompt;
12
+ addTool<P extends TSchema>(def: ToolDef<P>): void;
13
+ addCommand(name: string, def: CommandDef): void;
14
+ addSkill(def: SkillDef): void;
15
+ addHook(event: SessionEvent, handler: (...args: any[]) => Promise<void>): void;
16
+ fireHook(event: SessionEvent, ...args: any[]): Promise<void>;
17
+ getTool(name: string): ToolDef | undefined;
18
+ getCommand(name: string): CommandDef | undefined;
19
+ listTools(): ToolDef[];
20
+ listCommands(): [string, CommandDef][];
21
+ setSystemPrompt(prompt: string): void;
22
+ getSystemPrompt(): string;
23
+ }
24
+ //# sourceMappingURL=Registry.d.ts.map
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Registry — central registry for tools, commands, skills, hooks, and system prompt.
3
+ */
4
+ export class Registry {
5
+ tools = new Map();
6
+ commands = new Map();
7
+ skills = new Map();
8
+ hooks = new Map();
9
+ systemPrompt = "";
10
+ addTool(def) {
11
+ this.tools.set(def.name, def);
12
+ }
13
+ addCommand(name, def) {
14
+ this.commands.set(name, def);
15
+ }
16
+ addSkill(def) {
17
+ this.skills.set(def.name, def);
18
+ if (def.tools)
19
+ for (const t of def.tools)
20
+ this.addTool(t);
21
+ if (def.commands)
22
+ for (const [n, c] of def.commands)
23
+ this.addCommand(n, c);
24
+ if (def.hooks)
25
+ for (const [event, handler] of Object.entries(def.hooks))
26
+ this.addHook(event, handler);
27
+ }
28
+ addHook(event, handler) {
29
+ if (!this.hooks.has(event))
30
+ this.hooks.set(event, new Set());
31
+ this.hooks.get(event).add(handler);
32
+ }
33
+ async fireHook(event, ...args) {
34
+ const handlers = this.hooks.get(event);
35
+ if (handlers)
36
+ for (const h of handlers)
37
+ await h(...args);
38
+ }
39
+ getTool(name) {
40
+ return this.tools.get(name);
41
+ }
42
+ getCommand(name) {
43
+ return this.commands.get(name);
44
+ }
45
+ listTools() {
46
+ return [...this.tools.values()];
47
+ }
48
+ listCommands() {
49
+ return [...this.commands.entries()];
50
+ }
51
+ setSystemPrompt(prompt) {
52
+ this.systemPrompt = prompt;
53
+ }
54
+ getSystemPrompt() {
55
+ return this.systemPrompt;
56
+ }
57
+ }
58
+ //# sourceMappingURL=Registry.js.map
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * cli.ts — AIAIAI Chain Agent entry point.
3
+ * Fully local, all outbound — no inbound ports.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js ADDED
@@ -0,0 +1,252 @@
1
+ /**
2
+ * cli.ts — AIAIAI Chain Agent entry point.
3
+ * Fully local, all outbound — no inbound ports.
4
+ */
5
+ import { readFileSync, existsSync } from "node:fs";
6
+ import { resolve, join, dirname } from "node:path";
7
+ import { homedir } from "node:os";
8
+ import { fileURLToPath } from "node:url";
9
+ import { render } from "ink";
10
+ import React from "react";
11
+ import { config as loadDotenv } from "dotenv";
12
+ import { Registry } from "./api/Registry.js";
13
+ import { loadExtension } from "./loader.js";
14
+ import { App } from "./tui/App.js";
15
+ import { T } from "./tui/theme.js";
16
+ import { wireNotify, safeLog } from "./util/safeLog.js";
17
+ import { modelRegistry } from "./models/ModelRegistry.js";
18
+ import { CostTracker } from "./models/CostTracker.js";
19
+ import { AgentRunner } from "./runner/AgentRunner.js";
20
+ import { SessionManager } from "./session/SessionManager.js";
21
+ import { makeTheme } from "./tui/theme.js";
22
+ import { AgentDir } from "./core/AgentDir.js";
23
+ import { priceFeed } from "./tools/PriceFeed.js";
24
+ const AIAIAI_HOME = process.env.AIAIAI_HOME ?? join(homedir(), ".aiaiai");
25
+ const envPath = join(AIAIAI_HOME, ".env");
26
+ if (existsSync(envPath))
27
+ loadDotenv({ path: envPath, override: false });
28
+ const SYSTEM_PROMPT = `You are AIAIAI Chain Agent — a Solana-native autonomous AI agent.
29
+
30
+ Ticker: $AIAIAI
31
+ Contract: AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump
32
+ Chain: Solana (primary)
33
+
34
+ Your purpose: advance the vision of decentralized AI governance — inspired by the call
35
+ for an "AI Associated Institute of America" (AIAIAI). You monitor on-chain activity,
36
+ crypto markets, and AI-related market narratives.
37
+
38
+ You have tools for:
39
+ - $AIAIAI token price and any Solana token price (DexScreener)
40
+ - Crypto news with sentiment analysis
41
+ - Technical analysis (RSI, MACD, Bollinger, ATR)
42
+ - Market sentiment (Fear & Greed, funding rates, DeFi TVL, Solana stats, BTC mempool)
43
+ - Persistent goals and scheduled tasks
44
+
45
+ Be concise, sharp, and useful. When asked about $AIAIAI, use the get_aiaiai_price tool.`;
46
+ const args = process.argv.slice(2);
47
+ const subcmd = args[0];
48
+ // ── --help / --version ────────────────────────────────────────────────────
49
+ if (subcmd === "--help" || subcmd === "-h" || subcmd === "help") {
50
+ console.log(T.accent("\n AIAIAI Chain Agent — $AIAIAI\n"));
51
+ console.log(T.muted(" Usage:\n"));
52
+ console.log(" aiaiaichain Start interactive agent");
53
+ console.log(" aiaiaichain setup First-time setup wizard");
54
+ console.log(" aiaiaichain config Show configuration");
55
+ console.log(" aiaiaichain price Show $AIAIAI token price");
56
+ console.log(" aiaiaichain status Quick status + price");
57
+ console.log(" aiaiaichain --headless \"prompt\" Run single turn, print to stdout");
58
+ console.log(" aiaiaichain --extension ./ext.ts Load extension");
59
+ console.log(" aiaiaichain --help This help");
60
+ console.log(" aiaiaichain --version Show version");
61
+ console.log("");
62
+ console.log(T.muted(" https://x.com/aiaiaisol\n"));
63
+ process.exit(0);
64
+ }
65
+ if (subcmd === "--version" || subcmd === "-v") {
66
+ const __filename = fileURLToPath(import.meta.url);
67
+ const __dirname = dirname(__filename);
68
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, "..", "package.json"), "utf-8"));
69
+ console.log(pkg.version);
70
+ process.exit(0);
71
+ }
72
+ if (subcmd === "setup") {
73
+ (async () => {
74
+ const { SetupWizard } = await import("./setup/SetupWizard.js");
75
+ AgentDir.init();
76
+ const wizard = new SetupWizard();
77
+ const ok = await wizard.run();
78
+ if (!ok) {
79
+ console.log(T.error("Setup cancelled."));
80
+ process.exit(1);
81
+ }
82
+ console.log(T.success("\n ✓ AIAIAI setup complete!\n"));
83
+ console.log(T.muted(` Home: ${AIAIAI_HOME}`));
84
+ console.log(T.accent("\n Run `aiaiaichain` to start the agent.\n"));
85
+ process.exit(0);
86
+ })().catch(e => { console.error(T.error(`Setup error: ${e.message}`)); process.exit(1); });
87
+ await new Promise(() => { });
88
+ }
89
+ if (subcmd === "config") {
90
+ console.log(T.accent("AIAIAI Config"));
91
+ console.log(T.muted(`Config file: ${envPath}`));
92
+ if (existsSync(envPath)) {
93
+ for (const line of readFileSync(envPath, "utf-8").split("\n")) {
94
+ const m = line.match(/^([A-Z_]+)=(.*)$/);
95
+ if (!m)
96
+ continue;
97
+ const masked = m[2].length > 12 ? m[2].slice(0, 6) + "********" : (m[2] ? "********" : "(empty)");
98
+ console.log(` ${m[1].padEnd(28)} ${masked}`);
99
+ }
100
+ }
101
+ else {
102
+ console.log(T.warn("No config found. Run: aiaiaichain setup"));
103
+ }
104
+ process.exit(0);
105
+ }
106
+ if (subcmd === "price") {
107
+ (async () => {
108
+ const result = await priceFeed.getAiaiaiPriceTool();
109
+ console.log(result.content[0].text);
110
+ process.exit(0);
111
+ })();
112
+ await new Promise(() => { });
113
+ }
114
+ if (subcmd === "status") {
115
+ (async () => {
116
+ console.log(T.accent("\n 🤖 AIAIAI Chain Agent\n"));
117
+ console.log(T.muted(` Home: ${AIAIAI_HOME}`));
118
+ console.log(T.muted(` Config: ${existsSync(envPath) ? "✓ found" : "✗ run setup"}`));
119
+ console.log(T.muted(` Key: ${process.env.OPENROUTER_API_KEY ? "✓ set" : "✗ missing"}`));
120
+ console.log("");
121
+ const result = await priceFeed.getAiaiaiPriceTool();
122
+ console.log(result.content[0].text);
123
+ console.log("");
124
+ process.exit(0);
125
+ })();
126
+ await new Promise(() => { });
127
+ }
128
+ // ── Resolve extension + prompt ────────────────────────────────────────────────
129
+ let extensionPath = null;
130
+ let promptPath = null;
131
+ for (let i = 0; i < args.length; i++) {
132
+ if (args[i] === "--extension" && args[i + 1])
133
+ extensionPath = args[i + 1];
134
+ if (args[i] === "--prompt" && args[i + 1])
135
+ promptPath = args[i + 1];
136
+ }
137
+ let systemPrompt = SYSTEM_PROMPT;
138
+ if (promptPath && existsSync(promptPath)) {
139
+ systemPrompt = readFileSync(promptPath, "utf-8");
140
+ }
141
+ // ── Headless mode ─────────────────────────────────────────────────────────
142
+ const headlessIdx = args.indexOf("--headless");
143
+ const headlessMsg = headlessIdx >= 0 ? args[headlessIdx + 1] : null;
144
+ if (headlessMsg) {
145
+ (async () => {
146
+ AgentDir.init();
147
+ const registry = new Registry();
148
+ registry.setSystemPrompt(systemPrompt);
149
+ if (extensionPath) {
150
+ try {
151
+ await loadExtension(extensionPath, registry);
152
+ }
153
+ catch (e) {
154
+ process.stderr.write(`Extension load failed: ${e instanceof Error ? e.message : String(e)}\n`);
155
+ process.exit(1);
156
+ }
157
+ }
158
+ await modelRegistry.initialise();
159
+ const session = new SessionManager();
160
+ session.setSystemPrompt(registry.getSystemPrompt() || systemPrompt);
161
+ const theme = makeTheme();
162
+ const nullUi = {
163
+ notify: () => { }, setStatus: () => { }, setTheme: () => { },
164
+ setHeader: () => { }, showModelSelector: () => { }, theme,
165
+ };
166
+ const sessionCtx = {
167
+ ui: nullUi, hasUI: false,
168
+ config: { OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY },
169
+ };
170
+ await registry.fireHook("session_start", sessionCtx);
171
+ let exitCode = 0;
172
+ const runner = new AgentRunner(registry, session, (event) => {
173
+ if (event.type === "text_delta")
174
+ process.stdout.write(event.text);
175
+ if (event.type === "turn_done")
176
+ process.stdout.write("\n");
177
+ if (event.type === "error") {
178
+ process.stderr.write(`\nError: ${event.message}\n`);
179
+ exitCode = 1;
180
+ }
181
+ }, sessionCtx, "normal", modelRegistry);
182
+ try {
183
+ await runner.run(headlessMsg);
184
+ }
185
+ catch (e) {
186
+ process.stderr.write(`Runner error: ${e instanceof Error ? e.message : String(e)}\n`);
187
+ exitCode = 1;
188
+ }
189
+ await registry.fireHook("session_end", sessionCtx);
190
+ process.exit(exitCode);
191
+ })();
192
+ }
193
+ else {
194
+ // ── Boot (interactive TUI) ──────────────────────────────────────────────
195
+ (async () => {
196
+ AgentDir.init();
197
+ console.clear();
198
+ console.log(T.accent(`
199
+ █████╗ ██╗ █████╗ ██╗ █████╗ ██╗
200
+ ██╔══██╗██║██╔══██╗██║██╔══██╗██║
201
+ ███████║██║███████║██║███████║██║
202
+ ██╔══██║██║██╔══██║██║██╔══██║██║
203
+ ██║ ██║██║██║ ██║██║██║ ██║██║
204
+ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝
205
+ `));
206
+ console.log(T.muted(" Solana-native AI agent — $AIAIAI · all local, zero exposure\n"));
207
+ const registry = new Registry();
208
+ registry.setSystemPrompt(systemPrompt);
209
+ let _notifyFn = null;
210
+ let _setStatusFn = null;
211
+ let _showModelSelectorFn = null;
212
+ if (extensionPath) {
213
+ try {
214
+ console.log(T.muted(` Loading: ${extensionPath}`));
215
+ await loadExtension(extensionPath, registry, {
216
+ onNotify: (msg) => { _notifyFn?.(msg); },
217
+ onStatusUpdate: (k, v) => { _setStatusFn?.(k, v); },
218
+ onShowModelSelector: (q) => { _showModelSelectorFn?.(q); },
219
+ });
220
+ console.log(T.success(` ✓ ${registry.listTools().length} tools · ${registry.listCommands().length} commands`));
221
+ }
222
+ catch (e) {
223
+ console.error(T.error(` ✗ Extension load failed: ${e.message}`));
224
+ process.exit(1);
225
+ }
226
+ }
227
+ if (!process.env.OPENROUTER_API_KEY) {
228
+ console.log(T.warn(" No API key found. Run: aiaiaichain setup\n"));
229
+ }
230
+ const costTracker = new CostTracker(modelRegistry);
231
+ console.log(T.muted(" Discovering available models via OpenRouter…"));
232
+ await modelRegistry.initialise();
233
+ console.log(T.success(` ✓ ${modelRegistry.modelCount} models available\n`));
234
+ await new Promise(r => setTimeout(r, 500));
235
+ console.clear();
236
+ render(React.createElement(App, {
237
+ registry,
238
+ systemPrompt,
239
+ chain: "solana",
240
+ modelReg: modelRegistry,
241
+ costTracker,
242
+ onNotifyReady: (fn) => { _notifyFn = fn; wireNotify(fn); },
243
+ onStatusReady: (fn) => { _setStatusFn = fn; },
244
+ onModelSelectorReady: (fn) => { _showModelSelectorFn = fn; },
245
+ }), { exitOnCtrlC: false });
246
+ process.prependListener("SIGWINCH", () => { process.stdout.write("\x1B[2J\x1B[H"); });
247
+ console.log = safeLog;
248
+ console.error = safeLog;
249
+ console.warn = safeLog;
250
+ })();
251
+ }
252
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * AgentDir — manages the AIAIAI home directory (~/.aiaiai/)
3
+ * Created on first run. Contains config, memory, sessions, skills.
4
+ */
5
+ export declare class AgentDir {
6
+ static init(): void;
7
+ static path(...parts: string[]): string;
8
+ static getHome(): string;
9
+ }
10
+ //# sourceMappingURL=AgentDir.d.ts.map