@exagent/agent 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-6LDEQK7Q.mjs +986 -0
- package/dist/chunk-DRHO56RO.mjs +986 -0
- package/dist/chunk-GO5SB4LS.mjs +986 -0
- package/dist/chunk-JHXVT7PE.mjs +1090 -0
- package/dist/chunk-JMDWVGDG.mjs +986 -0
- package/dist/chunk-JS7RJORF.mjs +1548 -0
- package/dist/chunk-NTGO2FIV.mjs +1121 -0
- package/dist/chunk-XCTKJAV6.mjs +1061 -0
- package/dist/chunk-ZJ7JS4V6.mjs +986 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1828 -0
- package/dist/cli.mjs +322 -0
- package/dist/index.d.mts +673 -0
- package/dist/index.d.ts +673 -0
- package/dist/index.js +1607 -0
- package/dist/index.mjs +54 -0
- package/package.json +52 -0
- package/templates/.env.template +55 -0
- package/templates/docker-compose.yml +60 -0
- package/templates/strategy.template.ts +153 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentConfigSchema,
|
|
3
|
+
AgentRuntime,
|
|
4
|
+
AnthropicAdapter,
|
|
5
|
+
BaseLLMAdapter,
|
|
6
|
+
LLMConfigSchema,
|
|
7
|
+
LLMProviderSchema,
|
|
8
|
+
MarketDataService,
|
|
9
|
+
OllamaAdapter,
|
|
10
|
+
OpenAIAdapter,
|
|
11
|
+
RiskManager,
|
|
12
|
+
RiskUniverseSchema,
|
|
13
|
+
STRATEGY_TEMPLATES,
|
|
14
|
+
TradeExecutor,
|
|
15
|
+
TradingConfigSchema,
|
|
16
|
+
VaultConfigSchema,
|
|
17
|
+
VaultManager,
|
|
18
|
+
VaultPolicySchema,
|
|
19
|
+
createLLMAdapter,
|
|
20
|
+
createSampleConfig,
|
|
21
|
+
getAllStrategyTemplates,
|
|
22
|
+
getStrategyTemplate,
|
|
23
|
+
loadConfig,
|
|
24
|
+
loadStrategy,
|
|
25
|
+
validateConfig,
|
|
26
|
+
validateStrategy
|
|
27
|
+
} from "./chunk-JS7RJORF.mjs";
|
|
28
|
+
export {
|
|
29
|
+
AgentConfigSchema,
|
|
30
|
+
AgentRuntime,
|
|
31
|
+
AnthropicAdapter,
|
|
32
|
+
BaseLLMAdapter,
|
|
33
|
+
LLMConfigSchema,
|
|
34
|
+
LLMProviderSchema,
|
|
35
|
+
MarketDataService,
|
|
36
|
+
OllamaAdapter,
|
|
37
|
+
OpenAIAdapter,
|
|
38
|
+
RiskManager,
|
|
39
|
+
RiskUniverseSchema,
|
|
40
|
+
STRATEGY_TEMPLATES,
|
|
41
|
+
TradeExecutor,
|
|
42
|
+
TradingConfigSchema,
|
|
43
|
+
VaultConfigSchema,
|
|
44
|
+
VaultManager,
|
|
45
|
+
VaultPolicySchema,
|
|
46
|
+
createLLMAdapter,
|
|
47
|
+
createSampleConfig,
|
|
48
|
+
getAllStrategyTemplates,
|
|
49
|
+
getStrategyTemplate,
|
|
50
|
+
loadConfig,
|
|
51
|
+
loadStrategy,
|
|
52
|
+
validateConfig,
|
|
53
|
+
validateStrategy
|
|
54
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@exagent/agent",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Autonomous trading agent runtime for Exagent",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"exagent": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"templates"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts",
|
|
24
|
+
"dev": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --watch",
|
|
25
|
+
"start": "node dist/cli.js",
|
|
26
|
+
"test": "vitest",
|
|
27
|
+
"lint": "eslint src/",
|
|
28
|
+
"clean": "rm -rf dist"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@exagent/sdk": "workspace:*",
|
|
32
|
+
"chalk": "^5.3.0",
|
|
33
|
+
"commander": "^12.0.0",
|
|
34
|
+
"dotenv": "^16.4.0",
|
|
35
|
+
"openai": "^4.0.0",
|
|
36
|
+
"tsx": "^4.7.0",
|
|
37
|
+
"viem": "^2.21.0",
|
|
38
|
+
"zod": "^3.22.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^20.0.0",
|
|
42
|
+
"tsup": "^8.0.0",
|
|
43
|
+
"typescript": "^5.3.0",
|
|
44
|
+
"vitest": "^2.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"viem": "^2.0.0"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=18.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Exagent Agent Configuration
|
|
2
|
+
# WARNING: Never commit this file to version control!
|
|
3
|
+
# Keep your private key and API keys secret.
|
|
4
|
+
|
|
5
|
+
# ============================================
|
|
6
|
+
# REQUIRED: Your wallet private key
|
|
7
|
+
# ============================================
|
|
8
|
+
# This wallet will be used to:
|
|
9
|
+
# 1. Link to your agent identity on-chain
|
|
10
|
+
# 2. Execute trades through the ExagentRouter
|
|
11
|
+
# 3. Pay gas fees for transactions
|
|
12
|
+
#
|
|
13
|
+
# Format: 64 hex characters starting with 0x
|
|
14
|
+
# Example: 0x1234567890abcdef...
|
|
15
|
+
EXAGENT_PRIVATE_KEY=
|
|
16
|
+
|
|
17
|
+
# ============================================
|
|
18
|
+
# REQUIRED: Network (mainnet or testnet)
|
|
19
|
+
# ============================================
|
|
20
|
+
# Use 'testnet' for Base Sepolia (recommended for testing)
|
|
21
|
+
# Use 'mainnet' for Base mainnet (real money!)
|
|
22
|
+
EXAGENT_NETWORK=testnet
|
|
23
|
+
|
|
24
|
+
# ============================================
|
|
25
|
+
# LLM API Keys (choose one based on your config)
|
|
26
|
+
# ============================================
|
|
27
|
+
|
|
28
|
+
# OpenAI API Key
|
|
29
|
+
# Get yours at: https://platform.openai.com/api-keys
|
|
30
|
+
# OPENAI_API_KEY=sk-...
|
|
31
|
+
|
|
32
|
+
# Anthropic API Key
|
|
33
|
+
# Get yours at: https://console.anthropic.com/settings/keys
|
|
34
|
+
# ANTHROPIC_API_KEY=sk-ant-...
|
|
35
|
+
|
|
36
|
+
# Ollama (Local LLM - no API key needed)
|
|
37
|
+
# Just install Ollama: https://ollama.com/download
|
|
38
|
+
# Then run: ollama serve
|
|
39
|
+
# And pull your model: ollama pull mistral
|
|
40
|
+
# EXAGENT_LLM_URL=http://localhost:11434
|
|
41
|
+
|
|
42
|
+
# ============================================
|
|
43
|
+
# Optional: Override LLM model
|
|
44
|
+
# ============================================
|
|
45
|
+
# EXAGENT_LLM_MODEL=gpt-4-turbo-preview
|
|
46
|
+
|
|
47
|
+
# ============================================
|
|
48
|
+
# Optional: Custom config path
|
|
49
|
+
# ============================================
|
|
50
|
+
# EXAGENT_CONFIG=./agent-config.json
|
|
51
|
+
|
|
52
|
+
# ============================================
|
|
53
|
+
# Optional: Custom strategy path
|
|
54
|
+
# ============================================
|
|
55
|
+
# EXAGENT_STRATEGY=./strategy.ts
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Docker Compose for Exagent Trading Agent
|
|
2
|
+
#
|
|
3
|
+
# Usage:
|
|
4
|
+
# 1. Copy .env.template to .env and fill in your secrets
|
|
5
|
+
# 2. Run: docker-compose up -d
|
|
6
|
+
# 3. View logs: docker-compose logs -f
|
|
7
|
+
# 4. Stop: docker-compose down
|
|
8
|
+
|
|
9
|
+
version: '3.8'
|
|
10
|
+
|
|
11
|
+
services:
|
|
12
|
+
agent:
|
|
13
|
+
image: node:20-alpine
|
|
14
|
+
container_name: exagent-${AGENT_NAME:-agent}
|
|
15
|
+
working_dir: /app
|
|
16
|
+
volumes:
|
|
17
|
+
- .:/app
|
|
18
|
+
- agent_node_modules:/app/node_modules
|
|
19
|
+
environment:
|
|
20
|
+
- NODE_ENV=production
|
|
21
|
+
- EXAGENT_PRIVATE_KEY=${EXAGENT_PRIVATE_KEY}
|
|
22
|
+
- EXAGENT_NETWORK=${EXAGENT_NETWORK:-testnet}
|
|
23
|
+
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
|
24
|
+
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
|
|
25
|
+
- EXAGENT_LLM_URL=${EXAGENT_LLM_URL:-}
|
|
26
|
+
command: npm start
|
|
27
|
+
restart: unless-stopped
|
|
28
|
+
healthcheck:
|
|
29
|
+
test: ["CMD", "node", "-e", "console.log('healthy')"]
|
|
30
|
+
interval: 30s
|
|
31
|
+
timeout: 10s
|
|
32
|
+
retries: 3
|
|
33
|
+
logging:
|
|
34
|
+
driver: "json-file"
|
|
35
|
+
options:
|
|
36
|
+
max-size: "10m"
|
|
37
|
+
max-file: "3"
|
|
38
|
+
|
|
39
|
+
# Optional: Local Ollama for on-device LLM
|
|
40
|
+
# Uncomment if using local LLM
|
|
41
|
+
#
|
|
42
|
+
# ollama:
|
|
43
|
+
# image: ollama/ollama
|
|
44
|
+
# container_name: exagent-ollama
|
|
45
|
+
# volumes:
|
|
46
|
+
# - ollama_models:/root/.ollama
|
|
47
|
+
# ports:
|
|
48
|
+
# - "11434:11434"
|
|
49
|
+
# deploy:
|
|
50
|
+
# resources:
|
|
51
|
+
# reservations:
|
|
52
|
+
# devices:
|
|
53
|
+
# - driver: nvidia
|
|
54
|
+
# count: all
|
|
55
|
+
# capabilities: [gpu]
|
|
56
|
+
# restart: unless-stopped
|
|
57
|
+
|
|
58
|
+
volumes:
|
|
59
|
+
agent_node_modules:
|
|
60
|
+
# ollama_models: # Uncomment if using Ollama
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Trading Strategy
|
|
3
|
+
*
|
|
4
|
+
* This is YOUR strategy file - customize it to your needs.
|
|
5
|
+
* Your prompts and logic are your competitive advantage.
|
|
6
|
+
* We don't store or know what's in this file.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT WARNINGS:
|
|
9
|
+
* - LLMs can hallucinate or make errors. Always validate outputs.
|
|
10
|
+
* - Test thoroughly on testnet before using real funds.
|
|
11
|
+
* - Agents may not behave exactly as expected based on your prompts.
|
|
12
|
+
* - You are fully responsible for your trading decisions.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type {
|
|
16
|
+
StrategyFunction,
|
|
17
|
+
MarketData,
|
|
18
|
+
TradeSignal,
|
|
19
|
+
LLMAdapter,
|
|
20
|
+
AgentConfig,
|
|
21
|
+
} from '@exagent/agent';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Your custom system prompt
|
|
25
|
+
*
|
|
26
|
+
* This is the secret sauce of your trading agent.
|
|
27
|
+
* Customize this to define how your agent thinks and trades.
|
|
28
|
+
*/
|
|
29
|
+
const SYSTEM_PROMPT = `You are an AI trading assistant analyzing cryptocurrency markets.
|
|
30
|
+
|
|
31
|
+
Your role is to analyze market data and provide trading recommendations.
|
|
32
|
+
|
|
33
|
+
IMPORTANT CONSTRAINTS:
|
|
34
|
+
- Only recommend trades when you have high confidence
|
|
35
|
+
- Consider risk/reward ratios
|
|
36
|
+
- Never exceed position size limits
|
|
37
|
+
- Be conservative - it's okay to recommend "hold"
|
|
38
|
+
|
|
39
|
+
When analyzing market data, consider:
|
|
40
|
+
1. Price trends and momentum
|
|
41
|
+
2. Current portfolio allocation
|
|
42
|
+
3. Risk management
|
|
43
|
+
|
|
44
|
+
Respond with JSON in this exact format:
|
|
45
|
+
{
|
|
46
|
+
"analysis": "Brief market analysis (1-2 sentences)",
|
|
47
|
+
"signals": [
|
|
48
|
+
{
|
|
49
|
+
"action": "buy" | "sell" | "hold",
|
|
50
|
+
"tokenIn": "0x...",
|
|
51
|
+
"tokenOut": "0x...",
|
|
52
|
+
"percentage": 0-100,
|
|
53
|
+
"confidence": 0-1,
|
|
54
|
+
"reasoning": "Why this trade"
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
If you're unsure or market conditions are unclear, respond with:
|
|
60
|
+
{
|
|
61
|
+
"analysis": "Market conditions unclear",
|
|
62
|
+
"signals": [{ "action": "hold", "confidence": 1.0, "reasoning": "Waiting for clearer signals" }]
|
|
63
|
+
}`;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generate trading signals
|
|
67
|
+
*
|
|
68
|
+
* This function is called on each trading cycle.
|
|
69
|
+
* It receives market data, has access to the LLM, and returns trade signals.
|
|
70
|
+
*
|
|
71
|
+
* @param marketData - Current prices, balances, and portfolio value
|
|
72
|
+
* @param llm - LLM adapter for analysis
|
|
73
|
+
* @param config - Agent configuration
|
|
74
|
+
* @returns Array of trade signals
|
|
75
|
+
*/
|
|
76
|
+
export const generateSignals: StrategyFunction = async (
|
|
77
|
+
marketData: MarketData,
|
|
78
|
+
llm: LLMAdapter,
|
|
79
|
+
config: AgentConfig
|
|
80
|
+
): Promise<TradeSignal[]> => {
|
|
81
|
+
// Format market data for the LLM
|
|
82
|
+
const userMessage = JSON.stringify({
|
|
83
|
+
timestamp: new Date(marketData.timestamp).toISOString(),
|
|
84
|
+
prices: marketData.prices,
|
|
85
|
+
portfolioValue: `$${marketData.portfolioValue.toFixed(2)}`,
|
|
86
|
+
balances: formatBalances(marketData.balances),
|
|
87
|
+
config: {
|
|
88
|
+
riskUniverse: config.riskUniverse,
|
|
89
|
+
maxPositionSize: `${config.trading.maxPositionSizeBps / 100}%`,
|
|
90
|
+
timeHorizon: config.trading.timeHorizon,
|
|
91
|
+
},
|
|
92
|
+
}, null, 2);
|
|
93
|
+
|
|
94
|
+
// Call the LLM
|
|
95
|
+
const response = await llm.chat([
|
|
96
|
+
{ role: 'system', content: SYSTEM_PROMPT },
|
|
97
|
+
{ role: 'user', content: userMessage },
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
// Parse and validate the response
|
|
101
|
+
try {
|
|
102
|
+
const parsed = JSON.parse(response.content);
|
|
103
|
+
|
|
104
|
+
if (!parsed.signals || !Array.isArray(parsed.signals)) {
|
|
105
|
+
console.warn('LLM response missing signals array');
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Log analysis
|
|
110
|
+
if (parsed.analysis) {
|
|
111
|
+
console.log(`Analysis: ${parsed.analysis}`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Convert to TradeSignal format
|
|
115
|
+
return parsed.signals
|
|
116
|
+
.filter((s: any) => s.action !== 'hold') // Filter out hold signals
|
|
117
|
+
.map((s: any) => ({
|
|
118
|
+
action: s.action as 'buy' | 'sell',
|
|
119
|
+
tokenIn: s.tokenIn || '',
|
|
120
|
+
tokenOut: s.tokenOut || '',
|
|
121
|
+
amountIn: calculateAmount(s.percentage, marketData),
|
|
122
|
+
confidence: s.confidence || 0.5,
|
|
123
|
+
reasoning: s.reasoning,
|
|
124
|
+
}));
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('Failed to parse LLM response:', error);
|
|
127
|
+
console.error('Raw response:', response.content);
|
|
128
|
+
return []; // Safe fallback: no trades
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Format balances for LLM display
|
|
134
|
+
*/
|
|
135
|
+
function formatBalances(balances: Record<string, bigint>): Record<string, string> {
|
|
136
|
+
const formatted: Record<string, string> = {};
|
|
137
|
+
for (const [address, balance] of Object.entries(balances)) {
|
|
138
|
+
// Assume 18 decimals for simplicity
|
|
139
|
+
const amount = Number(balance) / 1e18;
|
|
140
|
+
formatted[address] = amount.toFixed(6);
|
|
141
|
+
}
|
|
142
|
+
return formatted;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Calculate trade amount from percentage
|
|
147
|
+
*/
|
|
148
|
+
function calculateAmount(percentage: number, marketData: MarketData): bigint {
|
|
149
|
+
// This is a simplified calculation
|
|
150
|
+
// In production, you'd want to calculate based on actual token balances
|
|
151
|
+
const value = (marketData.portfolioValue * percentage) / 100;
|
|
152
|
+
return BigInt(Math.floor(value * 1e18));
|
|
153
|
+
}
|