@quantish/agent 0.1.24 → 0.1.26

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 (4) hide show
  1. package/LICENSE +137 -17
  2. package/README.md +137 -46
  3. package/dist/index.js +195 -32
  4. package/package.json +7 -3
package/LICENSE CHANGED
@@ -1,24 +1,144 @@
1
- MIT License
1
+ # PolyForm Noncommercial License 1.0.0
2
2
 
3
- Copyright (c) 2024 Quantish
3
+ <https://polyformproject.org/licenses/noncommercial/1.0.0>
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Required Notice: Copyright 2025 Quantish Inc. (https://quantish.live)
11
6
 
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
7
+ ## Acceptance
14
8
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
9
+ In order to get any license under these terms, you must agree
10
+ to them as both strict obligations and conditions to all
11
+ your licenses.
22
12
 
13
+ ## Copyright License
23
14
 
15
+ The licensor grants you a copyright license for the software
16
+ to do everything you might do with the software that would
17
+ otherwise infringe the licensor's copyright in it for any
18
+ permitted purpose. However, you may only distribute the
19
+ software according to [Distribution License](#distribution-license)
20
+ and make changes or new works based on the software according
21
+ to [Changes and New Works License](#changes-and-new-works-license).
24
22
 
23
+ ## Distribution License
24
+
25
+ The licensor grants you an additional copyright license to
26
+ distribute copies of the software. Your license to distribute
27
+ covers distributing the software with changes and new works
28
+ permitted by [Changes and New Works License](#changes-and-new-works-license).
29
+
30
+ ## Notices
31
+
32
+ You must ensure that anyone who gets a copy of any part of
33
+ the software from you also gets a copy of these terms or the
34
+ URL for them above, as well as copies of any plain-text lines
35
+ beginning with `Required Notice:` that the licensor provided
36
+ with the software. For example:
37
+
38
+ > Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
39
+
40
+ ## Changes and New Works License
41
+
42
+ The licensor grants you an additional copyright license to
43
+ make changes and new works based on the software for any
44
+ permitted purpose.
45
+
46
+ ## Patent License
47
+
48
+ The licensor grants you a patent license for the software that
49
+ covers patent claims the licensor can license, or becomes able
50
+ to license, that you would infringe by using the software.
51
+
52
+ ## Noncommercial Purposes
53
+
54
+ Any noncommercial purpose is a permitted purpose.
55
+
56
+ ## Personal Uses
57
+
58
+ Personal use for research, experiment, and testing for
59
+ the benefit of public knowledge, personal study, private
60
+ entertainment, hobby projects, amateur pursuits, or religious
61
+ observance, without any anticipated commercial application,
62
+ is use for a permitted purpose.
63
+
64
+ ## Noncommercial Organizations
65
+
66
+ Use by any charitable organization, educational institution,
67
+ public research organization, public safety or health
68
+ organization, environmental protection organization, or
69
+ government institution is use for a permitted purpose
70
+ regardless of the source of funding or obligations resulting
71
+ from the funding.
72
+
73
+ ## Fair Use
74
+
75
+ You may have "fair use" rights for the software under the
76
+ law. These terms do not limit them.
77
+
78
+ ## No Other Rights
79
+
80
+ These terms do not allow you to sublicense or transfer any
81
+ of your licenses to anyone else, or prevent the licensor
82
+ from granting licenses to anyone else. These terms do not
83
+ imply any other licenses.
84
+
85
+ ## Patent Defense
86
+
87
+ If you make any written claim that the software infringes
88
+ or contributes to infringement of any patent, your patent
89
+ license for the software granted under these terms ends
90
+ immediately. If your company makes such a claim, your
91
+ patent license ends immediately for work on behalf of your
92
+ company.
93
+
94
+ ## Violations
95
+
96
+ The first time you are notified in writing that you have
97
+ violated any of these terms, or done anything with the
98
+ software not covered by your licenses, your licenses can
99
+ nonetheless continue if you come into full compliance with
100
+ these terms, and take practical steps to correct past
101
+ violations, within 32 days of receiving notice. Otherwise,
102
+ all your licenses end immediately.
103
+
104
+ ## No Liability
105
+
106
+ ***As far as the law allows, the software comes as is,
107
+ without any warranty or condition, and the licensor will
108
+ not be liable to you for any damages arising out of these
109
+ terms or the use or nature of the software, under any kind
110
+ of legal claim.***
111
+
112
+ ## Definitions
113
+
114
+ The **licensor** is the individual or entity offering these
115
+ terms, and the **software** is the software the licensor
116
+ makes available under these terms.
117
+
118
+ **You** refers to the individual or entity agreeing to these
119
+ terms.
120
+
121
+ **Your company** is any legal entity, sole proprietorship,
122
+ or other kind of organization that you work for, plus all
123
+ organizations that have control over, are under the control
124
+ of, or are under common control with that organization.
125
+ **Control** means ownership of substantially all the assets
126
+ of an entity, or the power to direct its management and
127
+ policies by vote, contract, or otherwise. Control can be
128
+ direct or indirect.
129
+
130
+ **Your licenses** are all the licenses granted to you for
131
+ the software under these terms.
132
+
133
+ **Use** means anything you do with the software requiring
134
+ one of your licenses.
135
+
136
+ ---
137
+
138
+ ## Commercial Licensing
139
+
140
+ For commercial use or to monetize this software as a product,
141
+ please contact Quantish Inc. for a commercial license:
142
+
143
+ Email: hello@quantish.live
144
+ Website: https://quantish.live
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # @quantish/agent
2
2
 
3
- AI-powered coding & trading agent for Polymarket. Build trading bots, analyze markets, and execute trades using natural language.
3
+ AI-powered coding & trading agent for Polymarket and Kalshi. Build trading bots, analyze markets, and execute trades using natural language.
4
4
 
5
5
  ## ✨ Features
6
6
 
7
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
8
+ - **💹 Live Trading** - Trade on Polymarket (Polygon) and Kalshi (Solana via DFlow)
9
9
  - **🔧 Full Coding Tools** - Read/write files, run commands, git operations
10
10
  - **🌐 Web Search** - Search the web with Exa AI or DuckDuckGo fallback
11
11
  - **💾 Session Persistence** - Save and resume conversations across sessions
@@ -30,17 +30,26 @@ quantish
30
30
 
31
31
  ## How It Works
32
32
 
33
- The agent connects to two MCP (Model Context Protocol) servers:
33
+ The agent connects to three MCP (Model Context Protocol) servers:
34
34
 
35
- 1. **Discovery MCP** (Public) - Market search, trending markets, market details
36
- 2. **Trading MCP** (Your API Key) - Wallet, orders, positions, trades
35
+ | MCP | URL | Auth | Purpose |
36
+ |-----|-----|------|---------|
37
+ | Discovery | `quantish.live/mcp` | Public (embedded key) | Search markets across all platforms |
38
+ | Polymarket | `quantish-sdk-production.up.railway.app/mcp` | `QUANTISH_API_KEY` | Trade on Polymarket (Polygon) |
39
+ | Kalshi | `kalshi-mcp-production-7c2c.up.railway.app/mcp` | `KALSHI_API_KEY` | Trade on Kalshi (Solana via DFlow) |
37
40
 
38
- Your wallet is created and managed through our signing server, which:
39
- - ✅ Handles gasless transactions (Polymarket covers fees)
41
+ **Polymarket** - Managed Polygon wallet:
42
+ - ✅ Gasless transactions (Polymarket covers fees)
40
43
  - ✅ Signs orders using Polymarket's required format
41
44
  - ✅ Works globally (no geo-restrictions)
42
45
  - 🔒 Non-custodial - export your private key anytime
43
46
 
47
+ **Kalshi** - Managed Solana wallet via DFlow:
48
+ - ✅ Trade on CFTC-regulated Kalshi markets
49
+ - ✅ Uses DFlow protocol for on-chain settlement
50
+ - ⚡ Small SOL fees (~0.01 SOL per trade)
51
+ - 🔒 Non-custodial - export your private key anytime
52
+
44
53
  ## Interactive Commands
45
54
 
46
55
  ### Chat Commands
@@ -141,23 +150,48 @@ quantish --version # Show version
141
150
  | `web_answer` | AI-powered Q&A (requires Exa API key) |
142
151
  | `fetch_url` | Fetch URL content |
143
152
 
144
- ### MCP Tools (Trading)
145
-
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 |
153
+ ### MCP Tools - Discovery
154
+
155
+ | Tool | Description |
156
+ |------|-------------|
157
+ | `search_markets` | Search markets across Polymarket, Kalshi, Limitless |
158
+ | `get_trending_markets` | Get trending/popular markets |
159
+ | `get_market_details` | Get market info and prices |
160
+ | `get_categories` | List available categories |
161
+ | `get_market_stats` | Get platform statistics |
162
+
163
+ ### MCP Tools - Polymarket Trading
164
+
165
+ | Tool | Description |
166
+ |------|-------------|
167
+ | `get_balances` | Check USDC and position balances |
168
+ | `get_positions` | View current positions |
169
+ | `place_order` | Place buy/sell orders |
170
+ | `cancel_order` | Cancel open orders |
171
+ | `get_orders` | List orders |
172
+ | `get_orderbook` | Get market orderbook |
173
+ | `get_price` | Get current price |
174
+ | `transfer_usdc` | Transfer USDC |
175
+ | `claim_winnings` | Claim from resolved markets |
176
+ | `export_private_key` | Export wallet private key |
177
+
178
+ ### MCP Tools - Kalshi Trading
179
+
180
+ | Tool | Description |
181
+ |------|-------------|
182
+ | `kalshi_signup` | Create new account with Solana wallet |
183
+ | `kalshi_search_markets` | Search Kalshi markets |
184
+ | `kalshi_get_market` | Get market details by ticker |
185
+ | `kalshi_get_events` | Browse market categories |
186
+ | `kalshi_get_live_data` | Get live market data |
187
+ | `kalshi_get_quote` | Get quote for buy/sell order |
188
+ | `kalshi_place_order` | Execute a trade on Solana |
189
+ | `kalshi_get_wallet_info` | Get wallet address and balances |
190
+ | `kalshi_get_positions` | View Kalshi positions |
191
+ | `kalshi_check_market_initialization` | Check if market is tokenized |
192
+ | `kalshi_initialize_market` | Initialize market on-chain |
193
+ | `kalshi_check_redemption_status` | Check if market can be redeemed |
194
+ | `kalshi_export_private_key` | Export Solana private key |
161
195
 
162
196
  ## LLM Providers
163
197
 
@@ -201,9 +235,11 @@ Configuration is stored in `~/.quantish/config.json`.
201
235
  |----------|-------------|
202
236
  | `ANTHROPIC_API_KEY` | Anthropic API key |
203
237
  | `OPENROUTER_API_KEY` | OpenRouter API key |
204
- | `QUANTISH_API_KEY` | Quantish trading API key |
238
+ | `QUANTISH_API_KEY` | Polymarket trading API key |
239
+ | `KALSHI_API_KEY` | Kalshi trading API key |
205
240
  | `EXA_API_KEY` | Exa AI search key (optional) |
206
- | `MCP_SERVER_URL` | Custom Trading MCP server URL |
241
+ | `MCP_SERVER_URL` | Custom Polymarket MCP server URL |
242
+ | `KALSHI_MCP_URL` | Custom Kalshi MCP server URL |
207
243
 
208
244
  ### Export Configuration
209
245
 
@@ -217,11 +253,12 @@ The agent can build standalone applications that use the Quantish MCP API. When
217
253
 
218
254
  1. **Use HTTP API** - Don't use MCP SDK directly
219
255
  2. **Environment Variables** - Store API keys in `.env`
220
- 3. **Two Endpoints**:
256
+ 3. **Three Endpoints**:
221
257
  - Discovery: `https://quantish.live/mcp/execute` (public)
222
- - Trading: `https://quantish-sdk-production.up.railway.app/mcp/execute` (requires API key)
258
+ - Polymarket: `https://quantish-sdk-production.up.railway.app/mcp/execute` (requires `QUANTISH_API_KEY`)
259
+ - Kalshi: `https://kalshi-mcp-production-7c2c.up.railway.app/mcp` (requires `KALSHI_API_KEY`)
223
260
 
224
- Example API call:
261
+ Example API calls:
225
262
 
226
263
  ```javascript
227
264
  // Discovery MCP (simple format)
@@ -237,7 +274,7 @@ const response = await fetch('https://quantish.live/mcp/execute', {
237
274
  })
238
275
  });
239
276
 
240
- // Trading MCP (JSON-RPC format)
277
+ // Polymarket Trading MCP (JSON-RPC format)
241
278
  const response = await fetch('https://quantish-sdk-production.up.railway.app/mcp/execute', {
242
279
  method: 'POST',
243
280
  headers: {
@@ -248,26 +285,70 @@ const response = await fetch('https://quantish-sdk-production.up.railway.app/mcp
248
285
  jsonrpc: '2.0',
249
286
  id: 1,
250
287
  method: 'tools/call',
251
- params: {
252
- name: 'get_positions',
253
- arguments: {}
254
- }
288
+ params: { name: 'get_positions', arguments: {} }
289
+ })
290
+ });
291
+
292
+ // Kalshi Trading MCP (JSON-RPC format)
293
+ const response = await fetch('https://kalshi-mcp-production-7c2c.up.railway.app/mcp', {
294
+ method: 'POST',
295
+ headers: {
296
+ 'Content-Type': 'application/json',
297
+ 'X-API-Key': process.env.KALSHI_API_KEY
298
+ },
299
+ body: JSON.stringify({
300
+ jsonrpc: '2.0',
301
+ id: 1,
302
+ method: 'tools/call',
303
+ params: { name: 'kalshi_get_positions', arguments: {} }
255
304
  })
256
305
  });
257
306
  ```
258
307
 
259
308
  ## Self-Hosting
260
309
 
261
- You can self-host the Quantish MCP server:
310
+ You can self-host your own Trading MCP servers for full control over your wallet keys.
311
+
312
+ ### Polymarket Server
262
313
 
263
314
  ```bash
264
- # Set custom server URL
265
- quantish config --server https://your-server.com/mcp
315
+ npm install @quantish/server
316
+ ```
266
317
 
267
- # Or use environment variable
318
+ ```bash
319
+ # Configure CLI to use your server
268
320
  export MCP_SERVER_URL=https://your-server.com/mcp
269
321
  ```
270
322
 
323
+ Resources:
324
+ - **NPM**: [@quantish/server](https://www.npmjs.com/package/@quantish/server)
325
+ - **GitHub**: [joinQuantish/quantish-server](https://github.com/joinQuantish/quantish-server)
326
+ - **Polymarket API**: [docs.polymarket.com](https://docs.polymarket.com)
327
+
328
+ ### Kalshi Server
329
+
330
+ ```bash
331
+ npm install @quantish/kalshi-server
332
+ ```
333
+
334
+ ```bash
335
+ # Configure CLI to use your server
336
+ export KALSHI_MCP_URL=https://your-kalshi-server.com/mcp
337
+ ```
338
+
339
+ Required environment variables for Kalshi server:
340
+ - `DATABASE_URL` - PostgreSQL connection string
341
+ - `ENCRYPTION_KEY` - 64-char hex string for wallet encryption
342
+ - `DFLOW_API_KEY` - DFlow API key
343
+ - `SOLANA_RPC_URL` - Solana RPC endpoint
344
+
345
+ Resources:
346
+ - **NPM**: [@quantish/kalshi-server](https://www.npmjs.com/package/@quantish/kalshi-server)
347
+ - **GitHub**: [joinQuantish/kalshi-mcp](https://github.com/joinQuantish/kalshi-mcp)
348
+ - **DFlow Docs**: [docs.dflow.net](https://docs.dflow.net)
349
+
350
+ See the [Self-Hosting Guide](https://docs.quantish.live/self-hosting.html) for full deployment instructions.
351
+
271
352
  ## Platform Support
272
353
 
273
354
  | Platform | Support |
@@ -279,19 +360,26 @@ export MCP_SERVER_URL=https://your-server.com/mcp
279
360
  ## Examples
280
361
 
281
362
  ```bash
282
- # Search for markets
363
+ # Search for markets (both Polymarket and Kalshi)
283
364
  quantish -p "find markets about bitcoin"
284
365
 
285
- # Check positions
286
- quantish -p "show my positions with P&L"
366
+ # Check Polymarket positions
367
+ quantish -p "show my Polymarket positions with P&L"
287
368
 
288
- # Build a trading bot
369
+ # Check Kalshi positions
370
+ quantish -p "show my Kalshi positions"
371
+
372
+ # Create a Kalshi account
289
373
  quantish
290
- > Create a bot that monitors Trump markets and alerts me when prices change more than 5%
374
+ > Create a Kalshi account for me
291
375
 
292
- # Start a dev server
376
+ # Trade on Kalshi
293
377
  quantish
294
- > Start my React app on port 3001
378
+ > Buy $10 of YES on the next Fed rate decision market on Kalshi
379
+
380
+ # Build a trading bot
381
+ quantish
382
+ > Create a bot that monitors Trump markets and alerts me when prices change more than 5%
295
383
 
296
384
  # Code review
297
385
  quantish
@@ -336,10 +424,13 @@ npm link # Install locally
336
424
 
337
425
  ## License
338
426
 
339
- MIT
427
+ This project is licensed under the [PolyForm Noncommercial License 1.0.0](https://polyformproject.org/licenses/noncommercial/1.0.0/).
428
+
429
+ **Free for personal use, research, and non-commercial purposes.** Commercial use requires explicit permission from Quantish Inc. Contact hello@quantish.live for commercial licensing.
340
430
 
341
431
  ## Links
342
432
 
433
+ - [Agent Website](https://agent.quantish.live)
343
434
  - [GitHub](https://github.com/joinQuantish/quantish-agent)
344
435
  - [NPM](https://www.npmjs.com/package/@quantish/agent)
345
436
  - [Documentation](https://docs.quantish.live)
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ import { join } from "path";
13
13
  var DEFAULT_TRADING_MCP_URL = "https://quantish-sdk-production.up.railway.app/mcp";
14
14
  var DISCOVERY_MCP_URL = "https://quantish.live/mcp";
15
15
  var DISCOVERY_MCP_PUBLIC_KEY = "qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8";
16
+ var KALSHI_MCP_URL = "https://kalshi-mcp-production-7c2c.up.railway.app/mcp";
16
17
  var DEFAULT_MCP_URL = DEFAULT_TRADING_MCP_URL;
17
18
  var DEFAULT_ANTHROPIC_MODEL = "claude-sonnet-4-5-20250929";
18
19
  var DEFAULT_OPENROUTER_MODEL = "z-ai/glm-4.7";
@@ -26,6 +27,9 @@ var schema = {
26
27
  quantishApiKey: {
27
28
  type: "string"
28
29
  },
30
+ kalshiApiKey: {
31
+ type: "string"
32
+ },
29
33
  mcpServerUrl: {
30
34
  type: "string",
31
35
  default: DEFAULT_MCP_URL
@@ -91,6 +95,20 @@ var ConfigManager = class {
91
95
  setQuantishApiKey(key) {
92
96
  this.conf.set("quantishApiKey", key);
93
97
  }
98
+ /**
99
+ * Get the Kalshi API key
100
+ */
101
+ getKalshiApiKey() {
102
+ const envKey = process.env.KALSHI_API_KEY;
103
+ if (envKey) return envKey;
104
+ return this.conf.get("kalshiApiKey");
105
+ }
106
+ /**
107
+ * Set the Kalshi API key
108
+ */
109
+ setKalshiApiKey(key) {
110
+ this.conf.set("kalshiApiKey", key);
111
+ }
94
112
  /**
95
113
  * Get the current LLM provider
96
114
  */
@@ -382,18 +400,26 @@ function createMCPClient(baseUrl, apiKey, source = "trading") {
382
400
  var MCPClientManager = class {
383
401
  discoveryClient;
384
402
  tradingClient;
403
+ kalshiClient;
385
404
  toolSourceMap = /* @__PURE__ */ new Map();
386
405
  allToolsCache = null;
387
- constructor(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey) {
406
+ constructor(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey, kalshiUrl, kalshiApiKey) {
388
407
  this.discoveryClient = new MCPClient(discoveryUrl, discoveryApiKey, "discovery");
389
408
  this.tradingClient = tradingUrl && tradingApiKey ? new MCPClient(tradingUrl, tradingApiKey, "trading") : null;
409
+ this.kalshiClient = kalshiUrl && kalshiApiKey ? new MCPClient(kalshiUrl, kalshiApiKey, "kalshi") : null;
390
410
  }
391
411
  /**
392
- * Check if trading is enabled
412
+ * Check if trading is enabled (Polymarket)
393
413
  */
394
414
  isTradingEnabled() {
395
415
  return this.tradingClient !== null;
396
416
  }
417
+ /**
418
+ * Check if Kalshi trading is enabled
419
+ */
420
+ isKalshiEnabled() {
421
+ return this.kalshiClient !== null;
422
+ }
397
423
  /**
398
424
  * Get the discovery client
399
425
  */
@@ -406,6 +432,12 @@ var MCPClientManager = class {
406
432
  getTradingClient() {
407
433
  return this.tradingClient;
408
434
  }
435
+ /**
436
+ * Get the Kalshi client (may be null)
437
+ */
438
+ getKalshiClient() {
439
+ return this.kalshiClient;
440
+ }
409
441
  /**
410
442
  * List all tools from both servers
411
443
  */
@@ -435,6 +467,17 @@ var MCPClientManager = class {
435
467
  console.warn("Failed to fetch Trading MCP tools:", error2);
436
468
  }
437
469
  }
470
+ if (this.kalshiClient) {
471
+ try {
472
+ const kalshiTools = await this.kalshiClient.listTools();
473
+ for (const tool of kalshiTools) {
474
+ allTools.push({ ...tool, source: "kalshi" });
475
+ this.toolSourceMap.set(tool.name, "kalshi");
476
+ }
477
+ } catch (error2) {
478
+ console.warn("Failed to fetch Kalshi MCP tools:", error2);
479
+ }
480
+ }
438
481
  this.allToolsCache = allTools;
439
482
  return allTools;
440
483
  }
@@ -466,12 +509,22 @@ var MCPClientManager = class {
466
509
  if (!this.tradingClient) {
467
510
  return {
468
511
  success: false,
469
- error: `Trading not enabled. Run 'quantish init' to set up trading.`
512
+ error: `Polymarket trading not enabled. Run 'quantish init' to set up trading.`
470
513
  };
471
514
  }
472
515
  const result = await this.tradingClient.callTool(name, args);
473
516
  return { ...result, source: "trading" };
474
517
  }
518
+ if (source === "kalshi") {
519
+ if (!this.kalshiClient) {
520
+ return {
521
+ success: false,
522
+ error: `Kalshi trading not enabled. Run 'quantish init' to set up your Kalshi API key.`
523
+ };
524
+ }
525
+ const result = await this.kalshiClient.callTool(name, args);
526
+ return { ...result, source: "kalshi" };
527
+ }
475
528
  return {
476
529
  success: false,
477
530
  error: `Unknown tool source: ${source}`
@@ -495,8 +548,8 @@ var MCPClientManager = class {
495
548
  return { discovery, trading };
496
549
  }
497
550
  };
498
- function createMCPClientManager(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey) {
499
- return new MCPClientManager(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey);
551
+ function createMCPClientManager(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey, kalshiUrl, kalshiApiKey) {
552
+ return new MCPClientManager(discoveryUrl, discoveryApiKey, tradingUrl, tradingApiKey, kalshiUrl, kalshiApiKey);
500
553
  }
501
554
 
502
555
  // src/mcp/tools.ts
@@ -528,25 +581,28 @@ function printArchitectureInfo() {
528
581
  console.log(chalk.bold.yellow("\n\u{1F4CB} How Quantish Works\n"));
529
582
  console.log(chalk.dim("\u2500".repeat(60)));
530
583
  console.log();
531
- console.log(chalk.bold("Two Capabilities:"));
584
+ console.log(chalk.bold("Three Capabilities:"));
532
585
  console.log();
533
586
  console.log(chalk.cyan("\u{1F50D} Market Discovery") + chalk.dim(" (Free, always available)"));
534
587
  console.log(chalk.dim(" Search markets across Polymarket, Kalshi, and more"));
535
588
  console.log(chalk.dim(" Uses our Discovery MCP with embedded public key"));
536
589
  console.log();
537
590
  console.log(chalk.magenta("\u{1F4B0} Polymarket Trading") + chalk.dim(" (Optional, your own wallet)"));
538
- console.log(chalk.dim(" Trade on Polymarket with a managed wallet"));
591
+ console.log(chalk.dim(" Trade on Polymarket with a managed Polygon wallet"));
539
592
  console.log(chalk.dim(" Uses the Quantish Signing Server"));
540
593
  console.log();
594
+ console.log(chalk.blue("\u{1F5F3}\uFE0F Kalshi Trading") + chalk.dim(" (Optional, via DFlow on Solana)"));
595
+ console.log(chalk.dim(" Trade on Kalshi markets via DFlow protocol"));
596
+ console.log(chalk.dim(" Uses a Solana wallet managed by the Kalshi MCP"));
597
+ console.log();
541
598
  console.log(chalk.bold("How Trading Works:"));
542
- console.log(chalk.dim(" 1. We create a wallet for you on the Quantish Signing Server"));
543
- console.log(chalk.dim(" 2. Orders are signed and relayed through Polymarket's system"));
544
- console.log(chalk.dim(" 3. Gas fees are covered by Polymarket's relayer - FREE!"));
545
- console.log(chalk.dim(" 4. You control your wallet via your personal API key\n"));
599
+ console.log(chalk.dim(" Polymarket: Gasless transactions on Polygon, fees covered"));
600
+ console.log(chalk.dim(" Kalshi: Trade on Solana via DFlow, small SOL fees"));
601
+ console.log(chalk.dim(" Both: Non-custodial wallets, export keys anytime\n"));
546
602
  console.log(chalk.bold("Security:"));
547
- console.log(chalk.dim(" \u2022 Your wallet is non-custodial - only you can authorize trades"));
603
+ console.log(chalk.dim(" \u2022 Your wallets are non-custodial - only you can authorize trades"));
548
604
  console.log(chalk.dim(" \u2022 Export your private key anytime with: ") + chalk.cyan("export_private_key"));
549
- console.log(chalk.dim(" \u2022 Discovery is read-only - it can't access your wallet"));
605
+ console.log(chalk.dim(" \u2022 Discovery is read-only - it can't access your wallets"));
550
606
  console.log();
551
607
  console.log(chalk.dim("\u2500".repeat(60)));
552
608
  console.log();
@@ -693,7 +749,48 @@ async function runSetup() {
693
749
  } else {
694
750
  console.log(chalk.dim("\u2713 No trading key - you can still search markets via Discovery\n"));
695
751
  }
696
- console.log(chalk.bold("Step 3: Exa API Key (Optional)"));
752
+ console.log(chalk.bold("Step 3: Kalshi Trading (Optional)"));
753
+ console.log(chalk.dim("Trade on Kalshi markets via DFlow on Solana."));
754
+ console.log(chalk.dim("Skip this if you only want Polymarket or market discovery.\n"));
755
+ let kalshiKey = config.getKalshiApiKey();
756
+ let skipKalshi = false;
757
+ if (kalshiKey) {
758
+ console.log(chalk.dim(`Current Kalshi key: ${kalshiKey.slice(0, 12)}...`));
759
+ const action = await prompt("Keep current key (Enter), enter new key (n), or disable Kalshi (d): ");
760
+ if (action.toLowerCase() === "n") {
761
+ kalshiKey = await prompt("Enter your Kalshi API key: ", true);
762
+ } else if (action.toLowerCase() === "d") {
763
+ kalshiKey = void 0;
764
+ skipKalshi = true;
765
+ }
766
+ } else {
767
+ console.log("Options:");
768
+ console.log(chalk.dim(" 1. Create a new Kalshi account (via agent)"));
769
+ console.log(chalk.dim(" 2. Enter an existing Kalshi API key"));
770
+ console.log(chalk.dim(" 3. Skip Kalshi for now\n"));
771
+ const choice = await prompt("Choose (1/2/3): ");
772
+ if (choice === "1") {
773
+ console.log();
774
+ console.log(chalk.green("To create a Kalshi account, start the agent and ask:"));
775
+ console.log(chalk.cyan(' "Create a Kalshi account for me"'));
776
+ console.log(chalk.dim("\nThe agent will generate a Solana wallet and provide your API key."));
777
+ console.log(chalk.dim('You can then run "quantish init" again to save the key.\n'));
778
+ skipKalshi = true;
779
+ } else if (choice === "2") {
780
+ kalshiKey = await prompt("Enter your Kalshi API key: ", true);
781
+ } else {
782
+ skipKalshi = true;
783
+ }
784
+ }
785
+ if (kalshiKey) {
786
+ config.setKalshiApiKey(kalshiKey);
787
+ console.log(chalk.green("\u2713 Kalshi API key saved\n"));
788
+ } else if (skipKalshi) {
789
+ console.log(chalk.dim("\u2713 Kalshi disabled - you can set it up later via the agent\n"));
790
+ } else {
791
+ console.log(chalk.dim("\u2713 No Kalshi key - you can set it up later\n"));
792
+ }
793
+ console.log(chalk.bold("Step 4: Exa API Key (Optional)"));
697
794
  console.log(chalk.dim("Powers web search. Get one free at https://dashboard.exa.ai"));
698
795
  console.log(chalk.dim("Without this, web search will use DuckDuckGo as fallback.\n"));
699
796
  const exaKey = await prompt("Enter your Exa API key (or press Enter to skip): ", true);
@@ -704,7 +801,7 @@ async function runSetup() {
704
801
  } else {
705
802
  console.log(chalk.dim("Skipped. Web search will use DuckDuckGo.\n"));
706
803
  }
707
- console.log(chalk.bold("Step 4: Verifying connections..."));
804
+ console.log(chalk.bold("Step 5: Verifying connections..."));
708
805
  try {
709
806
  const discoveryClient = createMCPClient(DISCOVERY_MCP_URL, DISCOVERY_MCP_PUBLIC_KEY, "discovery");
710
807
  const discoveryResult = await discoveryClient.callTool("get_market_stats", {});
@@ -723,19 +820,37 @@ async function runSetup() {
723
820
  const result = await tradingClient.callTool("get_wallet_status", {});
724
821
  if (result.success && typeof result.data === "object" && result.data !== null) {
725
822
  const data = result.data;
726
- console.log(chalk.green("\u2713 Trading MCP connected"));
823
+ console.log(chalk.green("\u2713 Polymarket MCP connected"));
727
824
  console.log(chalk.dim(` Safe Address: ${data.safeAddress || "Not yet deployed"}`));
728
825
  console.log(chalk.dim(` Status: ${data.status}`));
729
826
  console.log(chalk.dim(` Ready to trade: ${data.isReady ? "Yes" : "Run setup_wallet first"}`));
730
827
  } else {
731
- console.log(chalk.yellow("\u26A0 Trading MCP: " + (result.error || "Unknown error")));
828
+ console.log(chalk.yellow("\u26A0 Polymarket MCP: " + (result.error || "Unknown error")));
732
829
  }
733
830
  } catch (error2) {
734
- console.log(chalk.yellow("\u26A0 Could not verify Trading MCP connection."));
831
+ console.log(chalk.yellow("\u26A0 Could not verify Polymarket MCP connection."));
735
832
  console.log(chalk.dim(String(error2)));
736
833
  }
737
834
  } else {
738
- console.log(chalk.dim("\u23ED Trading MCP skipped (no API key)"));
835
+ console.log(chalk.dim("\u23ED Polymarket MCP skipped (no API key)"));
836
+ }
837
+ if (kalshiKey) {
838
+ try {
839
+ const kalshiClient = createMCPClient(KALSHI_MCP_URL, kalshiKey, "kalshi");
840
+ const result = await kalshiClient.callTool("kalshi_get_wallet_info", {});
841
+ if (result.success && typeof result.data === "object" && result.data !== null) {
842
+ const data = result.data;
843
+ console.log(chalk.green("\u2713 Kalshi MCP connected"));
844
+ console.log(chalk.dim(` Solana Address: ${data.publicKey || "Unknown"}`));
845
+ } else {
846
+ console.log(chalk.yellow("\u26A0 Kalshi MCP: " + (result.error || "Unknown error")));
847
+ }
848
+ } catch (error2) {
849
+ console.log(chalk.yellow("\u26A0 Could not verify Kalshi MCP connection."));
850
+ console.log(chalk.dim(String(error2)));
851
+ }
852
+ } else {
853
+ console.log(chalk.dim("\u23ED Kalshi MCP skipped (no API key)"));
739
854
  }
740
855
  console.log();
741
856
  console.log(chalk.bold.green("\u{1F389} Setup complete!"));
@@ -2348,9 +2463,13 @@ function calculateCostWithPricing(pricing, inputTokens, outputTokens, cacheCreat
2348
2463
  }
2349
2464
  function formatCost(cost) {
2350
2465
  if (cost < 0.01) {
2351
- return `$${(cost * 100).toFixed(3)}\xA2`;
2466
+ const cents = cost * 100;
2467
+ return `${cents.toFixed(3)}\xA2`;
2352
2468
  }
2353
- return `$${cost.toFixed(4)}`;
2469
+ if (cost < 1) {
2470
+ return `$${cost.toFixed(4)}`;
2471
+ }
2472
+ return `$${cost.toFixed(2)}`;
2354
2473
  }
2355
2474
  function listModels() {
2356
2475
  return Object.values(MODELS);
@@ -5067,8 +5186,11 @@ Use /load <id> to load a session.`
5067
5186
  abortController.current = null;
5068
5187
  }
5069
5188
  }, [agent, isProcessing, isInterrupted, exit, onExit, handleSlashCommand]);
5189
+ const wasProcessing = useRef(false);
5070
5190
  useEffect(() => {
5071
- if (!isProcessing && hasQueuedMessage && queuedInput) {
5191
+ const justFinished = wasProcessing.current && !isProcessing;
5192
+ wasProcessing.current = isProcessing;
5193
+ if (justFinished && hasQueuedMessage && queuedInput) {
5072
5194
  const nextMessage = queuedInput;
5073
5195
  setQueuedInput("");
5074
5196
  setHasQueuedMessage(false);
@@ -5147,10 +5269,22 @@ Stopped ${count} background process${count > 1 ? "es" : ""}.`);
5147
5269
  setIsInterrupted(true);
5148
5270
  abortController.current?.abort();
5149
5271
  if (hasQueuedMessage && queuedInput) {
5150
- setMessages((prev) => [...prev, {
5151
- role: "system",
5152
- content: "\u26A1 Interrupting and sending queued message..."
5153
- }]);
5272
+ const messageToSend = queuedInput;
5273
+ setQueuedInput("");
5274
+ setHasQueuedMessage(false);
5275
+ setIsProcessing(false);
5276
+ setMessages((prev) => {
5277
+ const filtered = prev.filter(
5278
+ (m) => !(m.role === "system" && m.content.startsWith("\u{1F4E5} Queued:"))
5279
+ );
5280
+ return [...filtered, {
5281
+ role: "system",
5282
+ content: "\u26A1 Interrupted. Sending queued message..."
5283
+ }];
5284
+ });
5285
+ setTimeout(() => {
5286
+ handleSubmit(messageToSend);
5287
+ }, 200);
5154
5288
  } else {
5155
5289
  setMessages((prev) => [...prev, {
5156
5290
  role: "system",
@@ -5284,7 +5418,7 @@ Stopped ${count} background process${count > 1 ? "es" : ""}.`);
5284
5418
  }
5285
5419
 
5286
5420
  // src/index.ts
5287
- var VERSION = "0.1.24";
5421
+ var VERSION = "0.1.25";
5288
5422
  function cleanup() {
5289
5423
  if (processManager.hasRunning()) {
5290
5424
  const count = processManager.runningCount();
@@ -5373,9 +5507,9 @@ program.command("config").description("View or edit configuration").option("-s,
5373
5507
  }
5374
5508
  console.log();
5375
5509
  });
5376
- program.command("tools").description("List available tools").option("-l, --local", "Show only local tools").option("-d, --discovery", "Show only Discovery MCP tools").option("-t, --trading", "Show only Trading MCP tools").action(async (options) => {
5510
+ program.command("tools").description("List available tools").option("-l, --local", "Show only local tools").option("-d, --discovery", "Show only Discovery MCP tools").option("-t, --trading", "Show only Trading MCP tools").option("-k, --kalshi", "Show only Kalshi MCP tools").action(async (options) => {
5377
5511
  console.log();
5378
- const showAll = !options.local && !options.discovery && !options.trading;
5512
+ const showAll = !options.local && !options.discovery && !options.trading && !options.kalshi;
5379
5513
  if (showAll || options.local) {
5380
5514
  console.log(chalk3.bold.blue("\u{1F4C1} Local Tools (coding)"));
5381
5515
  printDivider();
@@ -5409,7 +5543,7 @@ program.command("tools").description("List available tools").option("-l, --local
5409
5543
  if (showAll || options.trading) {
5410
5544
  const config = getConfigManager();
5411
5545
  if (config.isTradingEnabled()) {
5412
- console.log(chalk3.bold.magenta("\u{1F4B0} Trading MCP Tools (wallet & orders)"));
5546
+ console.log(chalk3.bold.magenta("\u{1F4B0} Polymarket Trading MCP Tools (wallet & orders)"));
5413
5547
  printDivider();
5414
5548
  try {
5415
5549
  const tradingClient = createMCPClient(
@@ -5428,7 +5562,34 @@ program.command("tools").description("List available tools").option("-l, --local
5428
5562
  }
5429
5563
  console.log();
5430
5564
  } else {
5431
- console.log(chalk3.dim('\u{1F4B0} Trading MCP: Not configured. Run "quantish init" to enable trading.'));
5565
+ console.log(chalk3.dim('\u{1F4B0} Polymarket Trading MCP: Not configured. Run "quantish init" to enable trading.'));
5566
+ console.log();
5567
+ }
5568
+ }
5569
+ if (showAll || options.kalshi) {
5570
+ const config = getConfigManager();
5571
+ const kalshiKey = config.getKalshiApiKey();
5572
+ if (kalshiKey) {
5573
+ console.log(chalk3.bold.yellow("\u{1F3AF} Kalshi MCP Tools (DFlow on Solana)"));
5574
+ printDivider();
5575
+ try {
5576
+ const kalshiClient = createMCPClient(
5577
+ KALSHI_MCP_URL,
5578
+ kalshiKey,
5579
+ "kalshi"
5580
+ );
5581
+ const kalshiTools = await kalshiClient.listTools();
5582
+ for (const tool of kalshiTools) {
5583
+ console.log(chalk3.yellow(` ${tool.name}`));
5584
+ const desc = tool.description || "";
5585
+ console.log(chalk3.dim(` ${desc.slice(0, 80)}${desc.length > 80 ? "..." : ""}`));
5586
+ }
5587
+ } catch (error2) {
5588
+ warn("Could not fetch Kalshi tools. Check your API key.");
5589
+ }
5590
+ console.log();
5591
+ } else {
5592
+ console.log(chalk3.dim("\u{1F3AF} Kalshi MCP: Not configured. Set your Kalshi API key to enable."));
5432
5593
  console.log();
5433
5594
  }
5434
5595
  }
@@ -5485,7 +5646,9 @@ function createMCPManager(options) {
5485
5646
  DISCOVERY_MCP_URL,
5486
5647
  DISCOVERY_MCP_PUBLIC_KEY,
5487
5648
  config.isTradingEnabled() ? config.getTradingMcpUrl() : void 0,
5488
- config.getQuantishApiKey()
5649
+ config.getQuantishApiKey(),
5650
+ config.getKalshiApiKey() ? KALSHI_MCP_URL : void 0,
5651
+ config.getKalshiApiKey()
5489
5652
  );
5490
5653
  }
5491
5654
  async function runInteractiveChat(options = {}) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quantish/agent",
3
- "version": "0.1.24",
4
- "description": "AI-powered agent for building trading bots on Polymarket",
3
+ "version": "0.1.26",
4
+ "description": "AI-powered agent for trading on Polymarket and Kalshi",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "quantish": "./dist/index.js"
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "keywords": [
22
22
  "polymarket",
23
+ "kalshi",
23
24
  "trading",
24
25
  "cli",
25
26
  "ai",
@@ -28,11 +29,14 @@
28
29
  "mcp",
29
30
  "prediction-markets",
30
31
  "polymarket-trading",
32
+ "kalshi-trading",
33
+ "solana",
34
+ "dflow",
31
35
  "ai-agent",
32
36
  "trading-bot"
33
37
  ],
34
38
  "author": "Quantish <hello@quantish.live>",
35
- "license": "MIT",
39
+ "license": "PolyForm-Noncommercial-1.0.0",
36
40
  "publishConfig": {
37
41
  "access": "public"
38
42
  },