@aiaiaichain/agent 0.1.3 → 0.1.5

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 +2 -2
  2. package/dist/cli.js +274 -26
  3. package/dist/core/ChainConfig.js +1 -1
  4. package/dist/core/SystemMonitor.d.ts +32 -0
  5. package/dist/core/SystemMonitor.js +89 -0
  6. package/dist/index.d.ts +17 -2
  7. package/dist/index.js +18 -1
  8. package/dist/models/ModelRegistry.js +12 -4
  9. package/dist/runner/AgentRunner.d.ts +2 -0
  10. package/dist/runner/AgentRunner.js +18 -1
  11. package/dist/runner/ModelClient.js +109 -48
  12. package/dist/session/SessionManager.d.ts +1 -0
  13. package/dist/session/SessionManager.js +8 -2
  14. package/dist/session/SessionStore.d.ts +45 -0
  15. package/dist/session/SessionStore.js +128 -0
  16. package/dist/tools/CrossTools.d.ts +52 -0
  17. package/dist/tools/CrossTools.js +190 -0
  18. package/dist/tools/MarketSentiment.js +22 -13
  19. package/dist/tools/NewsSentiment.js +9 -3
  20. package/dist/tools/PriceFeed.js +11 -4
  21. package/dist/tools/TechnicalAnalysis.js +2 -1
  22. package/dist/tools/TokenCalendar.d.ts +24 -0
  23. package/dist/tools/TokenCalendar.js +81 -0
  24. package/dist/tools/TokenSecurityScanner.d.ts +22 -0
  25. package/dist/tools/TokenSecurityScanner.js +102 -0
  26. package/dist/tools/TransactionSim.d.ts +17 -0
  27. package/dist/tools/TransactionSim.js +78 -0
  28. package/dist/tui/App.d.ts +4 -3
  29. package/dist/tui/App.js +371 -118
  30. package/dist/tui/REPL.d.ts +2 -1
  31. package/dist/tui/REPL.js +190 -16
  32. package/dist/tui/Sparkline.d.ts +21 -0
  33. package/dist/tui/Sparkline.js +44 -0
  34. package/dist/tui/StatusBar.d.ts +5 -1
  35. package/dist/tui/StatusBar.js +6 -4
  36. package/dist/tui/ThemePresets.d.ts +25 -0
  37. package/dist/tui/ThemePresets.js +117 -0
  38. package/dist/util/clipboard.d.ts +9 -0
  39. package/dist/util/clipboard.js +26 -0
  40. package/dist/util/commandSuggest.d.ts +7 -0
  41. package/dist/util/commandSuggest.js +44 -0
  42. package/dist/util/confirmation.d.ts +6 -0
  43. package/dist/util/confirmation.js +16 -0
  44. package/dist/util/errorHandler.d.ts +3 -0
  45. package/dist/util/errorHandler.js +28 -0
  46. package/dist/util/logger.d.ts +11 -0
  47. package/dist/util/logger.js +43 -0
  48. package/dist/util/processManager.d.ts +5 -0
  49. package/dist/util/processManager.js +39 -0
  50. package/dist/util/resilientFetch.d.ts +21 -0
  51. package/dist/util/resilientFetch.js +94 -0
  52. package/dist/util/responseCache.d.ts +27 -0
  53. package/dist/util/responseCache.js +54 -0
  54. package/dist/util/safeLog.d.ts +4 -5
  55. package/dist/util/safeLog.js +68 -30
  56. package/dist/util/scheduler.d.ts +14 -0
  57. package/dist/util/scheduler.js +75 -0
  58. package/dist/util/webhooks.d.ts +9 -0
  59. package/dist/util/webhooks.js +75 -0
  60. package/dist/wallet/ActionFeed.js +12 -4
  61. package/dist/wallet/AgentWallet.d.ts +2 -0
  62. package/dist/wallet/AgentWallet.js +31 -5
  63. package/dist/wallet/ProfitTracker.d.ts +30 -0
  64. package/dist/wallet/ProfitTracker.js +93 -0
  65. package/docs/COMMANDS.md +40 -9
  66. package/docs/README.md +2 -0
  67. package/package.json +5 -3
  68. package/scripts/postinstall.js +34 -0
@@ -2,6 +2,7 @@
2
2
  * AgentRunner — main agent loop. Handles tool calling, streaming, and message processing.
3
3
  * The AI responds with text or tool calls; we parse, dispatch, and feed results back.
4
4
  */
5
+ import { logger } from "../util/logger.js";
5
6
  import { ToolDispatcher } from "./ToolDispatcher.js";
6
7
  import { ModelClient, resolveModelConfig } from "./ModelClient.js";
7
8
  export class AgentRunner {
@@ -17,6 +18,8 @@ export class AgentRunner {
17
18
  contextStore;
18
19
  abortController = null;
19
20
  _pendingApproval;
21
+ _toolRetries = new Map();
22
+ _maxToolRetries = 2;
20
23
  constructor(registry, session, onEvent, sessionCtx, effectLevel, modelReg, costTracker, goalManager, contextStore) {
21
24
  this.registry = registry;
22
25
  this.session = session;
@@ -53,7 +56,9 @@ export class AgentRunner {
53
56
  try {
54
57
  args = JSON.parse(toolCallMatch[3]);
55
58
  }
56
- catch { /* use empty args */ }
59
+ catch {
60
+ logger.warn('AgentRunner', 'Failed to parse tool call args from stream', { toolCall: toolCallMatch[0].slice(0, 100) });
61
+ }
57
62
  fullResponse = fullResponse.replace(toolCallMatch[0], "").trim();
58
63
  toolCallBuffer = "";
59
64
  if (toolName !== "noop") {
@@ -130,6 +135,18 @@ export class AgentRunner {
130
135
  result: resultText,
131
136
  isError: result.isError ?? false,
132
137
  });
138
+ // Break retry loop: don't feed back if tool has failed too many times
139
+ if (result.isError) {
140
+ const retries = (this._toolRetries.get(toolName) ?? 0) + 1;
141
+ this._toolRetries.set(toolName, retries);
142
+ if (retries > this._maxToolRetries) {
143
+ this._toolRetries.delete(toolName);
144
+ return; // Stop feeding errors — prevent loop
145
+ }
146
+ }
147
+ else {
148
+ this._toolRetries.delete(toolName);
149
+ }
133
150
  // Feed the result back to the model for a follow-up
134
151
  const toolMessages = [
135
152
  ...messages.slice(-5),
@@ -3,6 +3,14 @@
3
3
  * Handles streaming and non-streaming calls.
4
4
  */
5
5
  import { env } from "../core/EnvLoader.js";
6
+ import { logger } from "../util/logger.js";
7
+ import { resilientFetch } from "../util/resilientFetch.js";
8
+ const MAX_RETRIES = 2;
9
+ const RETRY_BACKOFF_MS = 1000;
10
+ const REQUEST_TIMEOUT = 60_000;
11
+ function isRetryable(status) {
12
+ return status === 429 || status >= 500;
13
+ }
6
14
  export function resolveModelConfig(registry) {
7
15
  const apiKey = env.get("OPENROUTER_API_KEY");
8
16
  const defaultModel = env.get("DEFAULT_MODEL");
@@ -24,61 +32,114 @@ export class ModelClient {
24
32
  stream: true,
25
33
  max_tokens: 4096,
26
34
  };
27
- try {
28
- const response = await fetch(`${config.baseUrl}/chat/completions`, {
29
- method: "POST",
30
- headers: {
31
- "Content-Type": "application/json",
32
- Authorization: `Bearer ${config.apiKey}`,
33
- "HTTP-Referer": "https://aiaiaichain.dev",
34
- "X-Title": "AIAIAI Chain Agent",
35
- },
36
- body: JSON.stringify(body),
37
- signal,
38
- });
39
- if (!response.ok) {
40
- const err = await response.text().catch(() => "unknown error");
41
- onEvent({ type: "error", message: `API error ${response.status}: ${err}` });
42
- return;
43
- }
44
- const reader = response.body?.getReader();
45
- if (!reader) {
46
- onEvent({ type: "error", message: "No response body" });
47
- return;
48
- }
49
- const decoder = new TextDecoder();
50
- let buffer = "";
51
- while (true) {
52
- const { done, value } = await reader.read();
53
- if (done)
54
- break;
55
- buffer += decoder.decode(value, { stream: true });
56
- const lines = buffer.split("\n");
57
- buffer = lines.pop() || "";
58
- for (const line of lines) {
59
- const trimmed = line.trim();
60
- if (!trimmed || trimmed === "data: [DONE]")
61
- continue;
62
- if (!trimmed.startsWith("data: "))
35
+ let lastError = "";
36
+ let lastStatus = 0;
37
+ let timer;
38
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
39
+ try {
40
+ if (attempt > 0) {
41
+ const delay = RETRY_BACKOFF_MS * Math.pow(2, attempt - 1);
42
+ logger.info('ModelClient', `Retry attempt ${attempt}/${MAX_RETRIES} after ${delay}ms`);
43
+ await new Promise(r => setTimeout(r, delay));
44
+ }
45
+ const controller = new AbortController();
46
+ timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
47
+ if (signal?.aborted) {
48
+ onEvent({ type: "error", message: "Request aborted" });
49
+ return;
50
+ }
51
+ const combinedSignal = signal ?? controller.signal;
52
+ const response = await resilientFetch(`${config.baseUrl}/chat/completions`, {
53
+ timeout: REQUEST_TIMEOUT,
54
+ retries: 0,
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ Authorization: `Bearer ${config.apiKey}`,
59
+ "HTTP-Referer": "https://aiaiaichain.dev",
60
+ "X-Title": "AIAIAI Chain Agent",
61
+ },
62
+ body: JSON.stringify(body),
63
+ signal: combinedSignal,
64
+ });
65
+ clearTimeout(timer);
66
+ if (!response.ok) {
67
+ const err = await response.text().catch(() => "unknown error");
68
+ lastError = err;
69
+ lastStatus = response.status;
70
+ if (isRetryable(response.status) && attempt < MAX_RETRIES) {
71
+ logger.warn('ModelClient', `Retryable error ${response.status}`, { attempt });
63
72
  continue;
64
- try {
65
- const json = JSON.parse(trimmed.slice(6));
66
- const delta = json.choices?.[0]?.delta?.content;
67
- if (delta)
68
- onEvent({ type: "text_delta", text: delta });
69
73
  }
70
- catch { /* skip malformed lines */ }
74
+ if (response.status === 401) {
75
+ onEvent({ type: "error", message: `API auth failed: OpenRouter key is missing or invalid.\nRun: aiaiai setup\nGet a key: https://openrouter.ai/keys` });
76
+ }
77
+ else {
78
+ onEvent({ type: "error", message: `API error ${response.status}: ${err}` });
79
+ }
80
+ return;
81
+ }
82
+ const reader = response.body?.getReader();
83
+ if (!reader) {
84
+ onEvent({ type: "error", message: "No response body" });
85
+ return;
86
+ }
87
+ const decoder = new TextDecoder();
88
+ let buffer = "";
89
+ while (true) {
90
+ const { done, value } = await reader.read();
91
+ if (done)
92
+ break;
93
+ buffer += decoder.decode(value, { stream: true });
94
+ const lines = buffer.split("\n");
95
+ buffer = lines.pop() || "";
96
+ for (const line of lines) {
97
+ const trimmed = line.trim();
98
+ if (!trimmed || trimmed === "data: [DONE]")
99
+ continue;
100
+ if (!trimmed.startsWith("data: "))
101
+ continue;
102
+ try {
103
+ const json = JSON.parse(trimmed.slice(6));
104
+ const delta = json.choices?.[0]?.delta?.content;
105
+ if (delta)
106
+ onEvent({ type: "text_delta", text: delta });
107
+ }
108
+ catch {
109
+ logger.debug('ModelClient', 'Skipped malformed SSE line', { line: trimmed.slice(0, 100) });
110
+ }
111
+ }
71
112
  }
72
- }
73
- onEvent({ type: "turn_done" });
74
- }
75
- catch (e) {
76
- if (e instanceof Error && e.name === "AbortError") {
77
113
  onEvent({ type: "turn_done" });
114
+ return; // Success — exit retry loop
115
+ }
116
+ catch (e) {
117
+ clearTimeout(timer);
118
+ if (e instanceof Error && e.name === "AbortError") {
119
+ if (signal?.aborted) {
120
+ onEvent({ type: "turn_done" });
121
+ return;
122
+ }
123
+ // Timeout
124
+ lastError = "Request timed out";
125
+ if (attempt < MAX_RETRIES) {
126
+ logger.warn('ModelClient', `Timeout, retrying`, { attempt });
127
+ continue;
128
+ }
129
+ onEvent({ type: "error", message: "Request timed out" });
130
+ return;
131
+ }
132
+ lastError = e instanceof Error ? e.message : String(e);
133
+ if (attempt < MAX_RETRIES) {
134
+ logger.warn('ModelClient', `Error, retrying`, { attempt, error: lastError });
135
+ continue;
136
+ }
137
+ onEvent({ type: "error", message: `ModelClient error (${lastStatus || 'offline'}): ${lastError}` });
78
138
  return;
79
139
  }
80
- onEvent({ type: "error", message: e instanceof Error ? e.message : String(e) });
81
140
  }
141
+ // Exhausted retries
142
+ onEvent({ type: "error", message: `ModelClient failed after ${MAX_RETRIES + 1} attempts: ${lastError}` });
82
143
  }
83
144
  }
84
145
  //# sourceMappingURL=ModelClient.js.map
@@ -10,6 +10,7 @@ export declare class SessionManager {
10
10
  private messages;
11
11
  private systemPrompt;
12
12
  private maxContextTokens;
13
+ private _cachedChars;
13
14
  setSystemPrompt(prompt: string): void;
14
15
  getSystemPrompt(): string;
15
16
  addMessage(role: string, content: string): void;
@@ -5,6 +5,7 @@ export class SessionManager {
5
5
  messages = [];
6
6
  systemPrompt = "";
7
7
  maxContextTokens = 128_000;
8
+ _cachedChars = 0;
8
9
  setSystemPrompt(prompt) {
9
10
  this.systemPrompt = prompt;
10
11
  }
@@ -13,13 +14,18 @@ export class SessionManager {
13
14
  }
14
15
  addMessage(role, content) {
15
16
  this.messages.push({ role, content });
17
+ this._cachedChars += content.length + role.length + 10;
16
18
  }
17
19
  getMessages() {
18
20
  // Estimate: 1 token ≈ 4 chars
19
21
  const maxChars = this.maxContextTokens * 4;
22
+ // Fast path: if total is under limit, return all
23
+ if (this._cachedChars <= maxChars) {
24
+ return [...this.messages];
25
+ }
26
+ // Slow path: walk backwards until we hit the limit
20
27
  let total = 0;
21
28
  const result = [];
22
- // Walk backwards, building up until we hit the limit
23
29
  for (let i = this.messages.length - 1; i >= 0; i--) {
24
30
  const msg = this.messages[i];
25
31
  const size = msg.content.length + msg.role.length + 10;
@@ -31,7 +37,7 @@ export class SessionManager {
31
37
  return result;
32
38
  }
33
39
  getContextPressure() {
34
- const totalChars = this.messages.reduce((sum, m) => sum + m.content.length + m.role.length + 10, 0);
40
+ const totalChars = this._cachedChars || this.messages.reduce((sum, m) => sum + m.content.length + m.role.length + 10, 0);
35
41
  const maxChars = this.maxContextTokens * 4;
36
42
  const pct = Math.min(100, Math.round((totalChars / maxChars) * 100));
37
43
  let level = "green";
@@ -0,0 +1,45 @@
1
+ /**
2
+ * SessionStore — saves/loads conversation sessions.
3
+ * Sessions stored as JSON in ~/.aiaiai/sessions/
4
+ */
5
+ import type { ChatMessage } from '../tui/REPL.js';
6
+ export interface SessionMeta {
7
+ id: string;
8
+ title: string;
9
+ createdAt: number;
10
+ updatedAt: number;
11
+ messageCount: number;
12
+ model: string;
13
+ }
14
+ export interface Session {
15
+ id: string;
16
+ title: string;
17
+ createdAt: number;
18
+ updatedAt: number;
19
+ messages: ChatMessage[];
20
+ model: string;
21
+ chain: string;
22
+ }
23
+ export declare class SessionStore {
24
+ private currentId;
25
+ private autoSaveInterval;
26
+ constructor();
27
+ /** Start auto-saving every 30s */
28
+ startAutoSave(getMessages: () => ChatMessage[]): void;
29
+ stopAutoSave(): void;
30
+ /** Save current session */
31
+ save(messages: ChatMessage[], title?: string): string;
32
+ /** Load a session by ID */
33
+ load(id: string): Session | null;
34
+ /** List all sessions (most recent first) */
35
+ list(): SessionMeta[];
36
+ /** Delete a session */
37
+ delete(id: string): boolean;
38
+ /** Set current session ID (for resuming) */
39
+ setCurrentId(id: string): void;
40
+ getCurrentId(): string;
41
+ /** Generate a title from first user message */
42
+ private generateTitle;
43
+ }
44
+ export declare const sessionStore: SessionStore;
45
+ //# sourceMappingURL=SessionStore.d.ts.map
@@ -0,0 +1,128 @@
1
+ /**
2
+ * SessionStore — saves/loads conversation sessions.
3
+ * Sessions stored as JSON in ~/.aiaiai/sessions/
4
+ */
5
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync } from 'node:fs';
6
+ import { resolve } from 'node:path';
7
+ import { homedir } from 'node:os';
8
+ import { logger } from '../util/logger.js';
9
+ const SESSIONS_DIR = resolve(homedir(), '.aiaiai', 'sessions');
10
+ function ensureDir() {
11
+ if (!existsSync(SESSIONS_DIR))
12
+ mkdirSync(SESSIONS_DIR, { recursive: true });
13
+ }
14
+ function sessionId() {
15
+ return `session-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
16
+ }
17
+ export class SessionStore {
18
+ currentId;
19
+ autoSaveInterval = null;
20
+ constructor() {
21
+ ensureDir();
22
+ this.currentId = sessionId();
23
+ }
24
+ /** Start auto-saving every 30s */
25
+ startAutoSave(getMessages) {
26
+ this.stopAutoSave();
27
+ this.autoSaveInterval = setInterval(() => {
28
+ const msgs = getMessages();
29
+ if (msgs.length > 0)
30
+ this.save(msgs, 'current');
31
+ }, 30_000);
32
+ }
33
+ stopAutoSave() {
34
+ if (this.autoSaveInterval) {
35
+ clearInterval(this.autoSaveInterval);
36
+ this.autoSaveInterval = null;
37
+ }
38
+ }
39
+ /** Save current session */
40
+ save(messages, title) {
41
+ ensureDir();
42
+ const id = this.currentId;
43
+ const existing = this.load(id);
44
+ const session = {
45
+ id,
46
+ title: title || existing?.title || this.generateTitle(messages),
47
+ createdAt: existing?.createdAt || Date.now(),
48
+ updatedAt: Date.now(),
49
+ messages,
50
+ model: process.env.DEFAULT_MODEL || 'unknown',
51
+ chain: 'solana',
52
+ };
53
+ try {
54
+ writeFileSync(resolve(SESSIONS_DIR, `${id}.json`), JSON.stringify(session, null, 2), 'utf-8');
55
+ }
56
+ catch { /* non-fatal */ }
57
+ return id;
58
+ }
59
+ /** Load a session by ID */
60
+ load(id) {
61
+ try {
62
+ const path = resolve(SESSIONS_DIR, `${id}.json`);
63
+ if (!existsSync(path))
64
+ return null;
65
+ return JSON.parse(readFileSync(path, 'utf-8'));
66
+ }
67
+ catch (error) {
68
+ logger.debug('SessionStore', 'Failed to load session', { error: error.message });
69
+ return null;
70
+ }
71
+ }
72
+ /** List all sessions (most recent first) */
73
+ list() {
74
+ ensureDir();
75
+ try {
76
+ const files = readdirSync(SESSIONS_DIR).filter(f => f.endsWith('.json'));
77
+ const sessions = [];
78
+ for (const file of files) {
79
+ try {
80
+ const data = JSON.parse(readFileSync(resolve(SESSIONS_DIR, file), 'utf-8'));
81
+ sessions.push({
82
+ id: data.id,
83
+ title: data.title,
84
+ createdAt: data.createdAt,
85
+ updatedAt: data.updatedAt,
86
+ messageCount: data.messages.length,
87
+ model: data.model,
88
+ });
89
+ }
90
+ catch (error) {
91
+ logger.debug('SessionStore', 'Skipped bad session file', { error: error.message });
92
+ }
93
+ }
94
+ return sessions.sort((a, b) => b.updatedAt - a.updatedAt);
95
+ }
96
+ catch (error) {
97
+ logger.warn('SessionStore', 'Failed to list sessions', { error: error.message });
98
+ return [];
99
+ }
100
+ }
101
+ /** Delete a session */
102
+ delete(id) {
103
+ try {
104
+ unlinkSync(resolve(SESSIONS_DIR, `${id}.json`));
105
+ return true;
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ }
111
+ /** Set current session ID (for resuming) */
112
+ setCurrentId(id) {
113
+ this.currentId = id;
114
+ }
115
+ getCurrentId() {
116
+ return this.currentId;
117
+ }
118
+ /** Generate a title from first user message */
119
+ generateTitle(messages) {
120
+ const firstUser = messages.find(m => m.role === 'user');
121
+ if (!firstUser)
122
+ return 'New Session';
123
+ const text = firstUser.content.trim();
124
+ return text.length > 40 ? text.slice(0, 37) + '…' : text;
125
+ }
126
+ }
127
+ export const sessionStore = new SessionStore();
128
+ //# sourceMappingURL=SessionStore.js.map
@@ -0,0 +1,52 @@
1
+ /**
2
+ * CrossTools — automation tools that combine multiple data sources.
3
+ * Watch tokens, compare, portfolio tracking, price alerts.
4
+ */
5
+ import type { ToolResult } from "../api/ExtensionAPI.js";
6
+ interface PriceAlert {
7
+ id: string;
8
+ token: string;
9
+ type: 'above' | 'below';
10
+ price: number;
11
+ active: boolean;
12
+ createdAt: number;
13
+ triggeredAt?: number;
14
+ }
15
+ export declare function addAlert(token: string, type: 'above' | 'below', price: number): PriceAlert;
16
+ export declare function checkAlerts(currentPrice: number, token: string): PriceAlert[];
17
+ export declare function getActiveAlerts(): PriceAlert[];
18
+ export declare function addToWatchList(tokenAddress: string): void;
19
+ export declare function removeFromWatchList(tokenAddress: string): void;
20
+ export declare function getWatchList(): string[];
21
+ export declare const watchTokenParams: import("@sinclair/typebox").TObject<{
22
+ address: import("@sinclair/typebox").TString;
23
+ }>;
24
+ export declare const removeWatchParams: import("@sinclair/typebox").TObject<{
25
+ address: import("@sinclair/typebox").TString;
26
+ }>;
27
+ export declare const listWatchParams: import("@sinclair/typebox").TObject<{}>;
28
+ export declare const addAlertParams: import("@sinclair/typebox").TObject<{
29
+ token: import("@sinclair/typebox").TString;
30
+ type: import("@sinclair/typebox").TString;
31
+ price: import("@sinclair/typebox").TNumber;
32
+ }>;
33
+ export declare const checkAlertsParams: import("@sinclair/typebox").TObject<{}>;
34
+ export declare const compareTokensParams: import("@sinclair/typebox").TObject<{
35
+ address1: import("@sinclair/typebox").TString;
36
+ address2: import("@sinclair/typebox").TString;
37
+ }>;
38
+ export declare function watchTokenTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
39
+ export declare function removeWatchTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
40
+ export declare function listWatchTool(): Promise<ToolResult>;
41
+ export declare function addAlertTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
42
+ export declare function checkAlertsTool(): Promise<ToolResult>;
43
+ export declare function compareTokensTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
44
+ export declare const portfolioParams: import("@sinclair/typebox").TObject<{
45
+ address: import("@sinclair/typebox").TString;
46
+ }>;
47
+ export declare function portfolioTool(_id: string, params: Record<string, unknown>): Promise<ToolResult>;
48
+ export declare const COLD_WALLET = "A11iZoqEt6hU7HyggqC67ee4AtYmaJjwKCvJLerJRV2J";
49
+ export declare const ACTION_WALLET = "BygDYM1ZXLQNC1HXLhnd1rHZ7E5XjioqT3vPjJFfjnU2";
50
+ export declare const DEPOSIT_WALLET = "FBMDYpG9WXKy4SgxuATQdB2sCyzHsJWPrEr45z3TgL2e";
51
+ export {};
52
+ //# sourceMappingURL=CrossTools.d.ts.map