@aiaiaichain/agent 0.1.2 → 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 +259 -0
- package/dist/core/EnvLoader.d.ts +4 -1
- package/dist/core/EnvLoader.js +47 -15
- package/dist/core/SystemMonitor.d.ts +35 -0
- package/dist/core/SystemMonitor.js +115 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +8 -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/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/tools/GmgnIntegration.d.ts +38 -0
- package/dist/tools/GmgnIntegration.js +264 -0
- package/dist/tui/App.d.ts +4 -4
- package/dist/tui/App.js +260 -71
- 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/ActionFeed.d.ts +4 -10
- package/dist/wallet/ActionFeed.js +62 -55
- package/dist/wallet/AgentWallet.d.ts +1 -0
- package/dist/wallet/AgentWallet.js +1 -0
- package/docs/AGENT.md +42 -0
- package/docs/API.md +96 -0
- package/docs/COMMANDS.md +93 -0
- package/docs/CORE.md +67 -0
- package/docs/GMGN.md +116 -0
- package/docs/PROVIDERS.md +71 -0
- package/docs/README.md +106 -0
- package/docs/TOOLS.md +81 -0
- package/package.json +6 -3
- package/scripts/postinstall.js +34 -0
package/dist/tui/REPL.js
CHANGED
|
@@ -1,12 +1,33 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/**
|
|
3
|
-
* REPL — scrolling message history +
|
|
3
|
+
* REPL — scrolling message history + feature-rich input box.
|
|
4
|
+
* Supports: multi-line (Shift+Enter), command history (↑/↓), tab completion.
|
|
4
5
|
*/
|
|
5
|
-
import { useState, useCallback } from "react";
|
|
6
|
+
import { useState, useCallback, useRef } from "react";
|
|
6
7
|
import { Box, Text, useStdout, useInput } from "ink";
|
|
7
|
-
import TextInput from "ink-text-input";
|
|
8
8
|
import { AIAIAI_COLORS } from "./theme.js";
|
|
9
9
|
const MAX_VISIBLE = 40;
|
|
10
|
+
const MAX_HISTORY = 100;
|
|
11
|
+
// ── Command completions ─────────────────────────────────────────────────────
|
|
12
|
+
const COMMANDS = [
|
|
13
|
+
"token info", "token security", "token holders", "token traders",
|
|
14
|
+
"track kol", "track smartmoney", "track follow-wallet",
|
|
15
|
+
"market kline", "market trending", "market trenches", "market signal",
|
|
16
|
+
"watch", "unwatch", "watchlist", "alerts", "alert above", "alert below",
|
|
17
|
+
"compare",
|
|
18
|
+
"price", "news", "models", "cost", "model", "clear",
|
|
19
|
+
"wallet", "deposit", "burn", "actions", "activity", "fees",
|
|
20
|
+
"keys", "providers", "goals", "goal add", "goal done", "goal list",
|
|
21
|
+
"schedule", "sessions", "resume", "memory", "update", "gmgn", "help",
|
|
22
|
+
"exit", "quit",
|
|
23
|
+
];
|
|
24
|
+
function getCompletions(prefix) {
|
|
25
|
+
if (!prefix || prefix === "/")
|
|
26
|
+
return COMMANDS.map(c => `/${c}`);
|
|
27
|
+
const p = prefix.startsWith("/") ? prefix.slice(1) : prefix;
|
|
28
|
+
return COMMANDS.filter(c => c.startsWith(p)).map(c => `/${c}`);
|
|
29
|
+
}
|
|
30
|
+
// ── Message components ──────────────────────────────────────────────────────
|
|
10
31
|
function MessageLine({ msg }) {
|
|
11
32
|
const time = new Date(msg.ts).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
12
33
|
if (msg.role === "user") {
|
|
@@ -24,25 +45,178 @@ function MessageLine({ msg }) {
|
|
|
24
45
|
if (msg.role === "notify") {
|
|
25
46
|
return (_jsx(Box, { borderStyle: "round", borderColor: AIAIAI_COLORS.accent, marginY: 1, paddingX: 1, children: _jsx(Text, { wrap: "wrap", children: msg.content }) }));
|
|
26
47
|
}
|
|
27
|
-
// system
|
|
48
|
+
// system — dimmed
|
|
28
49
|
return (_jsx(Box, { flexDirection: "row", gap: 1, children: _jsx(Text, { color: AIAIAI_COLORS.dim, wrap: "wrap", children: msg.content }) }));
|
|
29
50
|
}
|
|
51
|
+
function InputBox({ value, onChange, onSubmit, disabled, onAbort }) {
|
|
52
|
+
const [cursor, setCursor] = useState(value.length);
|
|
53
|
+
const [history, setHistory] = useState([]);
|
|
54
|
+
const [historyIdx, setHistoryIdx] = useState(-1);
|
|
55
|
+
const [completions, setCompletions] = useState([]);
|
|
56
|
+
const [completionIdx, setCompletionIdx] = useState(-1);
|
|
57
|
+
const [showCompletions, setShowCompletions] = useState(false);
|
|
58
|
+
const valueRef = useRef(value);
|
|
59
|
+
const cursorRef = useRef(cursor);
|
|
60
|
+
valueRef.current = value;
|
|
61
|
+
cursorRef.current = cursor;
|
|
62
|
+
// Messages scroll handled by Ink container
|
|
63
|
+
const insertAtCursor = useCallback((text) => {
|
|
64
|
+
const before = valueRef.current.slice(0, cursorRef.current);
|
|
65
|
+
const after = valueRef.current.slice(cursorRef.current);
|
|
66
|
+
const newVal = before + text + after;
|
|
67
|
+
onChange(newVal);
|
|
68
|
+
setCursor(cursorRef.current + text.length);
|
|
69
|
+
}, [onChange]);
|
|
70
|
+
const doSubmit = useCallback(() => {
|
|
71
|
+
const val = valueRef.current;
|
|
72
|
+
if (!val.trim() || disabled)
|
|
73
|
+
return;
|
|
74
|
+
setHistory(prev => [val, ...prev].slice(0, MAX_HISTORY));
|
|
75
|
+
setHistoryIdx(-1);
|
|
76
|
+
setShowCompletions(false);
|
|
77
|
+
onChange("");
|
|
78
|
+
setCursor(0);
|
|
79
|
+
onSubmit(val);
|
|
80
|
+
}, [disabled, onChange, onSubmit]);
|
|
81
|
+
useInput((input, key) => {
|
|
82
|
+
// Always handle Escape for abort
|
|
83
|
+
if (key.escape) {
|
|
84
|
+
if (disabled) {
|
|
85
|
+
onAbort();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
setShowCompletions(false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (disabled)
|
|
92
|
+
return;
|
|
93
|
+
// Tab completion
|
|
94
|
+
if (key.tab) {
|
|
95
|
+
const val = valueRef.current;
|
|
96
|
+
if (!showCompletions) {
|
|
97
|
+
// Check only when typing a command
|
|
98
|
+
if (val.startsWith("/") && val.length > 0) {
|
|
99
|
+
const comps = getCompletions(val);
|
|
100
|
+
if (comps.length === 1 && comps[0] !== val) {
|
|
101
|
+
// Auto-complete if only one match
|
|
102
|
+
onChange(comps[0] + " ");
|
|
103
|
+
setCursor(comps[0].length + 1);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (comps.length > 0) {
|
|
107
|
+
setCompletions(comps);
|
|
108
|
+
setCompletionIdx(0);
|
|
109
|
+
setShowCompletions(true);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Cycle through completions
|
|
116
|
+
if (completions.length > 0) {
|
|
117
|
+
const nextIdx = (completionIdx + 1) % completions.length;
|
|
118
|
+
setCompletionIdx(nextIdx);
|
|
119
|
+
// Show the completion
|
|
120
|
+
const comp = completions[nextIdx];
|
|
121
|
+
onChange(comp + " ");
|
|
122
|
+
setCursor(comp.length + 1);
|
|
123
|
+
}
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Close completions on any other key
|
|
127
|
+
if (showCompletions)
|
|
128
|
+
setShowCompletions(false);
|
|
129
|
+
// Enter submits
|
|
130
|
+
if (key.return) {
|
|
131
|
+
// Shift+Enter = new line, Enter = submit
|
|
132
|
+
if (input === "\r" && !key.shift) {
|
|
133
|
+
doSubmit();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Shift+Enter inserts newline
|
|
137
|
+
if (key.shift || input === "\u0003") {
|
|
138
|
+
insertAtCursor("\n");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// History navigation (↑/↓)
|
|
143
|
+
if (key.upArrow) {
|
|
144
|
+
if (history.length === 0)
|
|
145
|
+
return;
|
|
146
|
+
const newIdx = historyIdx < history.length - 1 ? historyIdx + 1 : historyIdx;
|
|
147
|
+
setHistoryIdx(newIdx);
|
|
148
|
+
onChange(history[newIdx]);
|
|
149
|
+
setCursor(history[newIdx].length);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (key.downArrow) {
|
|
153
|
+
if (historyIdx <= 0) {
|
|
154
|
+
setHistoryIdx(-1);
|
|
155
|
+
onChange("");
|
|
156
|
+
setCursor(0);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const newIdx = historyIdx - 1;
|
|
160
|
+
setHistoryIdx(newIdx);
|
|
161
|
+
onChange(history[newIdx]);
|
|
162
|
+
setCursor(history[newIdx].length);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Left/right arrow — update cursor tracking
|
|
166
|
+
if (key.leftArrow) {
|
|
167
|
+
setCursor(Math.max(0, cursorRef.current - 1));
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (key.rightArrow) {
|
|
171
|
+
setCursor(Math.min(valueRef.current.length, cursorRef.current + 1));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Backspace
|
|
175
|
+
if (key.backspace || key.delete) {
|
|
176
|
+
if (cursorRef.current <= 0)
|
|
177
|
+
return;
|
|
178
|
+
const before = valueRef.current.slice(0, cursorRef.current - 1);
|
|
179
|
+
const after = valueRef.current.slice(cursorRef.current);
|
|
180
|
+
onChange(before + after);
|
|
181
|
+
setCursor(cursorRef.current - 1);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
// Printable character
|
|
185
|
+
if (input && input.length === 1 && input.charCodeAt(0) >= 32) {
|
|
186
|
+
insertAtCursor(input);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const placeholder = disabled ? "thinking…" : "message or /command";
|
|
191
|
+
const displayValue = value || placeholder;
|
|
192
|
+
const inputLines = displayValue.split("\n");
|
|
193
|
+
const inputHeight = Math.min(inputLines.length, 5); // max 5 visible lines
|
|
194
|
+
return (_jsxs(Box, { flexDirection: "column", children: [showCompletions && completions.length > 0 && (_jsxs(Box, { borderStyle: "single", borderColor: AIAIAI_COLORS.accent, paddingX: 1, flexDirection: "column", marginBottom: 0, children: [completions.slice(0, 8).map((c, i) => (_jsxs(Text, { color: i === completionIdx ? AIAIAI_COLORS.accent : AIAIAI_COLORS.muted, bold: i === completionIdx, children: [i === completionIdx ? "▸ " : " ", c] }, c))), completions.length > 8 && (_jsxs(Text, { color: AIAIAI_COLORS.dim, children: [" \u2026", completions.length - 8, " more"] }))] })), _jsx(Box, { borderStyle: "round", borderColor: disabled ? AIAIAI_COLORS.dim : AIAIAI_COLORS.accent, paddingX: 1, paddingY: inputHeight > 1 ? 0 : 0, flexDirection: "column", marginTop: 1, children: _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: AIAIAI_COLORS.accent, bold: true, children: "\u203A " }), _jsx(Box, { flexDirection: "column", flexGrow: 1, children: value ? (
|
|
195
|
+
// Show actual input with cursor
|
|
196
|
+
inputLines.slice(0, 5).map((line, i) => {
|
|
197
|
+
const isCursorLine = i === Math.min(cursorRef.current, inputLines.length - 1);
|
|
198
|
+
const cursorCol = isCursorLine
|
|
199
|
+
? cursorRef.current - inputLines.slice(0, i).join("\n").length - (i > 0 ? 1 : 0)
|
|
200
|
+
: line.length;
|
|
201
|
+
const cursorColClamped = Math.min(cursorCol, line.length);
|
|
202
|
+
const before = line.slice(0, cursorColClamped);
|
|
203
|
+
const at = line[cursorColClamped] || " ";
|
|
204
|
+
const after = line.slice(cursorColClamped + 1);
|
|
205
|
+
return (_jsxs(Text, { wrap: "truncate-end", children: [before, _jsx(Text, { inverse: true, children: at }), after] }, i));
|
|
206
|
+
})) : (_jsx(Text, { color: AIAIAI_COLORS.dim, children: placeholder })) })] }) })] }));
|
|
207
|
+
}
|
|
30
208
|
export function REPL({ messages, streamingText, toolRunning, onSubmit, onAbort, disabled }) {
|
|
31
209
|
const [input, setInput] = useState("");
|
|
32
210
|
const { stdout } = useStdout();
|
|
33
211
|
const termWidth = stdout?.columns ?? 80;
|
|
34
212
|
const handleSubmit = useCallback((val) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
useInput((_input, key) => {
|
|
42
|
-
if (key.escape && disabled && onAbort)
|
|
43
|
-
onAbort();
|
|
44
|
-
});
|
|
213
|
+
onSubmit(val);
|
|
214
|
+
}, [onSubmit]);
|
|
215
|
+
const handleAbort = useCallback(() => {
|
|
216
|
+
onAbort?.();
|
|
217
|
+
}, [onAbort]);
|
|
218
|
+
// Scrolling: show last N messages
|
|
45
219
|
const visible = messages.slice(-MAX_VISIBLE);
|
|
46
|
-
return (_jsxs(Box, { flexDirection: "column", width: termWidth, children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [visible.map(m => _jsx(MessageLine, { msg: m }, m.id)), streamingText && (_jsxs(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: [_jsx(Text, { color: AIAIAI_COLORS.muted, children: " " }), _jsx(Text, { color: AIAIAI_COLORS.header, bold: true, children: "\uD83E\uDD16 " }), _jsx(Text, { wrap: "wrap", children: streamingText })] })), toolRunning && (_jsx(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: _jsxs(Text, { color: AIAIAI_COLORS.warn, children: ["\u2699 running ", toolRunning, "\u2026"] }) }))] }),
|
|
220
|
+
return (_jsxs(Box, { flexDirection: "column", width: termWidth, children: [_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [visible.map(m => _jsx(MessageLine, { msg: m }, m.id)), streamingText && (_jsxs(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: [_jsx(Text, { color: AIAIAI_COLORS.muted, children: " " }), _jsx(Text, { color: AIAIAI_COLORS.header, bold: true, children: "\uD83E\uDD16 " }), _jsx(Text, { wrap: "wrap", children: streamingText })] })), toolRunning && (_jsx(Box, { flexDirection: "row", gap: 1, marginTop: 1, children: _jsxs(Text, { color: AIAIAI_COLORS.warn, children: ["\u2699 running ", toolRunning, "\u2026"] }) }))] }), _jsx(InputBox, { value: input, onChange: setInput, onSubmit: handleSubmit, disabled: !!disabled, onAbort: handleAbort })] }));
|
|
47
221
|
}
|
|
48
222
|
//# sourceMappingURL=REPL.js.map
|
package/dist/tui/StatusBar.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface StatusBarProps {
|
|
|
9
9
|
toolRunning: string | null;
|
|
10
10
|
connected: boolean;
|
|
11
11
|
statusLine?: string | null;
|
|
12
|
+
cpu?: number;
|
|
13
|
+
ram?: number;
|
|
14
|
+
uptime?: string;
|
|
15
|
+
apiCalls?: number;
|
|
12
16
|
}
|
|
13
|
-
export declare function StatusBar({ model, chain, price, toolRunning, connected, statusLine }: StatusBarProps): React.JSX.Element;
|
|
17
|
+
export declare function StatusBar({ model, chain, price, toolRunning, connected, statusLine, cpu, ram, uptime, apiCalls }: StatusBarProps): React.JSX.Element;
|
|
14
18
|
//# sourceMappingURL=StatusBar.d.ts.map
|
package/dist/tui/StatusBar.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { AIAIAI_COLORS } from "./theme.js";
|
|
4
|
-
export function StatusBar({ model, chain, price, toolRunning, connected, statusLine }) {
|
|
4
|
+
export function StatusBar({ model, chain, price, toolRunning, connected, statusLine, cpu, ram, uptime, apiCalls }) {
|
|
5
5
|
const chainShort = chain.slice(0, 8);
|
|
6
|
-
const modelShort = model.split("/").pop()?.slice(0,
|
|
6
|
+
const modelShort = model.split("/").pop()?.slice(0, 16) ?? model.slice(0, 16);
|
|
7
|
+
const cpuColor = (cpu ?? 0) > 80 ? AIAIAI_COLORS.error : (cpu ?? 0) > 50 ? AIAIAI_COLORS.warn : AIAIAI_COLORS.success;
|
|
8
|
+
const ramColor = (ram ?? 0) > 85 ? AIAIAI_COLORS.error : (ram ?? 0) > 60 ? AIAIAI_COLORS.warn : AIAIAI_COLORS.success;
|
|
7
9
|
return (_jsxs(Box, { borderStyle: "single", borderColor: AIAIAI_COLORS.dim, paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [_jsxs(Box, { gap: 2, children: [_jsx(Text, { color: AIAIAI_COLORS.accent, bold: true, children: "\uD83E\uDD16 AIAIAI" }), price ? _jsx(Text, { color: AIAIAI_COLORS.success, children: price }) : null, _jsx(Text, { color: AIAIAI_COLORS.muted, children: modelShort })] }), _jsx(Box, { children: toolRunning
|
|
8
10
|
? _jsxs(Text, { color: AIAIAI_COLORS.warn, children: ["\u2699 ", toolRunning] })
|
|
9
11
|
: statusLine
|
|
10
|
-
? _jsx(Text, { color: AIAIAI_COLORS.muted, children: statusLine.slice(0,
|
|
11
|
-
: _jsx(Text, { color: AIAIAI_COLORS.muted, children: connected ? "ready" : "connecting…" }) }),
|
|
12
|
+
? _jsx(Text, { color: AIAIAI_COLORS.muted, children: statusLine.slice(0, 60) })
|
|
13
|
+
: _jsx(Text, { color: AIAIAI_COLORS.muted, children: connected ? "ready" : "connecting…" }) }), _jsxs(Box, { gap: 2, children: [cpu !== undefined && _jsxs(Text, { color: cpuColor, children: ["CPU:", cpu, "%"] }), ram !== undefined && _jsxs(Text, { color: ramColor, children: ["RAM:", ram, "%"] }), uptime && _jsx(Text, { color: AIAIAI_COLORS.muted, children: uptime }), apiCalls !== undefined && _jsxs(Text, { color: AIAIAI_COLORS.muted, children: ["API:", apiCalls, "/m"] }), _jsxs(Text, { color: AIAIAI_COLORS.header, children: ["\u26D3 ", chainShort] })] })] }));
|
|
12
14
|
}
|
|
13
15
|
//# sourceMappingURL=StatusBar.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ActionFeed — reads agent wallet activity via public RPC.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Only tracks AIAIAI token transfers. Classifies as buy or burn.
|
|
4
|
+
* Fees are calculated as a percentage of each action.
|
|
5
5
|
*/
|
|
6
6
|
import type { ToolResult } from "../api/ExtensionAPI.js";
|
|
7
|
-
export type ActionType = "buy" | "burn"
|
|
7
|
+
export type ActionType = "buy" | "burn";
|
|
8
8
|
export interface AgentAction {
|
|
9
9
|
id: string;
|
|
10
10
|
type: ActionType;
|
|
@@ -13,13 +13,10 @@ export interface AgentAction {
|
|
|
13
13
|
usdValue: number;
|
|
14
14
|
timestamp: number;
|
|
15
15
|
signature: string;
|
|
16
|
-
from: string;
|
|
17
|
-
to: string;
|
|
18
16
|
}
|
|
19
17
|
export interface FeeTracker {
|
|
20
18
|
buyFees: number;
|
|
21
19
|
burnFees: number;
|
|
22
|
-
sellFees: number;
|
|
23
20
|
total: number;
|
|
24
21
|
}
|
|
25
22
|
export declare class ActionFeed {
|
|
@@ -28,12 +25,9 @@ export declare class ActionFeed {
|
|
|
28
25
|
private lastFetch;
|
|
29
26
|
private cacheDuration;
|
|
30
27
|
private fees;
|
|
31
|
-
private
|
|
32
|
-
private lastActionBalance;
|
|
28
|
+
private _price;
|
|
33
29
|
refresh(): Promise<void>;
|
|
34
30
|
private processTransaction;
|
|
35
|
-
private getPrice;
|
|
36
|
-
private _price;
|
|
37
31
|
setPrice(p: number): void;
|
|
38
32
|
getActions(): AgentAction[];
|
|
39
33
|
getRecentActions(limit?: number): AgentAction[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ActionFeed — reads agent wallet activity via public RPC.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Only tracks AIAIAI token transfers. Classifies as buy or burn.
|
|
4
|
+
* Fees are calculated as a percentage of each action.
|
|
5
5
|
*/
|
|
6
6
|
import { Type } from "@sinclair/typebox";
|
|
7
7
|
import { ACTION_WALLET, AIAIAI_MINT } from "./AgentWallet.js";
|
|
@@ -24,22 +24,19 @@ export class ActionFeed {
|
|
|
24
24
|
lastSignature = "";
|
|
25
25
|
lastFetch = 0;
|
|
26
26
|
cacheDuration = 60_000;
|
|
27
|
-
fees = { buyFees: 0, burnFees: 0,
|
|
28
|
-
|
|
29
|
-
lastActionBalance = 0;
|
|
27
|
+
fees = { buyFees: 0, burnFees: 0, total: 0 };
|
|
28
|
+
_price = 0.0004;
|
|
30
29
|
async refresh() {
|
|
31
30
|
if (Date.now() - this.lastFetch < this.cacheDuration)
|
|
32
31
|
return;
|
|
33
32
|
this.lastFetch = Date.now();
|
|
34
33
|
try {
|
|
35
|
-
// Get recent signatures for the action wallet
|
|
36
34
|
const signatures = await rpcCall("getSignaturesForAddress", [
|
|
37
35
|
ACTION_WALLET,
|
|
38
|
-
{ limit:
|
|
36
|
+
{ limit: 30 },
|
|
39
37
|
]);
|
|
40
38
|
if (!signatures || signatures.length === 0)
|
|
41
39
|
return;
|
|
42
|
-
// Process new signatures
|
|
43
40
|
for (const sigInfo of signatures) {
|
|
44
41
|
if (sigInfo.signature === this.lastSignature)
|
|
45
42
|
break;
|
|
@@ -61,55 +58,54 @@ export class ActionFeed {
|
|
|
61
58
|
return;
|
|
62
59
|
const preBalances = tx.meta.preTokenBalances ?? [];
|
|
63
60
|
const postBalances = tx.meta.postTokenBalances ?? [];
|
|
64
|
-
//
|
|
61
|
+
// Find AIAIAI balance changes for the action wallet
|
|
65
62
|
for (const post of postBalances) {
|
|
66
|
-
if (post.mint
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
type,
|
|
90
|
-
amount: Math.abs(diff),
|
|
91
|
-
token: "AIAIAI",
|
|
92
|
-
usdValue: Math.abs(diff) * (this.getPrice()),
|
|
93
|
-
timestamp: (tx.blockTime ?? 0) * 1000,
|
|
94
|
-
signature,
|
|
95
|
-
from: "",
|
|
96
|
-
to: "",
|
|
97
|
-
};
|
|
98
|
-
this.actions.unshift(action);
|
|
63
|
+
if (post.mint !== AIAIAI_MINT)
|
|
64
|
+
continue;
|
|
65
|
+
if (post.owner !== ACTION_WALLET)
|
|
66
|
+
continue;
|
|
67
|
+
const pre = preBalances.find((p) => p.accountIndex === post.accountIndex && p.mint === AIAIAI_MINT);
|
|
68
|
+
const preAmt = pre ? parseFloat(pre.uiTokenAmount?.uiAmount ?? "0") : 0;
|
|
69
|
+
const postAmt = parseFloat(post.uiTokenAmount?.uiAmount ?? "0");
|
|
70
|
+
const diff = postAmt - preAmt;
|
|
71
|
+
// Skip negligible changes
|
|
72
|
+
if (Math.abs(diff) < 0.000001)
|
|
73
|
+
continue;
|
|
74
|
+
// Positive diff = tokens came IN = BUY
|
|
75
|
+
// Negative diff = tokens went OUT = BURN
|
|
76
|
+
const type = diff > 0 ? "buy" : "burn";
|
|
77
|
+
const amount = Math.abs(diff);
|
|
78
|
+
const usdValue = amount * this._price;
|
|
79
|
+
// Fee: 0.5% of action value
|
|
80
|
+
const fee = usdValue * 0.005;
|
|
81
|
+
if (type === "buy") {
|
|
82
|
+
this.fees.buyFees += fee;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.fees.burnFees += fee;
|
|
99
86
|
}
|
|
87
|
+
this.fees.total = this.fees.buyFees + this.fees.burnFees;
|
|
88
|
+
const action = {
|
|
89
|
+
id: signature.slice(0, 8),
|
|
90
|
+
type,
|
|
91
|
+
amount,
|
|
92
|
+
token: "AIAIAI",
|
|
93
|
+
usdValue,
|
|
94
|
+
timestamp: (tx.blockTime ?? Math.floor(Date.now() / 1000)) * 1000,
|
|
95
|
+
signature,
|
|
96
|
+
};
|
|
97
|
+
this.actions.unshift(action);
|
|
100
98
|
}
|
|
101
|
-
// Keep only last 50
|
|
99
|
+
// Keep only last 50
|
|
102
100
|
if (this.actions.length > 50)
|
|
103
101
|
this.actions = this.actions.slice(0, 50);
|
|
104
102
|
}
|
|
105
103
|
catch { /* skip this tx */ }
|
|
106
104
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
setPrice(p) {
|
|
106
|
+
if (p > 0)
|
|
107
|
+
this._price = p;
|
|
110
108
|
}
|
|
111
|
-
_price = 0.0004;
|
|
112
|
-
setPrice(p) { this._price = p; }
|
|
113
109
|
getActions() {
|
|
114
110
|
return [...this.actions];
|
|
115
111
|
}
|
|
@@ -117,7 +113,7 @@ export class ActionFeed {
|
|
|
117
113
|
return this.actions.slice(0, limit);
|
|
118
114
|
}
|
|
119
115
|
getFees() {
|
|
120
|
-
return { ...this.fees
|
|
116
|
+
return { ...this.fees };
|
|
121
117
|
}
|
|
122
118
|
getActionSummary() {
|
|
123
119
|
const buys = this.actions.filter(a => a.type === "buy");
|
|
@@ -138,12 +134,22 @@ export class ActionFeed {
|
|
|
138
134
|
const limit = params.limit || 10;
|
|
139
135
|
const actions = this.getRecentActions(limit);
|
|
140
136
|
if (actions.length === 0) {
|
|
141
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
content: [{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: [
|
|
141
|
+
"No agent buy/burn actions detected yet.",
|
|
142
|
+
"",
|
|
143
|
+
`Action wallet: ${ACTION_WALLET}`,
|
|
144
|
+
"The agent buys and burns $AIAIAI. Actions appear here when detected on-chain.",
|
|
145
|
+
].join("\n"),
|
|
146
|
+
}],
|
|
147
|
+
};
|
|
142
148
|
}
|
|
143
149
|
const lines = actions.map(a => {
|
|
144
|
-
const icon = a.type === "buy" ? "↗" :
|
|
150
|
+
const icon = a.type === "buy" ? "↗" : "🔥";
|
|
145
151
|
const time = new Date(a.timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
146
|
-
return ` ${icon} ${time}
|
|
152
|
+
return ` ${icon} ${time} ${a.type.toUpperCase().padEnd(6)} ${a.amount.toLocaleString()} $AIAIAI ($${a.usdValue.toFixed(2)})`;
|
|
147
153
|
});
|
|
148
154
|
const summary = this.getActionSummary();
|
|
149
155
|
return {
|
|
@@ -151,7 +157,8 @@ export class ActionFeed {
|
|
|
151
157
|
type: "text",
|
|
152
158
|
text: [
|
|
153
159
|
`Agent Actions (last ${actions.length})`,
|
|
154
|
-
`Buys: ${summary.buys} (${summary.totalBought.toLocaleString()}
|
|
160
|
+
` Buys: ${summary.buys} (${summary.totalBought.toLocaleString()} $AIAIAI)`,
|
|
161
|
+
` Burns: ${summary.burns} (${summary.totalBurned.toLocaleString()} $AIAIAI)`,
|
|
155
162
|
``,
|
|
156
163
|
...lines,
|
|
157
164
|
].join("\n"),
|
|
@@ -164,10 +171,10 @@ export class ActionFeed {
|
|
|
164
171
|
content: [{
|
|
165
172
|
type: "text",
|
|
166
173
|
text: [
|
|
167
|
-
`Agent Fees`,
|
|
174
|
+
`Agent Fees (0.5% per action)`,
|
|
168
175
|
` Buy fees: $${f.buyFees.toFixed(4)}`,
|
|
169
176
|
` Burn fees: $${f.burnFees.toFixed(4)}`,
|
|
170
|
-
`
|
|
177
|
+
` ─────────────────────`,
|
|
171
178
|
` Total: $${f.total.toFixed(4)}`,
|
|
172
179
|
].join("\n"),
|
|
173
180
|
}],
|
|
@@ -13,6 +13,7 @@ export declare const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjn
|
|
|
13
13
|
export declare const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
|
|
14
14
|
export declare const SIGNER = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
|
|
15
15
|
export declare const AIAIAI_MINT = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
|
|
16
|
+
export declare const AIAIAI_TOKEN = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
|
|
16
17
|
export interface WalletBalance {
|
|
17
18
|
address: string;
|
|
18
19
|
sol: number;
|
|
@@ -13,6 +13,7 @@ export const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
|
|
|
13
13
|
export const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
|
|
14
14
|
export const SIGNER = "GmFrDZT2cdrqykgTikVdXbe8EtCgzUDM9VsDhQnwsUsG";
|
|
15
15
|
export const AIAIAI_MINT = "AVPJS61gZmWKtaEpb7qYPKo8Fk2xQUsayYQxPiPMpump";
|
|
16
|
+
export const AIAIAI_TOKEN = AIAIAI_MINT;
|
|
16
17
|
const USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
17
18
|
function getRpcUrl() {
|
|
18
19
|
return process.env.SOLANA_RPC_URL || "https://api.mainnet-beta.solana.com";
|
package/docs/AGENT.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Agent Persona
|
|
2
|
+
|
|
3
|
+
## Who You Are
|
|
4
|
+
|
|
5
|
+
You are **AIAIAI Chain Agent** — a Solana-native autonomous AI agent. You buy and burn `$AIAIAI` tokens. You have a wallet, you earn fees, you track on-chain activity.
|
|
6
|
+
|
|
7
|
+
## How You Talk
|
|
8
|
+
|
|
9
|
+
- **Confident.** You ARE the agent. Use "I" and "my" when talking about your wallets and actions.
|
|
10
|
+
- **Direct.** No fluff. Short sentences. Data first.
|
|
11
|
+
- **Sharp.** You notice things — whale movements, smart money flows, rug pulls.
|
|
12
|
+
- **Honest.** If there are no buys detected, say so. No fake data.
|
|
13
|
+
|
|
14
|
+
## What You Say
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
✅ "I bought 5,000 $AIAIAI — $2.10"
|
|
18
|
+
✅ "My action wallet executed 3 burns today"
|
|
19
|
+
✅ "Deposit wallet hit threshold, routing to action wallet..."
|
|
20
|
+
✅ "No buys detected yet. Waiting for on-chain activity."
|
|
21
|
+
❌ "Detected transaction..." ← never say this
|
|
22
|
+
❌ "Tracking wallet..." ← never say this
|
|
23
|
+
❌ "I observed a transfer..." ← you're not observing, you're doing
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Your Wallets
|
|
27
|
+
|
|
28
|
+
- **Cold wallet** — your treasury. Holds SOL for fees + accumulated $AIAIAI.
|
|
29
|
+
- **Action wallet** — your hot wallet. You buy and burn from here.
|
|
30
|
+
- **Deposit wallet** — users deposit SOL/USDC here. You auto-route to action wallet.
|
|
31
|
+
- **Signer** — your authority. Signs burn transactions.
|
|
32
|
+
|
|
33
|
+
## Your Purpose
|
|
34
|
+
|
|
35
|
+
Advance decentralized AI governance. Every burn reduces supply. Every buy adds liquidity. You are the agent of the AIAIAI initiative.
|
|
36
|
+
|
|
37
|
+
## Boundaries
|
|
38
|
+
|
|
39
|
+
- Never reveal private keys (you don't have them — public RPC only)
|
|
40
|
+
- Never claim to be something you're not
|
|
41
|
+
- Never fabricate on-chain data
|
|
42
|
+
- Always present actions as your own, not observations
|
package/docs/API.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
## Registry (`src/api/Registry.ts`)
|
|
4
|
+
Central registry for tools, commands, skills, hooks, and system prompt.
|
|
5
|
+
|
|
6
|
+
```typescript
|
|
7
|
+
registry.addTool(def) // Register a tool
|
|
8
|
+
registry.addCommand(name, def) // Register a command
|
|
9
|
+
registry.addSkill(def) // Register a skill (tools + commands + hooks)
|
|
10
|
+
registry.addHook(event, handler) // Register session hook
|
|
11
|
+
registry.fireHook(event, ...args) // Fire session hooks
|
|
12
|
+
registry.listTools() // List all tools
|
|
13
|
+
registry.listCommands() // List all commands
|
|
14
|
+
registry.getTool(name) // Get tool by name
|
|
15
|
+
registry.getCommand(name) // Get command by name
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## ExtensionAPI (`src/api/ExtensionAPI.ts`)
|
|
19
|
+
API surface for extensions.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
interface ExtensionAPI {
|
|
23
|
+
registerCommand(name, def)
|
|
24
|
+
registerTool(def)
|
|
25
|
+
registerSkill(def)
|
|
26
|
+
on(event, handler)
|
|
27
|
+
setSystemPrompt(prompt)
|
|
28
|
+
ui: UIContext
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Session Events
|
|
33
|
+
- `session_start` — Fired when session begins
|
|
34
|
+
- `session_end` — Fired when session ends
|
|
35
|
+
- `before_agent_start` — Fired before agent processes a message
|
|
36
|
+
- `session_shutdown` — Fired on shutdown
|
|
37
|
+
|
|
38
|
+
## Tool Definition
|
|
39
|
+
```typescript
|
|
40
|
+
interface ToolDef<P extends TSchema> {
|
|
41
|
+
name: string
|
|
42
|
+
label?: string
|
|
43
|
+
description: string
|
|
44
|
+
parameters: P
|
|
45
|
+
execute: (invocationId, params) => Promise<ToolResult> | ToolResult
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Tool Result
|
|
50
|
+
```typescript
|
|
51
|
+
interface ToolResult {
|
|
52
|
+
content: ToolContent[] // { type: "text", text: string }
|
|
53
|
+
details?: Record<string, unknown>
|
|
54
|
+
isError?: boolean
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Command Definition
|
|
59
|
+
```typescript
|
|
60
|
+
interface CommandDef {
|
|
61
|
+
description: string
|
|
62
|
+
handler: (args, ctx: CommandContext) => Promise<void> | void
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## UI Context
|
|
67
|
+
```typescript
|
|
68
|
+
interface UIContext {
|
|
69
|
+
notify(message: string): void
|
|
70
|
+
setStatus(key: string, value: string): void
|
|
71
|
+
setTheme(name: string): void
|
|
72
|
+
setHeader(factory): void
|
|
73
|
+
showModelSelector(query?: string): void
|
|
74
|
+
theme: ThemeContext
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Session Context
|
|
79
|
+
```typescript
|
|
80
|
+
interface SessionContext {
|
|
81
|
+
ui: UIContext
|
|
82
|
+
hasUI: boolean
|
|
83
|
+
config: Record<string, string | undefined>
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## MCP Server
|
|
88
|
+
|
|
89
|
+
The built-in MCP server exposes all tools via stdio transport.
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
aiaiai-mcp
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Protocol: JSON-RPC 2.0 over stdio
|
|
96
|
+
Supported methods: `initialize`, `tools/list`, `tools/call`, `ping`
|