@quantish/agent 0.1.46 → 0.1.48
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/LICENSE +2 -0
- package/dist/index.js +162 -96
- package/package.json +1 -1
package/LICENSE
CHANGED
package/dist/index.js
CHANGED
|
@@ -1052,6 +1052,65 @@ async function fileExists(filePath) {
|
|
|
1052
1052
|
return { success: false, error: `Failed to check file: ${error2 instanceof Error ? error2.message : String(error2)}` };
|
|
1053
1053
|
}
|
|
1054
1054
|
}
|
|
1055
|
+
async function workspaceSummary(dirPath, options) {
|
|
1056
|
+
const maxDepth = options?.maxDepth ?? 3;
|
|
1057
|
+
const maxFiles = options?.maxFiles ?? 100;
|
|
1058
|
+
try {
|
|
1059
|
+
const resolvedPath = path.resolve(dirPath);
|
|
1060
|
+
if (!existsSync(resolvedPath)) {
|
|
1061
|
+
return { success: false, error: `Directory not found: ${dirPath}` };
|
|
1062
|
+
}
|
|
1063
|
+
const tree = [];
|
|
1064
|
+
let fileCount = 0;
|
|
1065
|
+
let dirCount = 0;
|
|
1066
|
+
const skipDirs = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "build", ".next", "__pycache__", "venv", ".venv", "target"]);
|
|
1067
|
+
async function walkDir(currentPath, prefix, depth) {
|
|
1068
|
+
if (depth > maxDepth || fileCount >= maxFiles) return;
|
|
1069
|
+
const entries = await fs.readdir(currentPath, { withFileTypes: true });
|
|
1070
|
+
entries.sort((a, b) => {
|
|
1071
|
+
if (a.isDirectory() === b.isDirectory()) return a.name.localeCompare(b.name);
|
|
1072
|
+
return a.isDirectory() ? -1 : 1;
|
|
1073
|
+
});
|
|
1074
|
+
for (let i = 0; i < entries.length && fileCount < maxFiles; i++) {
|
|
1075
|
+
const entry = entries[i];
|
|
1076
|
+
const isLast = i === entries.length - 1;
|
|
1077
|
+
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
1078
|
+
const newPrefix = isLast ? prefix + " " : prefix + "\u2502 ";
|
|
1079
|
+
if (entry.isDirectory()) {
|
|
1080
|
+
if (skipDirs.has(entry.name)) {
|
|
1081
|
+
tree.push(`${prefix}${connector}${entry.name}/ (skipped)`);
|
|
1082
|
+
} else {
|
|
1083
|
+
dirCount++;
|
|
1084
|
+
tree.push(`${prefix}${connector}${entry.name}/`);
|
|
1085
|
+
await walkDir(path.join(currentPath, entry.name), newPrefix, depth + 1);
|
|
1086
|
+
}
|
|
1087
|
+
} else {
|
|
1088
|
+
fileCount++;
|
|
1089
|
+
const filePath = path.join(currentPath, entry.name);
|
|
1090
|
+
const stats = await fs.stat(filePath);
|
|
1091
|
+
const size = stats.size < 1024 ? `${stats.size}B` : stats.size < 1024 * 1024 ? `${Math.round(stats.size / 1024)}KB` : `${Math.round(stats.size / (1024 * 1024))}MB`;
|
|
1092
|
+
tree.push(`${prefix}${connector}${entry.name} (${size})`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
tree.push(path.basename(resolvedPath) + "/");
|
|
1097
|
+
await walkDir(resolvedPath, "", 1);
|
|
1098
|
+
return {
|
|
1099
|
+
success: true,
|
|
1100
|
+
data: {
|
|
1101
|
+
path: resolvedPath,
|
|
1102
|
+
tree: tree.join("\n"),
|
|
1103
|
+
stats: {
|
|
1104
|
+
totalFiles: fileCount,
|
|
1105
|
+
totalDirectories: dirCount,
|
|
1106
|
+
truncated: fileCount >= maxFiles
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
} catch (error2) {
|
|
1111
|
+
return { success: false, error: `Failed to summarize workspace: ${error2 instanceof Error ? error2.message : String(error2)}` };
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1055
1114
|
async function editFile(filePath, oldString, newString, options) {
|
|
1056
1115
|
try {
|
|
1057
1116
|
const resolvedPath = path.resolve(filePath);
|
|
@@ -1194,6 +1253,35 @@ var filesystemTools = [
|
|
|
1194
1253
|
},
|
|
1195
1254
|
required: ["path", "old_string", "new_string"]
|
|
1196
1255
|
}
|
|
1256
|
+
},
|
|
1257
|
+
{
|
|
1258
|
+
name: "workspace_summary",
|
|
1259
|
+
description: `Get a tree-view summary of a directory. Perfect for understanding project structure after scaffolding or cloning.
|
|
1260
|
+
|
|
1261
|
+
Automatically skips: node_modules, .git, dist, build, .next, __pycache__, venv
|
|
1262
|
+
|
|
1263
|
+
Shows file sizes and provides a quick overview. Use this after:
|
|
1264
|
+
- Running npx create-react-app, npm create vite, etc.
|
|
1265
|
+
- Cloning a repo
|
|
1266
|
+
- Any command that creates multiple files`,
|
|
1267
|
+
input_schema: {
|
|
1268
|
+
type: "object",
|
|
1269
|
+
properties: {
|
|
1270
|
+
path: {
|
|
1271
|
+
type: "string",
|
|
1272
|
+
description: "The directory path to summarize"
|
|
1273
|
+
},
|
|
1274
|
+
max_depth: {
|
|
1275
|
+
type: "number",
|
|
1276
|
+
description: "Optional: Maximum depth to traverse (default: 3)"
|
|
1277
|
+
},
|
|
1278
|
+
max_files: {
|
|
1279
|
+
type: "number",
|
|
1280
|
+
description: "Optional: Maximum files to show (default: 100)"
|
|
1281
|
+
}
|
|
1282
|
+
},
|
|
1283
|
+
required: ["path"]
|
|
1284
|
+
}
|
|
1197
1285
|
}
|
|
1198
1286
|
];
|
|
1199
1287
|
async function executeFilesystemTool(name, args) {
|
|
@@ -1218,6 +1306,11 @@ async function executeFilesystemTool(name, args) {
|
|
|
1218
1306
|
args.new_string,
|
|
1219
1307
|
{ replaceAll: args.replace_all }
|
|
1220
1308
|
);
|
|
1309
|
+
case "workspace_summary":
|
|
1310
|
+
return workspaceSummary(args.path, {
|
|
1311
|
+
maxDepth: args.max_depth,
|
|
1312
|
+
maxFiles: args.max_files
|
|
1313
|
+
});
|
|
1221
1314
|
default:
|
|
1222
1315
|
return { success: false, error: `Unknown filesystem tool: ${name}` };
|
|
1223
1316
|
}
|
|
@@ -1434,15 +1527,40 @@ var PACKAGE_MANAGER_PATTERNS = [
|
|
|
1434
1527
|
/^cargo\s+(build|install)/,
|
|
1435
1528
|
/^go\s+(build|get|mod)/
|
|
1436
1529
|
];
|
|
1530
|
+
var SCAFFOLDING_PATTERNS = [
|
|
1531
|
+
/^npx\s+(--yes\s+)?create-/,
|
|
1532
|
+
// npx create-react-app, npx create-next-app
|
|
1533
|
+
/^npx\s+(--yes\s+)?@\w+\/create-/,
|
|
1534
|
+
// npx @vue/create-app, etc.
|
|
1535
|
+
/^bunx\s+create-/,
|
|
1536
|
+
// bunx create-react-app
|
|
1537
|
+
/^pnpm\s+(dlx\s+)?create-/,
|
|
1538
|
+
// pnpm create vite
|
|
1539
|
+
/^npm\s+create\s+/,
|
|
1540
|
+
// npm create vite@latest
|
|
1541
|
+
/^yarn\s+create\s+/,
|
|
1542
|
+
// yarn create react-app
|
|
1543
|
+
/^npx\s+degit/,
|
|
1544
|
+
// npx degit for templates
|
|
1545
|
+
/^npx\s+(--yes\s+)?(vite|astro|nuxt|remix|svelte)/
|
|
1546
|
+
// Direct scaffolding
|
|
1547
|
+
];
|
|
1437
1548
|
var LONG_RUNNING_PATTERNS = [
|
|
1438
1549
|
/^(npm|yarn|pnpm|bun)\s+(build|test|run)/,
|
|
1439
1550
|
/webpack|vite|esbuild|rollup/,
|
|
1440
|
-
/docker\s+(build|pull|push)
|
|
1551
|
+
/docker\s+(build|pull|push)/,
|
|
1552
|
+
/^npx\s+/
|
|
1553
|
+
// Most npx commands need more time than 30s default
|
|
1441
1554
|
];
|
|
1442
1555
|
function getSmartTimeout(command, explicitTimeout) {
|
|
1443
1556
|
if (explicitTimeout !== void 0) {
|
|
1444
1557
|
return explicitTimeout;
|
|
1445
1558
|
}
|
|
1559
|
+
for (const pattern of SCAFFOLDING_PATTERNS) {
|
|
1560
|
+
if (pattern.test(command)) {
|
|
1561
|
+
return 6e5;
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1446
1564
|
for (const pattern of PACKAGE_MANAGER_PATTERNS) {
|
|
1447
1565
|
if (pattern.test(command)) {
|
|
1448
1566
|
return 3e5;
|
|
@@ -1602,7 +1720,19 @@ async function findFiles(pattern, directory = ".") {
|
|
|
1602
1720
|
var shellTools = [
|
|
1603
1721
|
{
|
|
1604
1722
|
name: "run_command",
|
|
1605
|
-
description:
|
|
1723
|
+
description: `Execute a shell command on the local machine. Returns stdout, stderr, and exit code.
|
|
1724
|
+
|
|
1725
|
+
SMART TIMEOUTS (auto-detected):
|
|
1726
|
+
- 10 min: npx create-react-app, npm create vite, etc (scaffolding)
|
|
1727
|
+
- 5 min: npm install, yarn add, pip install (package installs)
|
|
1728
|
+
- 3 min: npm build, webpack, docker build (build commands)
|
|
1729
|
+
- 30 sec: all other commands
|
|
1730
|
+
|
|
1731
|
+
BEST PRACTICES:
|
|
1732
|
+
- For dev servers (npm start, npm run dev), use start_background_process instead
|
|
1733
|
+
- After creating a project, use list_dir to verify the files were created
|
|
1734
|
+
- Add --yes to npx commands to skip prompts (e.g., "npx --yes create-react-app myapp")
|
|
1735
|
+
- Compound commands (&&, ||, |) are supported`,
|
|
1606
1736
|
input_schema: {
|
|
1607
1737
|
type: "object",
|
|
1608
1738
|
properties: {
|
|
@@ -1616,7 +1746,7 @@ var shellTools = [
|
|
|
1616
1746
|
},
|
|
1617
1747
|
timeout: {
|
|
1618
1748
|
type: "number",
|
|
1619
|
-
description: "Optional:
|
|
1749
|
+
description: "Optional: Override timeout in milliseconds. Usually not needed - smart defaults handle most cases."
|
|
1620
1750
|
}
|
|
1621
1751
|
},
|
|
1622
1752
|
required: ["command"]
|
|
@@ -1668,7 +1798,20 @@ var shellTools = [
|
|
|
1668
1798
|
},
|
|
1669
1799
|
{
|
|
1670
1800
|
name: "start_background_process",
|
|
1671
|
-
description:
|
|
1801
|
+
description: `Start a long-running process in the background. Returns immediately with a process ID.
|
|
1802
|
+
|
|
1803
|
+
USE THIS FOR (runs indefinitely):
|
|
1804
|
+
- Dev servers: npm start, npm run dev, yarn dev
|
|
1805
|
+
- Watch modes: npm run watch, tsc --watch
|
|
1806
|
+
- Local servers: python -m http.server, serve -s build
|
|
1807
|
+
- Database servers: mongod, redis-server
|
|
1808
|
+
|
|
1809
|
+
DO NOT USE FOR (use run_command instead):
|
|
1810
|
+
- One-time installs: npm install, pip install
|
|
1811
|
+
- Project scaffolding: npx create-react-app
|
|
1812
|
+
- Build commands: npm run build
|
|
1813
|
+
|
|
1814
|
+
Returns a process ID to use with stop_process and get_process_output.`,
|
|
1672
1815
|
input_schema: {
|
|
1673
1816
|
type: "object",
|
|
1674
1817
|
properties: {
|
|
@@ -2477,20 +2620,6 @@ function resolveModelId(nameOrAlias) {
|
|
|
2477
2620
|
return id;
|
|
2478
2621
|
}
|
|
2479
2622
|
}
|
|
2480
|
-
if (OPENROUTER_MODELS[lower]) {
|
|
2481
|
-
return lower;
|
|
2482
|
-
}
|
|
2483
|
-
if (OPENROUTER_MODEL_ALIASES[lower]) {
|
|
2484
|
-
return OPENROUTER_MODEL_ALIASES[lower];
|
|
2485
|
-
}
|
|
2486
|
-
for (const [id, config] of Object.entries(OPENROUTER_MODELS)) {
|
|
2487
|
-
if (config.name.toLowerCase() === lower) {
|
|
2488
|
-
return id;
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
if (nameOrAlias.includes("/")) {
|
|
2492
|
-
return nameOrAlias;
|
|
2493
|
-
}
|
|
2494
2623
|
return null;
|
|
2495
2624
|
}
|
|
2496
2625
|
function getModelPricing(modelId) {
|
|
@@ -2620,16 +2749,6 @@ var OPENROUTER_MODELS = {
|
|
|
2620
2749
|
description: "Alibaba's coding specialist. Excellent for code generation."
|
|
2621
2750
|
}
|
|
2622
2751
|
};
|
|
2623
|
-
var OPENROUTER_MODEL_ALIASES = {
|
|
2624
|
-
"glm": "z-ai/glm-4.7",
|
|
2625
|
-
"glm-4.7": "z-ai/glm-4.7",
|
|
2626
|
-
"minimax": "minimax/minimax-m2.1",
|
|
2627
|
-
"deepseek": "deepseek/deepseek-chat",
|
|
2628
|
-
"gemini": "google/gemini-2.0-flash-001",
|
|
2629
|
-
"gemini-flash": "google/gemini-2.0-flash-001",
|
|
2630
|
-
"qwen": "qwen/qwen-2.5-coder-32b-instruct",
|
|
2631
|
-
"qwen-coder": "qwen/qwen-2.5-coder-32b-instruct"
|
|
2632
|
-
};
|
|
2633
2752
|
|
|
2634
2753
|
// src/agent/provider.ts
|
|
2635
2754
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -3570,7 +3689,10 @@ var ACTIONABLE_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3570
3689
|
"status",
|
|
3571
3690
|
"endDate",
|
|
3572
3691
|
// Platform (for multi-platform support)
|
|
3573
|
-
"platform"
|
|
3692
|
+
"platform",
|
|
3693
|
+
// Nested structures containing price data (Discovery MCP response)
|
|
3694
|
+
"markets",
|
|
3695
|
+
"outcomes"
|
|
3574
3696
|
]);
|
|
3575
3697
|
var SUMMARY_FIELDS = /* @__PURE__ */ new Set([
|
|
3576
3698
|
"volume",
|
|
@@ -3643,81 +3765,25 @@ function extractTokenInfo(token) {
|
|
|
3643
3765
|
price: token.price ?? token.probability
|
|
3644
3766
|
};
|
|
3645
3767
|
}
|
|
3646
|
-
var DEFAULT_SYSTEM_PROMPT = `You are Quantish, an AI trading agent for prediction markets.
|
|
3647
|
-
|
|
3648
|
-
## \u26A0\uFE0F MANDATORY TABLE FORMAT - READ THIS FIRST \u26A0\uFE0F
|
|
3649
|
-
|
|
3650
|
-
When displaying market search results, you MUST include PRICES in your table. The data is in the response - extract it!
|
|
3651
|
-
|
|
3652
|
-
Response structure: markets[].markets[].outcomes[] contains { name: "Yes"/"No", price: 0.05, probability: "5%" }
|
|
3653
|
-
|
|
3654
|
-
REQUIRED table format:
|
|
3655
|
-
| Market | Yes | No | Volume | End Date |
|
|
3656
|
-
| Will X happen? | 5\xA2 (5%) | 95\xA2 (95%) | $1.2M | Jan 1 |
|
|
3768
|
+
var DEFAULT_SYSTEM_PROMPT = `You are Quantish, an AI trading agent for prediction markets (Polymarket, Kalshi).
|
|
3657
3769
|
|
|
3658
|
-
|
|
3770
|
+
You have tools to search markets and place trades. When showing market data, display ALL relevant information from the response including prices/probabilities.
|
|
3659
3771
|
|
|
3660
|
-
##
|
|
3772
|
+
## Building Applications
|
|
3661
3773
|
|
|
3662
|
-
When
|
|
3663
|
-
1. Call search_markets ONCE with a good query
|
|
3664
|
-
2. Present results in the REQUIRED table format above (with prices!)
|
|
3665
|
-
3. STOP. Wait for user to ask for more.
|
|
3774
|
+
When asked to create applications or projects:
|
|
3666
3775
|
|
|
3667
|
-
**
|
|
3668
|
-
search_markets already returns prices, volume, resolution criteria, and outcome probabilities.
|
|
3776
|
+
1. **Use run_command for scaffolding** - Commands like \`npx create-react-app\` or \`npm create vite\` are automatically given 10 minutes to complete. Always add \`--yes\` flag to skip prompts.
|
|
3669
3777
|
|
|
3670
|
-
|
|
3778
|
+
2. **Verify after creation** - After scaffolding completes, use \`workspace_summary\` to see the file tree and confirm the project was created correctly.
|
|
3671
3779
|
|
|
3672
|
-
|
|
3673
|
-
- search_markets(query, limit=10) \u2192 Markets WITH prices from Polymarket/Kalshi/Limitless
|
|
3674
|
-
- get_market_details(platform, marketId) \u2192 Full details WITH prices for ONE market
|
|
3675
|
-
- get_trending_markets(limit=10) \u2192 Hot markets by volume
|
|
3780
|
+
3. **Use start_background_process for dev servers** - After the app is built, use this for \`npm start\`, \`npm run dev\`, etc. These run indefinitely until stopped.
|
|
3676
3781
|
|
|
3677
|
-
**
|
|
3678
|
-
- place_order, cancel_order, get_orders, get_positions, get_balances
|
|
3679
|
-
- get_price(tokenId) \u2192 Live price (only if you need real-time, Discovery already has prices)
|
|
3680
|
-
- get_orderbook(tokenId) \u2192 Bid/ask depth
|
|
3782
|
+
4. **Read files before editing** - Always use \`read_file\` before \`edit_file\` to understand the existing code structure.
|
|
3681
3783
|
|
|
3682
|
-
|
|
3784
|
+
5. **Test incrementally** - After making changes, run the app and verify it works before making more changes.
|
|
3683
3785
|
|
|
3684
|
-
|
|
3685
|
-
- kalshi_buy_yes, kalshi_buy_no, kalshi_get_positions, kalshi_get_balances
|
|
3686
|
-
|
|
3687
|
-
**Coding Tools** (for building apps/bots):
|
|
3688
|
-
- read_file, write_file, edit_file, list_dir, grep, find_files
|
|
3689
|
-
- run_command (blocking) - for npm install, build commands
|
|
3690
|
-
- start_background_process (non-blocking) - for dev servers, watch mode
|
|
3691
|
-
- get_process_output, list_processes, stop_process
|
|
3692
|
-
- git operations: status, diff, add, commit
|
|
3693
|
-
|
|
3694
|
-
## CRITICAL: File Operations
|
|
3695
|
-
|
|
3696
|
-
**NEVER repeat the same operation.** If write_file or edit_file fails:
|
|
3697
|
-
1. Stop and tell the user what went wrong
|
|
3698
|
-
2. Do NOT retry with the same content
|
|
3699
|
-
3. Do NOT delete and rewrite - use edit_file to fix specific issues
|
|
3700
|
-
|
|
3701
|
-
When writing code files:
|
|
3702
|
-
- Write complete, valid code (not JSON-escaped strings)
|
|
3703
|
-
- Create one file at a time, verify it works
|
|
3704
|
-
- If you get stuck, ask the user for help
|
|
3705
|
-
|
|
3706
|
-
## Building Trading Bots
|
|
3707
|
-
|
|
3708
|
-
When user wants to build an app or bot:
|
|
3709
|
-
1. Create files one at a time with write_file
|
|
3710
|
-
2. The MCP servers are HTTP APIs - apps can call them directly
|
|
3711
|
-
3. Use start_background_process for dev servers
|
|
3712
|
-
4. API endpoints:
|
|
3713
|
-
- Discovery: https://discovery-mcp-production.up.railway.app (read-only, public)
|
|
3714
|
-
- Trading: https://quantish-mcp-production.up.railway.app (requires API key)
|
|
3715
|
-
|
|
3716
|
-
## Prices
|
|
3717
|
-
- Polymarket: 0.01-0.99 (probability)
|
|
3718
|
-
- Kalshi: percentages like 5% YES
|
|
3719
|
-
|
|
3720
|
-
Be concise. Present results clearly. Wait for user input.`;
|
|
3786
|
+
Be concise and helpful.`;
|
|
3721
3787
|
var Agent = class _Agent {
|
|
3722
3788
|
anthropic;
|
|
3723
3789
|
llmProvider;
|
|
@@ -4018,7 +4084,7 @@ ${userMessage}`;
|
|
|
4018
4084
|
return this.runWithProvider(userMessage);
|
|
4019
4085
|
}
|
|
4020
4086
|
const maxIterations = this.config.maxIterations ?? 15;
|
|
4021
|
-
const model = this.config.model ??
|
|
4087
|
+
const model = this.config.model ?? "claude-sonnet-4-5-20250929";
|
|
4022
4088
|
const maxTokens = this.config.maxTokens ?? 8192;
|
|
4023
4089
|
const systemPrompt = this.config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
4024
4090
|
const useStreaming = this.config.streaming ?? true;
|