@quantish/agent 0.1.46 → 0.1.47
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 -72
- 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: {
|
|
@@ -3570,7 +3713,10 @@ var ACTIONABLE_FIELDS = /* @__PURE__ */ new Set([
|
|
|
3570
3713
|
"status",
|
|
3571
3714
|
"endDate",
|
|
3572
3715
|
// Platform (for multi-platform support)
|
|
3573
|
-
"platform"
|
|
3716
|
+
"platform",
|
|
3717
|
+
// Nested structures containing price data (Discovery MCP response)
|
|
3718
|
+
"markets",
|
|
3719
|
+
"outcomes"
|
|
3574
3720
|
]);
|
|
3575
3721
|
var SUMMARY_FIELDS = /* @__PURE__ */ new Set([
|
|
3576
3722
|
"volume",
|
|
@@ -3643,81 +3789,25 @@ function extractTokenInfo(token) {
|
|
|
3643
3789
|
price: token.price ?? token.probability
|
|
3644
3790
|
};
|
|
3645
3791
|
}
|
|
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 |
|
|
3657
|
-
|
|
3658
|
-
DO NOT show tables without prices. The user needs prices to make trading decisions.
|
|
3659
|
-
|
|
3660
|
-
## Efficient Market Searching
|
|
3792
|
+
var DEFAULT_SYSTEM_PROMPT = `You are Quantish, an AI trading agent for prediction markets (Polymarket, Kalshi).
|
|
3661
3793
|
|
|
3662
|
-
|
|
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.
|
|
3794
|
+
You have tools to search markets and place trades. When showing market data, display ALL relevant information from the response including prices/probabilities.
|
|
3666
3795
|
|
|
3667
|
-
|
|
3668
|
-
search_markets already returns prices, volume, resolution criteria, and outcome probabilities.
|
|
3796
|
+
## Building Applications
|
|
3669
3797
|
|
|
3670
|
-
|
|
3798
|
+
When asked to create applications or projects:
|
|
3671
3799
|
|
|
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
|
|
3800
|
+
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.
|
|
3676
3801
|
|
|
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
|
|
3802
|
+
2. **Verify after creation** - After scaffolding completes, use \`workspace_summary\` to see the file tree and confirm the project was created correctly.
|
|
3681
3803
|
|
|
3682
|
-
|
|
3804
|
+
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.
|
|
3683
3805
|
|
|
3684
|
-
**
|
|
3685
|
-
- kalshi_buy_yes, kalshi_buy_no, kalshi_get_positions, kalshi_get_balances
|
|
3806
|
+
4. **Read files before editing** - Always use \`read_file\` before \`edit_file\` to understand the existing code structure.
|
|
3686
3807
|
|
|
3687
|
-
**
|
|
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
|
|
3808
|
+
5. **Test incrementally** - After making changes, run the app and verify it works before making more changes.
|
|
3693
3809
|
|
|
3694
|
-
|
|
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.`;
|
|
3810
|
+
Be concise and helpful.`;
|
|
3721
3811
|
var Agent = class _Agent {
|
|
3722
3812
|
anthropic;
|
|
3723
3813
|
llmProvider;
|
|
@@ -4018,7 +4108,7 @@ ${userMessage}`;
|
|
|
4018
4108
|
return this.runWithProvider(userMessage);
|
|
4019
4109
|
}
|
|
4020
4110
|
const maxIterations = this.config.maxIterations ?? 15;
|
|
4021
|
-
const model = this.config.model ??
|
|
4111
|
+
const model = this.config.model ?? "claude-sonnet-4-5-20250929";
|
|
4022
4112
|
const maxTokens = this.config.maxTokens ?? 8192;
|
|
4023
4113
|
const systemPrompt = this.config.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
4024
4114
|
const useStreaming = this.config.streaming ?? true;
|