@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.
- package/README.md +157 -0
- package/bin/aiai-mcp +31 -0
- package/bin/aiaiaicli +60 -0
- package/dist/api/ExtensionAPI.d.ts +68 -0
- package/dist/api/ExtensionAPI.js +9 -0
- package/dist/api/Registry.d.ts +24 -0
- package/dist/api/Registry.js +58 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +252 -0
- package/dist/core/AgentDir.d.ts +10 -0
- package/dist/core/AgentDir.js +74 -0
- package/dist/core/ChainConfig.d.ts +19 -0
- package/dist/core/ChainConfig.js +65 -0
- package/dist/core/EnvLoader.d.ts +15 -0
- package/dist/core/EnvLoader.js +58 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +42 -0
- package/dist/loader.d.ts +11 -0
- package/dist/loader.js +73 -0
- package/dist/mcp/entry.d.ts +5 -0
- package/dist/mcp/entry.js +10 -0
- package/dist/mcp/server.d.ts +14 -0
- package/dist/mcp/server.js +137 -0
- package/dist/models/CostTracker.d.ts +38 -0
- package/dist/models/CostTracker.js +75 -0
- package/dist/models/ModelRegistry.d.ts +70 -0
- package/dist/models/ModelRegistry.js +163 -0
- package/dist/runner/AgentRunner.d.ts +54 -0
- package/dist/runner/AgentRunner.js +171 -0
- package/dist/runner/ModelClient.d.ts +30 -0
- package/dist/runner/ModelClient.js +84 -0
- package/dist/runner/SwarmRouter.d.ts +23 -0
- package/dist/runner/SwarmRouter.js +24 -0
- package/dist/runner/ToolDispatcher.d.ts +13 -0
- package/dist/runner/ToolDispatcher.js +34 -0
- package/dist/scheduler/AgentScheduler.d.ts +48 -0
- package/dist/scheduler/AgentScheduler.js +111 -0
- package/dist/session/ContextStore.d.ts +28 -0
- package/dist/session/ContextStore.js +85 -0
- package/dist/session/GoalManager.d.ts +43 -0
- package/dist/session/GoalManager.js +108 -0
- package/dist/session/MemoryStore.d.ts +27 -0
- package/dist/session/MemoryStore.js +92 -0
- package/dist/session/SessionManager.d.ts +24 -0
- package/dist/session/SessionManager.js +57 -0
- package/dist/setup/SetupWizard.d.ts +13 -0
- package/dist/setup/SetupWizard.js +71 -0
- package/dist/tools/MarketSentiment.d.ts +20 -0
- package/dist/tools/MarketSentiment.js +211 -0
- package/dist/tools/NewsSentiment.d.ts +36 -0
- package/dist/tools/NewsSentiment.js +141 -0
- package/dist/tools/PriceFeed.d.ts +85 -0
- package/dist/tools/PriceFeed.js +134 -0
- package/dist/tools/TechnicalAnalysis.d.ts +50 -0
- package/dist/tools/TechnicalAnalysis.js +234 -0
- package/dist/tui/App.d.ts +20 -0
- package/dist/tui/App.js +484 -0
- package/dist/tui/ModelSelector.d.ts +18 -0
- package/dist/tui/ModelSelector.js +59 -0
- package/dist/tui/REPL.d.ts +22 -0
- package/dist/tui/REPL.js +48 -0
- package/dist/tui/StatusBar.d.ts +14 -0
- package/dist/tui/StatusBar.js +13 -0
- package/dist/tui/theme.d.ts +27 -0
- package/dist/tui/theme.js +38 -0
- package/dist/util/safeLog.d.ts +8 -0
- package/dist/util/safeLog.js +38 -0
- package/package.json +64 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentDir — manages the AIAIAI home directory (~/.aiaiai/)
|
|
3
|
+
* Created on first run. Contains config, memory, sessions, skills.
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import { resolve } from 'node:path';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
const HOME = process.env.AIAIAI_HOME ?? resolve(homedir(), '.aiaiai');
|
|
9
|
+
const DIRS = [
|
|
10
|
+
'config',
|
|
11
|
+
'memory',
|
|
12
|
+
'checkpoints',
|
|
13
|
+
'sessions',
|
|
14
|
+
'skills',
|
|
15
|
+
];
|
|
16
|
+
const AIAIAI_MD_CONTENT = `# AIAIAI Chain Agent
|
|
17
|
+
|
|
18
|
+
Solana-native AI agent for decentralized AI governance.
|
|
19
|
+
Ticker: $AIAIAI (AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump)
|
|
20
|
+
|
|
21
|
+
## Directory layout
|
|
22
|
+
|
|
23
|
+
| Path | Contents |
|
|
24
|
+
|----------------|---------------------------------------------|
|
|
25
|
+
| config/ | Settings and API keys |
|
|
26
|
+
| memory/ | Long-term conversation memory |
|
|
27
|
+
| checkpoints/ | Agent state checkpoints |
|
|
28
|
+
| sessions/ | REPL conversation sessions |
|
|
29
|
+
| skills/ | Strategy skill definitions |
|
|
30
|
+
| .env | API keys and runtime config |
|
|
31
|
+
| AIAIAI.md | This file |
|
|
32
|
+
| settings.json | User preferences |
|
|
33
|
+
|
|
34
|
+
## Quick reference
|
|
35
|
+
|
|
36
|
+
\`\`\`
|
|
37
|
+
aiaiaichain — start interactive REPL
|
|
38
|
+
aiaiaichain setup — re-run setup wizard
|
|
39
|
+
aiaiaichain config — show configuration
|
|
40
|
+
aiaiaichain price — show $AIAIAI token price
|
|
41
|
+
\`\`\`
|
|
42
|
+
`;
|
|
43
|
+
export class AgentDir {
|
|
44
|
+
static init() {
|
|
45
|
+
if (!existsSync(HOME))
|
|
46
|
+
mkdirSync(HOME, { recursive: true });
|
|
47
|
+
for (const dir of DIRS) {
|
|
48
|
+
const full = resolve(HOME, dir);
|
|
49
|
+
if (!existsSync(full))
|
|
50
|
+
mkdirSync(full, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
const mdPath = resolve(HOME, 'AIAIAI.md');
|
|
53
|
+
if (!existsSync(mdPath))
|
|
54
|
+
writeFileSync(mdPath, AIAIAI_MD_CONTENT, 'utf-8');
|
|
55
|
+
const histPath = resolve(HOME, 'history.jsonl');
|
|
56
|
+
if (!existsSync(histPath))
|
|
57
|
+
writeFileSync(histPath, '', 'utf-8');
|
|
58
|
+
const settingsPath = resolve(HOME, 'settings.json');
|
|
59
|
+
if (!existsSync(settingsPath)) {
|
|
60
|
+
writeFileSync(settingsPath, JSON.stringify({
|
|
61
|
+
theme: 'dark',
|
|
62
|
+
autoSave: true,
|
|
63
|
+
activeChain: 'solana',
|
|
64
|
+
}, null, 2), 'utf-8');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
static path(...parts) {
|
|
68
|
+
return resolve(HOME, ...parts);
|
|
69
|
+
}
|
|
70
|
+
static getHome() {
|
|
71
|
+
return HOME;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=AgentDir.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChainConfig — single source of truth for supported chains.
|
|
3
|
+
* Solana is the default/primary chain. EVM chains are available but disabled by default.
|
|
4
|
+
*/
|
|
5
|
+
export interface ChainInfo {
|
|
6
|
+
name: string;
|
|
7
|
+
symbol: string;
|
|
8
|
+
chainId: number;
|
|
9
|
+
rpcUrl: string;
|
|
10
|
+
explorerUrl: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
primary: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare const CHAINS: Record<string, ChainInfo>;
|
|
15
|
+
export declare function getPrimaryChain(): ChainInfo;
|
|
16
|
+
export declare function getEnabledChains(): ChainInfo[];
|
|
17
|
+
export declare function getChain(name: string): ChainInfo | undefined;
|
|
18
|
+
export declare function getSupportedChains(): string[];
|
|
19
|
+
//# sourceMappingURL=ChainConfig.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChainConfig — single source of truth for supported chains.
|
|
3
|
+
* Solana is the default/primary chain. EVM chains are available but disabled by default.
|
|
4
|
+
*/
|
|
5
|
+
export const CHAINS = {
|
|
6
|
+
solana: {
|
|
7
|
+
name: 'solana',
|
|
8
|
+
symbol: 'SOL',
|
|
9
|
+
chainId: 101,
|
|
10
|
+
rpcUrl: 'https://api.mainnet-beta.solana.com',
|
|
11
|
+
explorerUrl: 'https://solscan.io',
|
|
12
|
+
enabled: true,
|
|
13
|
+
primary: true,
|
|
14
|
+
},
|
|
15
|
+
ethereum: {
|
|
16
|
+
name: 'ethereum',
|
|
17
|
+
symbol: 'ETH',
|
|
18
|
+
chainId: 1,
|
|
19
|
+
rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/',
|
|
20
|
+
explorerUrl: 'https://etherscan.io',
|
|
21
|
+
enabled: false,
|
|
22
|
+
primary: false,
|
|
23
|
+
},
|
|
24
|
+
bsc: {
|
|
25
|
+
name: 'bsc',
|
|
26
|
+
symbol: 'BNB',
|
|
27
|
+
chainId: 56,
|
|
28
|
+
rpcUrl: 'https://bsc-dataseed.binance.org',
|
|
29
|
+
explorerUrl: 'https://bscscan.com',
|
|
30
|
+
enabled: false,
|
|
31
|
+
primary: false,
|
|
32
|
+
},
|
|
33
|
+
base: {
|
|
34
|
+
name: 'base',
|
|
35
|
+
symbol: 'ETH',
|
|
36
|
+
chainId: 8453,
|
|
37
|
+
rpcUrl: 'https://mainnet.base.org',
|
|
38
|
+
explorerUrl: 'https://basescan.org',
|
|
39
|
+
enabled: false,
|
|
40
|
+
primary: false,
|
|
41
|
+
},
|
|
42
|
+
arbitrum: {
|
|
43
|
+
name: 'arbitrum',
|
|
44
|
+
symbol: 'ETH',
|
|
45
|
+
chainId: 42161,
|
|
46
|
+
rpcUrl: 'https://arb1.arbitrum.io/rpc',
|
|
47
|
+
explorerUrl: 'https://arbiscan.io',
|
|
48
|
+
enabled: false,
|
|
49
|
+
primary: false,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
export function getPrimaryChain() {
|
|
53
|
+
const primary = Object.values(CHAINS).find(c => c.primary);
|
|
54
|
+
return primary ?? CHAINS.solana;
|
|
55
|
+
}
|
|
56
|
+
export function getEnabledChains() {
|
|
57
|
+
return Object.values(CHAINS).filter(c => c.enabled);
|
|
58
|
+
}
|
|
59
|
+
export function getChain(name) {
|
|
60
|
+
return CHAINS[name];
|
|
61
|
+
}
|
|
62
|
+
export function getSupportedChains() {
|
|
63
|
+
return Object.keys(CHAINS);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=ChainConfig.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EnvLoader — loads environment variables from ~/.aiaiai/.env and process.env
|
|
3
|
+
*/
|
|
4
|
+
export declare class EnvLoader {
|
|
5
|
+
private cache;
|
|
6
|
+
private envPath;
|
|
7
|
+
constructor();
|
|
8
|
+
private load;
|
|
9
|
+
get(key: string, defaultValue?: string): string | undefined;
|
|
10
|
+
getRequired(key: string): string;
|
|
11
|
+
has(key: string): boolean;
|
|
12
|
+
reload(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare const env: EnvLoader;
|
|
15
|
+
//# sourceMappingURL=EnvLoader.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EnvLoader — loads environment variables from ~/.aiaiai/.env and process.env
|
|
3
|
+
*/
|
|
4
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
export class EnvLoader {
|
|
8
|
+
cache = {};
|
|
9
|
+
envPath;
|
|
10
|
+
constructor() {
|
|
11
|
+
const home = process.env.AIAIAI_HOME ?? resolve(homedir(), '.aiaiai');
|
|
12
|
+
this.envPath = resolve(home, '.env');
|
|
13
|
+
this.load();
|
|
14
|
+
}
|
|
15
|
+
load() {
|
|
16
|
+
// Load from .env file
|
|
17
|
+
if (existsSync(this.envPath)) {
|
|
18
|
+
const content = readFileSync(this.envPath, 'utf-8');
|
|
19
|
+
for (const line of content.split('\n')) {
|
|
20
|
+
const trimmed = line.trim();
|
|
21
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
22
|
+
continue;
|
|
23
|
+
const eqIdx = trimmed.indexOf('=');
|
|
24
|
+
if (eqIdx === -1)
|
|
25
|
+
continue;
|
|
26
|
+
const key = trimmed.slice(0, eqIdx).trim();
|
|
27
|
+
const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, '');
|
|
28
|
+
if (key)
|
|
29
|
+
this.cache[key] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Process.env overrides file
|
|
33
|
+
for (const key of Object.keys(process.env)) {
|
|
34
|
+
const value = process.env[key];
|
|
35
|
+
if (value !== undefined) {
|
|
36
|
+
this.cache[key] = value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
get(key, defaultValue) {
|
|
41
|
+
return this.cache[key] ?? defaultValue;
|
|
42
|
+
}
|
|
43
|
+
getRequired(key) {
|
|
44
|
+
const value = this.get(key);
|
|
45
|
+
if (!value)
|
|
46
|
+
throw new Error(`Required env var ${key} is not set`);
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
has(key) {
|
|
50
|
+
return this.cache[key] !== undefined;
|
|
51
|
+
}
|
|
52
|
+
reload() {
|
|
53
|
+
this.cache = {};
|
|
54
|
+
this.load();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export const env = new EnvLoader();
|
|
58
|
+
//# sourceMappingURL=EnvLoader.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aiaiaichain — public API
|
|
3
|
+
*
|
|
4
|
+
* Extension files import from here:
|
|
5
|
+
* import { Type } from "aiaiaichain"
|
|
6
|
+
* import type { ExtensionAPI } from "aiaiaichain"
|
|
7
|
+
*/
|
|
8
|
+
export { Type, type Static } from "@sinclair/typebox";
|
|
9
|
+
export type { ExtensionAPI, CommandDef, CommandContext, UIContext, ThemeContext, ToolDef, ToolContent, ToolResult, SkillDef, SessionEvent, SessionContext, } from "./api/ExtensionAPI.js";
|
|
10
|
+
export { text } from "./api/ExtensionAPI.js";
|
|
11
|
+
export { Registry } from "./api/Registry.js";
|
|
12
|
+
export { AgentRunner } from "./runner/AgentRunner.js";
|
|
13
|
+
export { ModelClient, resolveModelConfig } from "./runner/ModelClient.js";
|
|
14
|
+
export { ToolDispatcher } from "./runner/ToolDispatcher.js";
|
|
15
|
+
export { SwarmRouter } from "./runner/SwarmRouter.js";
|
|
16
|
+
export { loadExtension } from "./loader.js";
|
|
17
|
+
export { makeTheme, T, AIAIAI_COLORS } from "./tui/theme.js";
|
|
18
|
+
export { ModelRegistry, modelRegistry, classifyModel } from "./models/ModelRegistry.js";
|
|
19
|
+
export { CostTracker } from "./models/CostTracker.js";
|
|
20
|
+
export type { OpenRouterModel, TieredModel, TieredPool, ModelTier } from "./models/ModelRegistry.js";
|
|
21
|
+
export { fullAnalysis, rsi, macd, ema, sma, bollingerBands, atr, getCandlesTool, getCandlesParams } from "./tools/TechnicalAnalysis.js";
|
|
22
|
+
export { PriceFeed, priceFeed } from "./tools/PriceFeed.js";
|
|
23
|
+
export { NewsFeed, newsFeed, getNewsTool, scoreSentiment } from "./tools/NewsSentiment.js";
|
|
24
|
+
export { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "./tools/MarketSentiment.js";
|
|
25
|
+
export type { OHLCV, AnalysisResult } from "./tools/TechnicalAnalysis.js";
|
|
26
|
+
export type { PriceResult, DexScreenerPair } from "./tools/PriceFeed.js";
|
|
27
|
+
export type { NewsItem, SentimentReport } from "./tools/NewsSentiment.js";
|
|
28
|
+
export { SessionManager } from "./session/SessionManager.js";
|
|
29
|
+
export { MemoryStore, memoryStore } from "./session/MemoryStore.js";
|
|
30
|
+
export { GoalManager, goalManager } from "./session/GoalManager.js";
|
|
31
|
+
export { ContextStore, contextStore } from "./session/ContextStore.js";
|
|
32
|
+
export type { Goal } from "./session/GoalManager.js";
|
|
33
|
+
export type { ContextPressure } from "./session/SessionManager.js";
|
|
34
|
+
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
35
|
+
export type { ScheduledTask } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
export { MCPServer } from "./mcp/server.js";
|
|
37
|
+
export { AgentDir } from "./core/AgentDir.js";
|
|
38
|
+
export { EnvLoader, env } from "./core/EnvLoader.js";
|
|
39
|
+
export { CHAINS, getPrimaryChain, getEnabledChains, getChain, getSupportedChains } from "./core/ChainConfig.js";
|
|
40
|
+
export type { ChainInfo } from "./core/ChainConfig.js";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aiaiaichain — public API
|
|
3
|
+
*
|
|
4
|
+
* Extension files import from here:
|
|
5
|
+
* import { Type } from "aiaiaichain"
|
|
6
|
+
* import type { ExtensionAPI } from "aiaiaichain"
|
|
7
|
+
*/
|
|
8
|
+
// Re-export TypeBox Type builder
|
|
9
|
+
export { Type } from "@sinclair/typebox";
|
|
10
|
+
export { text } from "./api/ExtensionAPI.js";
|
|
11
|
+
export { Registry } from "./api/Registry.js";
|
|
12
|
+
// Runner
|
|
13
|
+
export { AgentRunner } from "./runner/AgentRunner.js";
|
|
14
|
+
export { ModelClient, resolveModelConfig } from "./runner/ModelClient.js";
|
|
15
|
+
export { ToolDispatcher } from "./runner/ToolDispatcher.js";
|
|
16
|
+
export { SwarmRouter } from "./runner/SwarmRouter.js";
|
|
17
|
+
// Loader
|
|
18
|
+
export { loadExtension } from "./loader.js";
|
|
19
|
+
// Theme
|
|
20
|
+
export { makeTheme, T, AIAIAI_COLORS } from "./tui/theme.js";
|
|
21
|
+
// Models
|
|
22
|
+
export { ModelRegistry, modelRegistry, classifyModel } from "./models/ModelRegistry.js";
|
|
23
|
+
export { CostTracker } from "./models/CostTracker.js";
|
|
24
|
+
// Tools
|
|
25
|
+
export { fullAnalysis, rsi, macd, ema, sma, bollingerBands, atr, getCandlesTool, getCandlesParams } from "./tools/TechnicalAnalysis.js";
|
|
26
|
+
export { PriceFeed, priceFeed } from "./tools/PriceFeed.js";
|
|
27
|
+
export { NewsFeed, newsFeed, getNewsTool, scoreSentiment } from "./tools/NewsSentiment.js";
|
|
28
|
+
export { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "./tools/MarketSentiment.js";
|
|
29
|
+
// Session
|
|
30
|
+
export { SessionManager } from "./session/SessionManager.js";
|
|
31
|
+
export { MemoryStore, memoryStore } from "./session/MemoryStore.js";
|
|
32
|
+
export { GoalManager, goalManager } from "./session/GoalManager.js";
|
|
33
|
+
export { ContextStore, contextStore } from "./session/ContextStore.js";
|
|
34
|
+
// Scheduler
|
|
35
|
+
export { AgentScheduler, agentScheduler } from "./scheduler/AgentScheduler.js";
|
|
36
|
+
// MCP
|
|
37
|
+
export { MCPServer } from "./mcp/server.js";
|
|
38
|
+
// Core
|
|
39
|
+
export { AgentDir } from "./core/AgentDir.js";
|
|
40
|
+
export { EnvLoader, env } from "./core/EnvLoader.js";
|
|
41
|
+
export { CHAINS, getPrimaryChain, getEnabledChains, getChain, getSupportedChains } from "./core/ChainConfig.js";
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
package/dist/loader.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loader.ts — loads an extension file and wires it to a Registry.
|
|
3
|
+
*/
|
|
4
|
+
import { Registry } from "./api/Registry.js";
|
|
5
|
+
export interface LoaderOptions {
|
|
6
|
+
onStatusUpdate?: (key: string, value: string) => void;
|
|
7
|
+
onNotify?: (message: string) => void;
|
|
8
|
+
onShowModelSelector?: (query?: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function loadExtension(extensionPath: string, registry: Registry, opts?: LoaderOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=loader.d.ts.map
|
package/dist/loader.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loader.ts — loads an extension file and wires it to a Registry.
|
|
3
|
+
*/
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { resolve, extname } from "node:path";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { makeTheme } from "./tui/theme.js";
|
|
8
|
+
export async function loadExtension(extensionPath, registry, opts = {}) {
|
|
9
|
+
const abs = resolve(extensionPath);
|
|
10
|
+
if (!existsSync(abs))
|
|
11
|
+
throw new Error(`Extension file not found: ${abs}`);
|
|
12
|
+
const theme = makeTheme();
|
|
13
|
+
let _notify = opts.onNotify ?? (() => { });
|
|
14
|
+
let _setStatus = opts.onStatusUpdate ?? (() => { });
|
|
15
|
+
let _showModelSelector = opts.onShowModelSelector ?? (() => { });
|
|
16
|
+
const ui = {
|
|
17
|
+
notify(msg) { _notify(msg); },
|
|
18
|
+
setStatus(key, value) { _setStatus(key, value); },
|
|
19
|
+
setTheme(_name) { },
|
|
20
|
+
setHeader(_factory) { },
|
|
21
|
+
showModelSelector(query) { _showModelSelector(query); },
|
|
22
|
+
theme,
|
|
23
|
+
};
|
|
24
|
+
const api = {
|
|
25
|
+
registerCommand(name, def) { registry.addCommand(name, def); },
|
|
26
|
+
registerTool(def) { registry.addTool(def); },
|
|
27
|
+
registerSkill(def) { registry.addSkill(def); },
|
|
28
|
+
on(event, handler) { registry.addHook(event, handler); },
|
|
29
|
+
setSystemPrompt(prompt) { registry.setSystemPrompt(prompt); },
|
|
30
|
+
ui,
|
|
31
|
+
};
|
|
32
|
+
const ext = extname(abs).toLowerCase();
|
|
33
|
+
let mod;
|
|
34
|
+
if (ext === ".ts") {
|
|
35
|
+
const jsPath = abs.replace(/\.ts$/, ".js");
|
|
36
|
+
if (existsSync(jsPath)) {
|
|
37
|
+
mod = await import(pathToFileURL(jsPath).href);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
try {
|
|
41
|
+
const tsxMod = await import("tsx/esm/api");
|
|
42
|
+
mod = await tsxMod.tsImport(pathToFileURL(abs).href, import.meta.url);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
throw new Error(`Cannot import TypeScript extension "${abs}" in packaged mode.\n` +
|
|
46
|
+
`Fix: compile to .js first or install tsx: npm install -g tsx`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
mod = await import(pathToFileURL(abs).href);
|
|
52
|
+
}
|
|
53
|
+
const fn = mod.default ?? mod;
|
|
54
|
+
if (typeof fn !== "function") {
|
|
55
|
+
throw new Error(`Extension must export a default function. Got: ${typeof fn}`);
|
|
56
|
+
}
|
|
57
|
+
const _origLog = console.log;
|
|
58
|
+
const _origError = console.error;
|
|
59
|
+
const _origWarn = console.warn;
|
|
60
|
+
const _extLog = (...args) => { ui.notify(args.map(a => String(a)).join(" ")); };
|
|
61
|
+
console.log = _extLog;
|
|
62
|
+
console.error = _extLog;
|
|
63
|
+
console.warn = _extLog;
|
|
64
|
+
try {
|
|
65
|
+
await fn(api);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
console.log = _origLog;
|
|
69
|
+
console.error = _origError;
|
|
70
|
+
console.warn = _origWarn;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP entry point — starts the AIAIAI MCP server over stdio.
|
|
3
|
+
*/
|
|
4
|
+
import { MCPServer } from "./server.js";
|
|
5
|
+
const server = new MCPServer();
|
|
6
|
+
server.start().catch((e) => {
|
|
7
|
+
process.stderr.write(`MCP server error: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server — exposes AIAIAI tools via the Model Context Protocol (stdio).
|
|
3
|
+
* Minimal JSON-RPC implementation over stdin/stdout.
|
|
4
|
+
*/
|
|
5
|
+
export declare class MCPServer {
|
|
6
|
+
private tools;
|
|
7
|
+
constructor();
|
|
8
|
+
private registerTools;
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
private handleMessage;
|
|
11
|
+
private respond;
|
|
12
|
+
private respondError;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP server — exposes AIAIAI tools via the Model Context Protocol (stdio).
|
|
3
|
+
* Minimal JSON-RPC implementation over stdin/stdout.
|
|
4
|
+
*/
|
|
5
|
+
import { priceFeed } from "../tools/PriceFeed.js";
|
|
6
|
+
import { getNewsTool } from "../tools/NewsSentiment.js";
|
|
7
|
+
import { getCandlesTool } from "../tools/TechnicalAnalysis.js";
|
|
8
|
+
import { getFearGreedTool, getFundingRatesTool, getBtcMempoolTool, getDefiTvlTool, getSolanaStatsTool, } from "../tools/MarketSentiment.js";
|
|
9
|
+
export class MCPServer {
|
|
10
|
+
tools = [];
|
|
11
|
+
constructor() {
|
|
12
|
+
this.registerTools();
|
|
13
|
+
}
|
|
14
|
+
registerTools() {
|
|
15
|
+
this.tools = [
|
|
16
|
+
{
|
|
17
|
+
name: "get_aiaiai_price",
|
|
18
|
+
description: "Get the current $AIAIAI token price, liquidity, market cap, and volume from DexScreener.",
|
|
19
|
+
inputSchema: { type: "object", properties: {} },
|
|
20
|
+
handler: async () => priceFeed.getAiaiaiPriceTool(),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "get_token_price",
|
|
24
|
+
description: "Get price data for any Solana token by address via DexScreener.",
|
|
25
|
+
inputSchema: { type: "object", properties: { address: { type: "string", description: "Solana token address" } }, required: ["address"] },
|
|
26
|
+
handler: async (args) => priceFeed.getTokenPriceTool("", args),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "get_news",
|
|
30
|
+
description: "Crypto news headlines with sentiment scoring.",
|
|
31
|
+
inputSchema: { type: "object", properties: { limit: { type: "number", description: "Number of items" } } },
|
|
32
|
+
handler: async (args) => getNewsTool("", args),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "get_candles",
|
|
36
|
+
description: "Fetch OHLCV candles from Binance and run technical analysis.",
|
|
37
|
+
inputSchema: { type: "object", properties: { symbol: { type: "string" }, interval: { type: "string" }, limit: { type: "number" } }, required: ["symbol"] },
|
|
38
|
+
handler: async (args) => getCandlesTool("", args),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "get_fear_greed",
|
|
42
|
+
description: "Crypto Fear & Greed Index.",
|
|
43
|
+
inputSchema: { type: "object", properties: {} },
|
|
44
|
+
handler: async () => getFearGreedTool(),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "get_funding_rates",
|
|
48
|
+
description: "Binance perpetual funding rates.",
|
|
49
|
+
inputSchema: { type: "object", properties: { limit: { type: "number" } } },
|
|
50
|
+
handler: async (args) => getFundingRatesTool("", args),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "get_btc_mempool",
|
|
54
|
+
description: "Bitcoin mempool stats and fee rates.",
|
|
55
|
+
inputSchema: { type: "object", properties: {} },
|
|
56
|
+
handler: async () => getBtcMempoolTool(),
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "get_defi_tvl",
|
|
60
|
+
description: "DeFiLlama TVL by chain or all chains.",
|
|
61
|
+
inputSchema: { type: "object", properties: { chain: { type: "string" } } },
|
|
62
|
+
handler: async (args) => getDefiTvlTool("", args),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "get_solana_stats",
|
|
66
|
+
description: "Solana network epoch, slot, and SOL price.",
|
|
67
|
+
inputSchema: { type: "object", properties: {} },
|
|
68
|
+
handler: async () => getSolanaStatsTool(),
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
async start() {
|
|
73
|
+
let buffer = "";
|
|
74
|
+
process.stdin.setEncoding("utf-8");
|
|
75
|
+
process.stdin.on("data", async (chunk) => {
|
|
76
|
+
buffer += chunk;
|
|
77
|
+
const lines = buffer.split("\n");
|
|
78
|
+
buffer = lines.pop() || "";
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
if (!line.trim())
|
|
81
|
+
continue;
|
|
82
|
+
await this.handleMessage(line.trim());
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
process.stderr.write("AIAIAI MCP server started (stdio)\n");
|
|
86
|
+
}
|
|
87
|
+
async handleMessage(raw) {
|
|
88
|
+
let msg;
|
|
89
|
+
try {
|
|
90
|
+
msg = JSON.parse(raw);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const { id, method, params } = msg;
|
|
96
|
+
if (method === "initialize") {
|
|
97
|
+
this.respond(id, {
|
|
98
|
+
protocolVersion: "2024-11-05",
|
|
99
|
+
capabilities: { tools: {} },
|
|
100
|
+
serverInfo: { name: "aiaiai-chain", version: "0.1.0" },
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (method === "tools/list") {
|
|
105
|
+
this.respond(id, {
|
|
106
|
+
tools: this.tools.map(t => ({ name: t.name, description: t.description, inputSchema: t.inputSchema })),
|
|
107
|
+
});
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (method === "tools/call") {
|
|
111
|
+
const tool = this.tools.find(t => t.name === params?.name);
|
|
112
|
+
if (!tool) {
|
|
113
|
+
this.respondError(id, -32602, `Unknown tool: ${params?.name}`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const result = await tool.handler(params.arguments ?? {});
|
|
118
|
+
this.respond(id, { content: result.content });
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
this.respondError(id, -32603, e instanceof Error ? e.message : String(e));
|
|
122
|
+
}
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (method === "ping") {
|
|
126
|
+
this.respond(id, {});
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
respond(id, result) {
|
|
131
|
+
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\n");
|
|
132
|
+
}
|
|
133
|
+
respondError(id, code, message) {
|
|
134
|
+
process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } }) + "\n");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CostTracker — tracks token usage and cost across sessions.
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
5
|
+
import type { ModelRegistry } from "./ModelRegistry.js";
|
|
6
|
+
export interface UsageEntry {
|
|
7
|
+
model: string;
|
|
8
|
+
promptTokens: number;
|
|
9
|
+
completionTokens: number;
|
|
10
|
+
cost: number;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
}
|
|
13
|
+
export interface SessionUsage {
|
|
14
|
+
entries: UsageEntry[];
|
|
15
|
+
totalCost: number;
|
|
16
|
+
totalTokens: number;
|
|
17
|
+
}
|
|
18
|
+
export interface LifetimeUsage {
|
|
19
|
+
sessions: number;
|
|
20
|
+
totalCost: number;
|
|
21
|
+
totalTokens: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class CostTracker {
|
|
24
|
+
private registry;
|
|
25
|
+
private sessionEntry;
|
|
26
|
+
private lifetime;
|
|
27
|
+
private loaded;
|
|
28
|
+
constructor(registry: ModelRegistry);
|
|
29
|
+
track(model: string, promptTokens: number, completionTokens: number): void;
|
|
30
|
+
private estimateCost;
|
|
31
|
+
statusLine(): string;
|
|
32
|
+
saveLifetime(): void;
|
|
33
|
+
private loadLifetime;
|
|
34
|
+
private writeLifetime;
|
|
35
|
+
costReportParams: import("@sinclair/typebox").TObject<{}>;
|
|
36
|
+
costReportTool(): Promise<ToolResult>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=CostTracker.d.ts.map
|