@quantish/agent 0.1.22 → 0.1.23
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 +246 -162
- package/dist/index.js +85 -133
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,116 +1,105 @@
|
|
|
1
|
-
# @quantish/
|
|
1
|
+
# @quantish/agent
|
|
2
2
|
|
|
3
|
-
AI-powered
|
|
3
|
+
AI-powered coding & trading agent for Polymarket. Build trading bots, analyze markets, and execute trades using natural language.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- ✅ **Free wallet creation** - No MATIC needed to set up
|
|
15
|
-
- ✅ **Free trading** - Polymarket covers gas fees on all transactions
|
|
16
|
-
- ✅ **Simplified signing** - Our server handles the complex signature formats
|
|
17
|
-
|
|
18
|
-
To make this work reliably, the Quantish Signing Server:
|
|
19
|
-
1. **Handles wallet creation** - Your wallet is created and managed through our server
|
|
20
|
-
2. **Signs transactions** - Orders are signed using Polymarket's required format
|
|
21
|
-
3. **Relays to Polymarket** - Transactions go through Polymarket's official relayer
|
|
22
|
-
4. **Bypasses geo-restrictions** - Our server is hosted in a compatible region
|
|
23
|
-
|
|
24
|
-
### What This Means for You
|
|
25
|
-
|
|
26
|
-
- **Your funds are secure** - Only you can authorize transactions via your API key
|
|
27
|
-
- **Wallets are non-custodial** - You can export your private key anytime with `export_private_key`
|
|
28
|
-
- **Trading is free** - No gas fees, ever
|
|
29
|
-
- **It just works** - No VPN or complex setup needed
|
|
30
|
-
|
|
31
|
-
> 🔒 **Security Note**: Your private keys are stored encrypted. You can export them and migrate to a self-hosted solution in the future if needed.
|
|
7
|
+
- **🤖 Multi-Provider AI** - Use Anthropic Claude or 100+ OpenRouter models (GLM-4.7, MiniMax, DeepSeek, etc.)
|
|
8
|
+
- **💹 Live Trading** - Place orders, manage positions, check balances on Polymarket
|
|
9
|
+
- **🔧 Full Coding Tools** - Read/write files, run commands, git operations
|
|
10
|
+
- **🌐 Web Search** - Search the web with Exa AI or DuckDuckGo fallback
|
|
11
|
+
- **💾 Session Persistence** - Save and resume conversations across sessions
|
|
12
|
+
- **⚡ Queued Input** - Type while the agent is working, queue messages
|
|
13
|
+
- **📊 Cost Tracking** - Real-time token usage and cost display
|
|
32
14
|
|
|
33
15
|
## Installation
|
|
34
16
|
|
|
35
17
|
```bash
|
|
36
|
-
npm install -g @quantish/
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
Or run directly with npx:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npx @quantish/cli
|
|
18
|
+
npm install -g @quantish/agent
|
|
43
19
|
```
|
|
44
20
|
|
|
45
21
|
## Quick Start
|
|
46
22
|
|
|
47
|
-
### 1. Initialize
|
|
48
|
-
|
|
49
|
-
Set up your API keys:
|
|
50
|
-
|
|
51
23
|
```bash
|
|
24
|
+
# First-time setup
|
|
52
25
|
quantish init
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
You'll need:
|
|
56
|
-
- **Anthropic API Key** - Get one at https://console.anthropic.com/
|
|
57
|
-
- **Quantish API Key** - Created automatically during setup
|
|
58
|
-
|
|
59
|
-
### 2. Start Building
|
|
60
26
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```bash
|
|
27
|
+
# Start interactive chat
|
|
64
28
|
quantish
|
|
65
29
|
```
|
|
66
30
|
|
|
67
|
-
|
|
31
|
+
## How It Works
|
|
68
32
|
|
|
69
|
-
|
|
70
|
-
You: Create a trading bot that monitors my positions and sells when profit > 20%
|
|
71
|
-
Assistant: I'll create that for you. Let me first check your current positions...
|
|
72
|
-
[Calling get_positions...]
|
|
73
|
-
[Writing bot.ts...]
|
|
33
|
+
The agent connects to two MCP (Model Context Protocol) servers:
|
|
74
34
|
|
|
75
|
-
|
|
76
|
-
|
|
35
|
+
1. **Discovery MCP** (Public) - Market search, trending markets, market details
|
|
36
|
+
2. **Trading MCP** (Your API Key) - Wallet, orders, positions, trades
|
|
77
37
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
38
|
+
Your wallet is created and managed through our signing server, which:
|
|
39
|
+
- ✅ Handles gasless transactions (Polymarket covers fees)
|
|
40
|
+
- ✅ Signs orders using Polymarket's required format
|
|
41
|
+
- ✅ Works globally (no geo-restrictions)
|
|
42
|
+
- 🔒 Non-custodial - export your private key anytime
|
|
81
43
|
|
|
82
|
-
|
|
44
|
+
## Interactive Commands
|
|
83
45
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
46
|
+
### Chat Commands
|
|
47
|
+
|
|
48
|
+
| Command | Description |
|
|
49
|
+
|---------|-------------|
|
|
50
|
+
| `/help` | Show all commands |
|
|
51
|
+
| `/clear` | Clear conversation history |
|
|
52
|
+
| `/compact` | Summarize conversation to save tokens |
|
|
53
|
+
| `/model <name>` | Switch model (opus, sonnet, haiku, glm, minimax, etc.) |
|
|
54
|
+
| `/provider <name>` | Switch LLM provider (anthropic, openrouter) |
|
|
55
|
+
| `/cost` | Show session cost breakdown |
|
|
56
|
+
| `/tools` | List available tools |
|
|
57
|
+
| `/config` | Show configuration info |
|
|
87
58
|
|
|
88
|
-
|
|
59
|
+
### Session Commands
|
|
89
60
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
61
|
+
| Command | Description |
|
|
62
|
+
|---------|-------------|
|
|
63
|
+
| `/save [name]` | Save current session |
|
|
64
|
+
| `/resume` | Resume last session |
|
|
65
|
+
| `/sessions` | List all saved sessions |
|
|
66
|
+
| `/load <id>` | Load a session by ID |
|
|
67
|
+
| `/forget` | Delete all saved sessions |
|
|
93
68
|
|
|
94
|
-
|
|
69
|
+
### Process Commands
|
|
95
70
|
|
|
96
71
|
| Command | Description |
|
|
97
72
|
|---------|-------------|
|
|
98
|
-
| `
|
|
99
|
-
|
|
|
100
|
-
| `
|
|
101
|
-
|
|
102
|
-
|
|
73
|
+
| `/processes` | List running background processes |
|
|
74
|
+
| `/stop <id>` | Stop a background process |
|
|
75
|
+
| `/stopall` | Stop all background processes |
|
|
76
|
+
|
|
77
|
+
### Keyboard Shortcuts
|
|
78
|
+
|
|
79
|
+
| Key | Action |
|
|
80
|
+
|-----|--------|
|
|
81
|
+
| `Enter` | Send message (or queue if agent is working) |
|
|
82
|
+
| `Esc` | Interrupt current generation |
|
|
83
|
+
| `Ctrl+C` | Exit CLI |
|
|
103
84
|
|
|
104
|
-
## Options
|
|
85
|
+
## CLI Options
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
quantish # Interactive mode
|
|
89
|
+
quantish init # First-time setup wizard
|
|
90
|
+
quantish config # View configuration
|
|
91
|
+
quantish config --export # Export as .env format
|
|
92
|
+
quantish tools # List all available tools
|
|
93
|
+
quantish -p "message" # One-shot mode
|
|
94
|
+
quantish --version # Show version
|
|
95
|
+
```
|
|
105
96
|
|
|
106
97
|
| Option | Description |
|
|
107
98
|
|--------|-------------|
|
|
108
99
|
| `-p, --prompt <message>` | Run a single prompt |
|
|
109
|
-
| `-v, --verbose` | Show tool calls |
|
|
100
|
+
| `-v, --verbose` | Show detailed tool calls |
|
|
110
101
|
| `--no-mcp` | Disable trading tools |
|
|
111
102
|
| `--no-local` | Disable coding tools |
|
|
112
|
-
| `--version` | Show version |
|
|
113
|
-
| `--help` | Show help |
|
|
114
103
|
|
|
115
104
|
## Available Tools
|
|
116
105
|
|
|
@@ -118,118 +107,166 @@ echo "show my positions" | quantish
|
|
|
118
107
|
|
|
119
108
|
| Tool | Description |
|
|
120
109
|
|------|-------------|
|
|
121
|
-
| `read_file` | Read file contents |
|
|
122
|
-
| `write_file` |
|
|
110
|
+
| `read_file` | Read file contents with line numbers |
|
|
111
|
+
| `write_file` | Create or overwrite files |
|
|
112
|
+
| `edit_file` | Search and replace in files |
|
|
113
|
+
| `edit_lines` | Edit specific line ranges (efficient) |
|
|
123
114
|
| `list_dir` | List directory contents |
|
|
124
115
|
| `delete_file` | Delete files |
|
|
125
116
|
| `file_exists` | Check if file exists |
|
|
126
|
-
| `run_command` | Execute shell commands |
|
|
117
|
+
| `run_command` | Execute shell commands (blocking) |
|
|
118
|
+
| `start_background_process` | Run long-running processes |
|
|
119
|
+
| `get_process_output` | Get output from background process |
|
|
120
|
+
| `stop_process` | Stop a background process |
|
|
127
121
|
| `grep` | Search file contents |
|
|
128
122
|
| `find_files` | Find files by pattern |
|
|
129
|
-
| `
|
|
130
|
-
|
|
123
|
+
| `setup_env` | Create/update .env files |
|
|
124
|
+
|
|
125
|
+
### Git Tools
|
|
126
|
+
|
|
127
|
+
| Tool | Description |
|
|
128
|
+
|------|-------------|
|
|
129
|
+
| `git_status` | Get repository status |
|
|
130
|
+
| `git_diff` | Show changes |
|
|
131
131
|
| `git_add` | Stage files |
|
|
132
132
|
| `git_commit` | Create commits |
|
|
133
133
|
| `git_log` | Show commit history |
|
|
134
134
|
| `git_checkout` | Switch branches |
|
|
135
|
-
| `web_search` | Search the web (Exa/DuckDuckGo) |
|
|
136
|
-
| `web_answer` | AI-powered Q&A (Exa) |
|
|
137
|
-
| `fetch_url` | Fetch URL content |
|
|
138
135
|
|
|
139
|
-
###
|
|
136
|
+
### Web Tools
|
|
140
137
|
|
|
141
138
|
| Tool | Description |
|
|
142
139
|
|------|-------------|
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `cancel_order` | Cancel open orders |
|
|
147
|
-
| `get_orders` | List orders |
|
|
148
|
-
| `get_orderbook` | Get market orderbook |
|
|
149
|
-
| `get_price` | Get current price |
|
|
150
|
-
| `transfer_usdc` | Transfer USDC |
|
|
151
|
-
| `swap_tokens` | Swap tokens |
|
|
152
|
-
| `claim_winnings` | Claim from resolved markets |
|
|
153
|
-
|
|
154
|
-
## Configuration
|
|
140
|
+
| `web_search` | Search the web (Exa/DuckDuckGo) |
|
|
141
|
+
| `web_answer` | AI-powered Q&A (requires Exa API key) |
|
|
142
|
+
| `fetch_url` | Fetch URL content |
|
|
155
143
|
|
|
156
|
-
|
|
144
|
+
### MCP Tools (Trading)
|
|
157
145
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
146
|
+
| Tool | Server | Description |
|
|
147
|
+
|------|--------|-------------|
|
|
148
|
+
| `search_markets` | Discovery | Search markets by query |
|
|
149
|
+
| `get_trending_markets` | Discovery | Get trending/popular markets |
|
|
150
|
+
| `get_market_details` | Discovery | Get market info and prices |
|
|
151
|
+
| `get_balances` | Trading | Check wallet balances |
|
|
152
|
+
| `get_positions` | Trading | View current positions |
|
|
153
|
+
| `place_order` | Trading | Place buy/sell orders |
|
|
154
|
+
| `cancel_order` | Trading | Cancel open orders |
|
|
155
|
+
| `get_orders` | Trading | List orders |
|
|
156
|
+
| `get_orderbook` | Trading | Get market orderbook |
|
|
157
|
+
| `get_price` | Trading | Get current price |
|
|
158
|
+
| `transfer_usdc` | Trading | Transfer USDC |
|
|
159
|
+
| `claim_winnings` | Trading | Claim from resolved markets |
|
|
160
|
+
| `export_private_key` | Trading | Export wallet private key |
|
|
165
161
|
|
|
166
|
-
|
|
167
|
-
- `ANTHROPIC_API_KEY`
|
|
168
|
-
- `QUANTISH_API_KEY`
|
|
162
|
+
## LLM Providers
|
|
169
163
|
|
|
170
|
-
|
|
164
|
+
### Anthropic (Default for new installs)
|
|
171
165
|
|
|
172
|
-
|
|
166
|
+
Uses Claude models directly via Anthropic API.
|
|
173
167
|
|
|
174
168
|
```bash
|
|
175
|
-
|
|
176
|
-
|
|
169
|
+
/model opus # Claude Opus 4.5 - Most capable
|
|
170
|
+
/model sonnet # Claude Sonnet 4.5 - Balanced (default)
|
|
171
|
+
/model haiku # Claude Haiku 4.5 - Fastest/cheapest
|
|
177
172
|
```
|
|
178
173
|
|
|
179
|
-
###
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
quantish -p "show me my positions with unrealized P&L"
|
|
183
|
-
```
|
|
174
|
+
### OpenRouter
|
|
184
175
|
|
|
185
|
-
|
|
176
|
+
Access 100+ models from various providers.
|
|
186
177
|
|
|
187
178
|
```bash
|
|
188
|
-
|
|
189
|
-
> Help me set up a basic market making strategy. I want to place both bid and ask orders around the current mid price.
|
|
190
|
-
```
|
|
179
|
+
/provider openrouter # Switch to OpenRouter
|
|
191
180
|
|
|
192
|
-
|
|
181
|
+
/model glm # GLM-4.7 (default for OpenRouter) - Best for coding
|
|
182
|
+
/model minimax # MiniMax M2.1 - Fast and cheap
|
|
183
|
+
/model deepseek # DeepSeek V3.2 - Great reasoning
|
|
184
|
+
/model gemini # Gemini 2.0 Flash - Google's latest
|
|
185
|
+
/model grok # Grok 3 Mini Beta - xAI
|
|
186
|
+
```
|
|
193
187
|
|
|
188
|
+
Or use any OpenRouter model ID:
|
|
194
189
|
```bash
|
|
195
|
-
|
|
196
|
-
|
|
190
|
+
/model anthropic/claude-3.5-sonnet
|
|
191
|
+
/model meta-llama/llama-3.3-70b-instruct
|
|
197
192
|
```
|
|
198
193
|
|
|
199
|
-
##
|
|
194
|
+
## Configuration
|
|
200
195
|
|
|
201
|
-
|
|
202
|
-
# Clone the repo
|
|
203
|
-
git clone https://github.com/quantish/cli
|
|
196
|
+
Configuration is stored in `~/.quantish/config.json`.
|
|
204
197
|
|
|
205
|
-
|
|
206
|
-
cd packages/quantish-cli
|
|
207
|
-
npm install
|
|
198
|
+
### Environment Variables
|
|
208
199
|
|
|
209
|
-
|
|
210
|
-
|
|
200
|
+
| Variable | Description |
|
|
201
|
+
|----------|-------------|
|
|
202
|
+
| `ANTHROPIC_API_KEY` | Anthropic API key |
|
|
203
|
+
| `OPENROUTER_API_KEY` | OpenRouter API key |
|
|
204
|
+
| `QUANTISH_API_KEY` | Quantish trading API key |
|
|
205
|
+
| `EXA_API_KEY` | Exa AI search key (optional) |
|
|
206
|
+
| `MCP_SERVER_URL` | Custom Trading MCP server URL |
|
|
211
207
|
|
|
212
|
-
|
|
213
|
-
npm start
|
|
208
|
+
### Export Configuration
|
|
214
209
|
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
```bash
|
|
211
|
+
quantish config --export > .env
|
|
217
212
|
```
|
|
218
213
|
|
|
219
|
-
##
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
214
|
+
## Building Applications
|
|
215
|
+
|
|
216
|
+
The agent can build standalone applications that use the Quantish MCP API. When building apps, ensure:
|
|
217
|
+
|
|
218
|
+
1. **Use HTTP API** - Don't use MCP SDK directly
|
|
219
|
+
2. **Environment Variables** - Store API keys in `.env`
|
|
220
|
+
3. **Two Endpoints**:
|
|
221
|
+
- Discovery: `https://quantish.live/mcp/execute` (public)
|
|
222
|
+
- Trading: `https://quantish-sdk-production.up.railway.app/mcp/execute` (requires API key)
|
|
223
|
+
|
|
224
|
+
Example API call:
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
// Discovery MCP (simple format)
|
|
228
|
+
const response = await fetch('https://quantish.live/mcp/execute', {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: {
|
|
231
|
+
'Content-Type': 'application/json',
|
|
232
|
+
'X-API-Key': 'qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8'
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify({
|
|
235
|
+
name: 'search_markets',
|
|
236
|
+
arguments: { query: 'bitcoin', limit: 5 }
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Trading MCP (JSON-RPC format)
|
|
241
|
+
const response = await fetch('https://quantish-sdk-production.up.railway.app/mcp/execute', {
|
|
242
|
+
method: 'POST',
|
|
243
|
+
headers: {
|
|
244
|
+
'Content-Type': 'application/json',
|
|
245
|
+
'X-API-Key': process.env.QUANTISH_API_KEY
|
|
246
|
+
},
|
|
247
|
+
body: JSON.stringify({
|
|
248
|
+
jsonrpc: '2.0',
|
|
249
|
+
id: 1,
|
|
250
|
+
method: 'tools/call',
|
|
251
|
+
params: {
|
|
252
|
+
name: 'get_positions',
|
|
253
|
+
arguments: {}
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
});
|
|
230
257
|
```
|
|
231
258
|
|
|
232
|
-
|
|
259
|
+
## Self-Hosting
|
|
260
|
+
|
|
261
|
+
You can self-host the Quantish MCP server:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Set custom server URL
|
|
265
|
+
quantish config --server https://your-server.com/mcp
|
|
266
|
+
|
|
267
|
+
# Or use environment variable
|
|
268
|
+
export MCP_SERVER_URL=https://your-server.com/mcp
|
|
269
|
+
```
|
|
233
270
|
|
|
234
271
|
## Platform Support
|
|
235
272
|
|
|
@@ -239,24 +276,71 @@ The agent uses Claude to understand your requests and decide which tools to use.
|
|
|
239
276
|
| Linux | ✅ Full support |
|
|
240
277
|
| Windows | ⚠️ Requires WSL |
|
|
241
278
|
|
|
242
|
-
|
|
279
|
+
## Examples
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Search for markets
|
|
283
|
+
quantish -p "find markets about bitcoin"
|
|
243
284
|
|
|
244
|
-
|
|
285
|
+
# Check positions
|
|
286
|
+
quantish -p "show my positions with P&L"
|
|
245
287
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
288
|
+
# Build a trading bot
|
|
289
|
+
quantish
|
|
290
|
+
> Create a bot that monitors Trump markets and alerts me when prices change more than 5%
|
|
291
|
+
|
|
292
|
+
# Start a dev server
|
|
293
|
+
quantish
|
|
294
|
+
> Start my React app on port 3001
|
|
295
|
+
|
|
296
|
+
# Code review
|
|
297
|
+
quantish
|
|
298
|
+
> Review my trading bot code and suggest improvements
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Troubleshooting
|
|
302
|
+
|
|
303
|
+
### Tool calls failing with malformed arguments
|
|
304
|
+
|
|
305
|
+
Some OpenRouter models (like GLM-4.7) occasionally emit malformed tool calls. The CLI includes robust parsing to handle these, but if issues persist:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
/model sonnet # Switch to Claude Sonnet
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Session not resuming
|
|
251
312
|
|
|
252
|
-
|
|
313
|
+
Sessions are stored in `~/.quantish/sessions/`. To reset:
|
|
253
314
|
|
|
254
|
-
|
|
315
|
+
```bash
|
|
316
|
+
rm -rf ~/.quantish/sessions
|
|
317
|
+
```
|
|
255
318
|
|
|
256
|
-
|
|
319
|
+
### High token usage
|
|
257
320
|
|
|
258
|
-
|
|
321
|
+
```bash
|
|
322
|
+
/compact # Summarize conversation
|
|
323
|
+
/model haiku # Switch to cheaper model
|
|
324
|
+
/clear # Start fresh
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Development
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
git clone https://github.com/joinQuantish/quantish-agent
|
|
331
|
+
cd quantish-agent
|
|
332
|
+
npm install
|
|
333
|
+
npm run build
|
|
334
|
+
npm link # Install locally
|
|
335
|
+
```
|
|
259
336
|
|
|
260
337
|
## License
|
|
261
338
|
|
|
262
339
|
MIT
|
|
340
|
+
|
|
341
|
+
## Links
|
|
342
|
+
|
|
343
|
+
- [GitHub](https://github.com/joinQuantish/quantish-agent)
|
|
344
|
+
- [NPM](https://www.npmjs.com/package/@quantish/agent)
|
|
345
|
+
- [Documentation](https://docs.quantish.live)
|
|
346
|
+
- [Quantish Platform](https://quantish.live)
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ var DEFAULT_TRADING_MCP_URL = "https://quantish-sdk-production.up.railway.app/mc
|
|
|
14
14
|
var DISCOVERY_MCP_URL = "https://quantish.live/mcp";
|
|
15
15
|
var DISCOVERY_MCP_PUBLIC_KEY = "qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8";
|
|
16
16
|
var DEFAULT_MCP_URL = DEFAULT_TRADING_MCP_URL;
|
|
17
|
+
var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-5-20250929";
|
|
18
|
+
var DEFAULT_OPENROUTER_MODEL = "z-ai/glm-4.7";
|
|
17
19
|
var schema = {
|
|
18
20
|
anthropicApiKey: {
|
|
19
21
|
type: "string"
|
|
@@ -132,10 +134,13 @@ var ConfigManager = class {
|
|
|
132
134
|
this.conf.set("mcpServerUrl", url);
|
|
133
135
|
}
|
|
134
136
|
/**
|
|
135
|
-
* Get the model to use
|
|
137
|
+
* Get the model to use (returns default based on current provider)
|
|
136
138
|
*/
|
|
137
139
|
getModel() {
|
|
138
|
-
|
|
140
|
+
const model = this.conf.get("model");
|
|
141
|
+
if (model) return model;
|
|
142
|
+
const provider = this.getProvider();
|
|
143
|
+
return provider === "openrouter" ? DEFAULT_OPENROUTER_MODEL : DEFAULT_ANTHROPIC_MODEL;
|
|
139
144
|
}
|
|
140
145
|
/**
|
|
141
146
|
* Set the model to use
|
|
@@ -2208,114 +2213,6 @@ async function executeLocalTool(name, args) {
|
|
|
2208
2213
|
return { success: false, error: `Unknown local tool: ${name}` };
|
|
2209
2214
|
}
|
|
2210
2215
|
|
|
2211
|
-
// src/agent/compaction.ts
|
|
2212
|
-
var COMPACTION_PROMPT = `Your context window is filling up. Please create a concise summary of our conversation so far that will allow you to continue working effectively.
|
|
2213
|
-
|
|
2214
|
-
The summary should be wrapped in <summary></summary> tags and include:
|
|
2215
|
-
|
|
2216
|
-
# Task Overview
|
|
2217
|
-
- The user's core request and goals
|
|
2218
|
-
- Success criteria and constraints
|
|
2219
|
-
- Any specific preferences mentioned
|
|
2220
|
-
|
|
2221
|
-
# Current State
|
|
2222
|
-
- What has been completed so far
|
|
2223
|
-
- Files created or modified (with paths)
|
|
2224
|
-
- Artifacts or outputs produced
|
|
2225
|
-
- Current working directory if relevant
|
|
2226
|
-
|
|
2227
|
-
# Important Discoveries
|
|
2228
|
-
- Technical constraints or requirements found
|
|
2229
|
-
- Key decisions made and why
|
|
2230
|
-
- Errors encountered and how they were resolved
|
|
2231
|
-
- Approaches that didn't work (to avoid repeating)
|
|
2232
|
-
|
|
2233
|
-
# Next Steps
|
|
2234
|
-
- Specific actions still needed
|
|
2235
|
-
- Priority order if multiple steps remain
|
|
2236
|
-
- Any blockers or dependencies
|
|
2237
|
-
|
|
2238
|
-
# Context to Preserve
|
|
2239
|
-
- User preferences or style requirements
|
|
2240
|
-
- Domain-specific details that matter
|
|
2241
|
-
- Any commitments or promises made
|
|
2242
|
-
|
|
2243
|
-
Be thorough but concise. The goal is to capture everything needed to continue seamlessly, while reducing token usage significantly.`;
|
|
2244
|
-
function parseCompactedSummary(response) {
|
|
2245
|
-
const match = response.match(/<summary>([\s\S]*?)<\/summary>/);
|
|
2246
|
-
if (match && match[1]) {
|
|
2247
|
-
return match[1].trim();
|
|
2248
|
-
}
|
|
2249
|
-
return response.trim() || null;
|
|
2250
|
-
}
|
|
2251
|
-
async function createCompactedSummary(anthropic, history, model = "claude-sonnet-4-5-20250929", customPrompt) {
|
|
2252
|
-
const prompt2 = customPrompt || COMPACTION_PROMPT;
|
|
2253
|
-
const compactionMessages = [
|
|
2254
|
-
...history,
|
|
2255
|
-
{
|
|
2256
|
-
role: "user",
|
|
2257
|
-
content: prompt2
|
|
2258
|
-
}
|
|
2259
|
-
];
|
|
2260
|
-
const response = await anthropic.messages.create({
|
|
2261
|
-
model,
|
|
2262
|
-
max_tokens: 4096,
|
|
2263
|
-
messages: compactionMessages
|
|
2264
|
-
});
|
|
2265
|
-
const textBlocks = response.content.filter((block) => block.type === "text");
|
|
2266
|
-
const fullText = textBlocks.map((block) => block.text).join("\n");
|
|
2267
|
-
const summary = parseCompactedSummary(fullText);
|
|
2268
|
-
if (!summary) {
|
|
2269
|
-
throw new Error("Failed to parse compacted summary from response");
|
|
2270
|
-
}
|
|
2271
|
-
return summary;
|
|
2272
|
-
}
|
|
2273
|
-
function historyFromSummary(summary) {
|
|
2274
|
-
return [
|
|
2275
|
-
{
|
|
2276
|
-
role: "assistant",
|
|
2277
|
-
content: summary
|
|
2278
|
-
}
|
|
2279
|
-
];
|
|
2280
|
-
}
|
|
2281
|
-
async function compactConversation(anthropic, history, model, systemPrompt, tools) {
|
|
2282
|
-
let originalTokens = 0;
|
|
2283
|
-
try {
|
|
2284
|
-
const countResult = await anthropic.messages.countTokens({
|
|
2285
|
-
model,
|
|
2286
|
-
system: systemPrompt,
|
|
2287
|
-
tools,
|
|
2288
|
-
messages: history
|
|
2289
|
-
});
|
|
2290
|
-
originalTokens = countResult.input_tokens;
|
|
2291
|
-
} catch (e) {
|
|
2292
|
-
const contentLength = JSON.stringify(history).length;
|
|
2293
|
-
originalTokens = Math.ceil(contentLength / 4);
|
|
2294
|
-
}
|
|
2295
|
-
const summaryModel = "claude-sonnet-4-5-20250929";
|
|
2296
|
-
const summary = await createCompactedSummary(anthropic, history, summaryModel);
|
|
2297
|
-
const newHistory = historyFromSummary(summary);
|
|
2298
|
-
let newTokens = 0;
|
|
2299
|
-
try {
|
|
2300
|
-
const countResult = await anthropic.messages.countTokens({
|
|
2301
|
-
model,
|
|
2302
|
-
system: systemPrompt,
|
|
2303
|
-
tools,
|
|
2304
|
-
messages: newHistory
|
|
2305
|
-
});
|
|
2306
|
-
newTokens = countResult.input_tokens;
|
|
2307
|
-
} catch (e) {
|
|
2308
|
-
const contentLength = JSON.stringify(newHistory).length;
|
|
2309
|
-
newTokens = Math.ceil(contentLength / 4);
|
|
2310
|
-
}
|
|
2311
|
-
return {
|
|
2312
|
-
newHistory,
|
|
2313
|
-
summary,
|
|
2314
|
-
originalTokens,
|
|
2315
|
-
newTokens
|
|
2316
|
-
};
|
|
2317
|
-
}
|
|
2318
|
-
|
|
2319
2216
|
// src/agent/pricing.ts
|
|
2320
2217
|
var MODELS = {
|
|
2321
2218
|
"claude-opus-4-5-20250929": {
|
|
@@ -3264,7 +3161,34 @@ var OpenRouterProvider = class {
|
|
|
3264
3161
|
if (!tc || !tc.name) {
|
|
3265
3162
|
continue;
|
|
3266
3163
|
}
|
|
3164
|
+
let toolName = tc.name;
|
|
3165
|
+
if (toolName.includes("<")) {
|
|
3166
|
+
toolName = toolName.split("<")[0];
|
|
3167
|
+
}
|
|
3168
|
+
if (toolName.includes("(")) {
|
|
3169
|
+
toolName = toolName.split("(")[0];
|
|
3170
|
+
}
|
|
3171
|
+
toolName = toolName.trim();
|
|
3267
3172
|
let args = tc.arguments?.trim() || "{}";
|
|
3173
|
+
if (args.includes("<arg_key>") || args.includes("</arg_key>")) {
|
|
3174
|
+
args = args.replace(/<\/?arg_key>/g, "");
|
|
3175
|
+
if (!args.startsWith("{")) {
|
|
3176
|
+
const keyValuePairs = [];
|
|
3177
|
+
const kvMatches = args.matchAll(/(\w+):\s*(?:"([^"]+)"|(\d+)|(\w+))/g);
|
|
3178
|
+
for (const match of kvMatches) {
|
|
3179
|
+
const key = match[1];
|
|
3180
|
+
const value = match[2] ?? match[3] ?? match[4];
|
|
3181
|
+
if (match[3]) {
|
|
3182
|
+
keyValuePairs.push(`"${key}": ${value}`);
|
|
3183
|
+
} else {
|
|
3184
|
+
keyValuePairs.push(`"${key}": "${value}"`);
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
if (keyValuePairs.length > 0) {
|
|
3188
|
+
args = `{${keyValuePairs.join(", ")}}`;
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
}
|
|
3268
3192
|
if (args && !args.endsWith("}") && !args.endsWith("]")) {
|
|
3269
3193
|
const openBraces = (args.match(/{/g) || []).length;
|
|
3270
3194
|
const closeBraces = (args.match(/}/g) || []).length;
|
|
@@ -3277,10 +3201,10 @@ var OpenRouterProvider = class {
|
|
|
3277
3201
|
}
|
|
3278
3202
|
const input = JSON.parse(args);
|
|
3279
3203
|
const toolId = tc.id || `tool_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
3280
|
-
toolCalls.push({ id: toolId, name:
|
|
3281
|
-
callbacks.onToolCall?.(toolId,
|
|
3204
|
+
toolCalls.push({ id: toolId, name: toolName, input });
|
|
3205
|
+
callbacks.onToolCall?.(toolId, toolName, input);
|
|
3282
3206
|
} catch (e) {
|
|
3283
|
-
const
|
|
3207
|
+
const cleanToolName = tc?.name?.split("<")[0]?.split("(")[0]?.trim() || "unknown_tool";
|
|
3284
3208
|
let parsedInput = {};
|
|
3285
3209
|
try {
|
|
3286
3210
|
const argsStr = tc?.arguments || "";
|
|
@@ -3291,8 +3215,8 @@ var OpenRouterProvider = class {
|
|
|
3291
3215
|
} catch {
|
|
3292
3216
|
}
|
|
3293
3217
|
const toolId = tc?.id || `tool_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
3294
|
-
toolCalls.push({ id: toolId, name:
|
|
3295
|
-
callbacks.onToolCall?.(toolId,
|
|
3218
|
+
toolCalls.push({ id: toolId, name: cleanToolName, input: parsedInput });
|
|
3219
|
+
callbacks.onToolCall?.(toolId, cleanToolName, parsedInput);
|
|
3296
3220
|
}
|
|
3297
3221
|
}
|
|
3298
3222
|
const cost = calculateOpenRouterCost(
|
|
@@ -4135,16 +4059,13 @@ ${userMessage}`;
|
|
|
4135
4059
|
/**
|
|
4136
4060
|
* Compact the conversation history to reduce token usage.
|
|
4137
4061
|
*
|
|
4138
|
-
* This uses
|
|
4062
|
+
* This uses the current LLM to create a structured summary of the conversation,
|
|
4139
4063
|
* then replaces the history with just the summary. This dramatically
|
|
4140
4064
|
* reduces token count while preserving important context.
|
|
4141
4065
|
*
|
|
4142
4066
|
* @returns Object with original/new token counts and the summary
|
|
4143
4067
|
*/
|
|
4144
4068
|
async compactHistory() {
|
|
4145
|
-
const model = this.config.model ?? "claude-sonnet-4-5-20250929";
|
|
4146
|
-
const systemPrompt = this.config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
4147
|
-
const allTools = await this.getAllTools();
|
|
4148
4069
|
if (this.conversationHistory.length < 2) {
|
|
4149
4070
|
return {
|
|
4150
4071
|
success: false,
|
|
@@ -4154,23 +4075,54 @@ ${userMessage}`;
|
|
|
4154
4075
|
};
|
|
4155
4076
|
}
|
|
4156
4077
|
try {
|
|
4157
|
-
const
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4078
|
+
const originalContentLength = JSON.stringify(this.conversationHistory).length;
|
|
4079
|
+
const originalTokens = Math.ceil(originalContentLength / 4);
|
|
4080
|
+
const compactionPrompt = `Your context window is filling up. Create a concise summary of our conversation so far.
|
|
4081
|
+
|
|
4082
|
+
Include:
|
|
4083
|
+
- User's main goals and what was accomplished
|
|
4084
|
+
- Files created/modified (with paths)
|
|
4085
|
+
- Key decisions and discoveries
|
|
4086
|
+
- Next steps still needed
|
|
4087
|
+
- Any important context to preserve
|
|
4088
|
+
|
|
4089
|
+
Be thorough but concise. The goal is to capture everything needed to continue seamlessly.`;
|
|
4090
|
+
const compactionMessages = [
|
|
4091
|
+
...this.conversationHistory,
|
|
4092
|
+
{ role: "user", content: compactionPrompt }
|
|
4093
|
+
];
|
|
4094
|
+
let summary;
|
|
4095
|
+
if (this.config.provider === "openrouter" && this.llmProvider) {
|
|
4096
|
+
const response = await this.llmProvider.chat(compactionMessages);
|
|
4097
|
+
summary = response.text;
|
|
4098
|
+
} else {
|
|
4099
|
+
const model = this.config.model ?? DEFAULT_MODEL;
|
|
4100
|
+
const response = await this.anthropic.messages.create({
|
|
4101
|
+
model,
|
|
4102
|
+
max_tokens: 4096,
|
|
4103
|
+
messages: compactionMessages
|
|
4104
|
+
});
|
|
4105
|
+
const textBlocks = response.content.filter((block) => block.type === "text");
|
|
4106
|
+
summary = textBlocks.map((block) => block.text).join("\n");
|
|
4107
|
+
}
|
|
4108
|
+
if (!summary || summary.trim().length === 0) {
|
|
4109
|
+
throw new Error("Failed to generate summary");
|
|
4110
|
+
}
|
|
4111
|
+
const newHistory = [
|
|
4112
|
+
{ role: "assistant", content: summary.trim() }
|
|
4113
|
+
];
|
|
4114
|
+
const newContentLength = JSON.stringify(newHistory).length;
|
|
4115
|
+
const newTokens = Math.ceil(newContentLength / 4);
|
|
4116
|
+
this.conversationHistory = newHistory;
|
|
4165
4117
|
this.resetTokenUsage();
|
|
4166
|
-
this.cumulativeTokenUsage.inputTokens =
|
|
4167
|
-
this.cumulativeTokenUsage.totalTokens =
|
|
4118
|
+
this.cumulativeTokenUsage.inputTokens = newTokens;
|
|
4119
|
+
this.cumulativeTokenUsage.totalTokens = newTokens;
|
|
4168
4120
|
this.config.onTokenUsage?.(this.cumulativeTokenUsage);
|
|
4169
4121
|
return {
|
|
4170
4122
|
success: true,
|
|
4171
|
-
summary:
|
|
4172
|
-
originalTokenCount:
|
|
4173
|
-
newTokenCount:
|
|
4123
|
+
summary: summary.trim(),
|
|
4124
|
+
originalTokenCount: originalTokens,
|
|
4125
|
+
newTokenCount: newTokens
|
|
4174
4126
|
};
|
|
4175
4127
|
} catch (error2) {
|
|
4176
4128
|
return {
|
|
@@ -5299,7 +5251,7 @@ Stopped ${count} background process${count > 1 ? "es" : ""}.`);
|
|
|
5299
5251
|
}
|
|
5300
5252
|
|
|
5301
5253
|
// src/index.ts
|
|
5302
|
-
var VERSION = "0.1.
|
|
5254
|
+
var VERSION = "0.1.23";
|
|
5303
5255
|
function cleanup() {
|
|
5304
5256
|
if (processManager.hasRunning()) {
|
|
5305
5257
|
const count = processManager.runningCount();
|