@quantish/agent 0.1.2 → 0.1.4

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 (2) hide show
  1. package/dist/index.js +362 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -913,8 +913,111 @@ var filesystemTools = [
913
913
  },
914
914
  required: ["path", "old_string", "new_string"]
915
915
  }
916
+ },
917
+ {
918
+ name: "setup_env",
919
+ description: "Setup or update environment variables in a .env file for an application. Creates .env if it doesn't exist. Optionally creates a .env.example template. Use this when building any application that needs API keys or configuration.",
920
+ input_schema: {
921
+ type: "object",
922
+ properties: {
923
+ path: {
924
+ type: "string",
925
+ description: 'Path to the .env file (default: ".env" in current directory)'
926
+ },
927
+ variables: {
928
+ type: "object",
929
+ description: 'Object with environment variable names as keys and values. Example: { "QUANTISH_API_KEY": "abc123", "TOKEN_ID": "xyz" }',
930
+ additionalProperties: { type: "string" }
931
+ },
932
+ overwrite: {
933
+ type: "boolean",
934
+ description: "If true, overwrite existing variables. Default false (skip existing)."
935
+ },
936
+ create_example: {
937
+ type: "boolean",
938
+ description: "If true, also create a .env.example template file with placeholder values."
939
+ }
940
+ },
941
+ required: ["variables"]
942
+ }
916
943
  }
917
944
  ];
945
+ async function setupEnv(envPath = ".env", variables, options) {
946
+ try {
947
+ const resolvedPath = path.resolve(envPath);
948
+ let content = "";
949
+ const existingVars = {};
950
+ if (existsSync(resolvedPath)) {
951
+ content = await fs.readFile(resolvedPath, "utf-8");
952
+ for (const line of content.split("\n")) {
953
+ const trimmed = line.trim();
954
+ if (trimmed && !trimmed.startsWith("#")) {
955
+ const eqIndex = trimmed.indexOf("=");
956
+ if (eqIndex > 0) {
957
+ const key = trimmed.slice(0, eqIndex);
958
+ const value = trimmed.slice(eqIndex + 1);
959
+ existingVars[key] = value;
960
+ }
961
+ }
962
+ }
963
+ }
964
+ const updatedVars = [];
965
+ const addedVars = [];
966
+ const skippedVars = [];
967
+ for (const [key, value] of Object.entries(variables)) {
968
+ if (existingVars[key] !== void 0) {
969
+ if (options?.overwrite) {
970
+ const regex = new RegExp(`^${key}=.*$`, "m");
971
+ content = content.replace(regex, `${key}=${value}`);
972
+ updatedVars.push(key);
973
+ } else {
974
+ skippedVars.push(key);
975
+ }
976
+ } else {
977
+ if (content && !content.endsWith("\n")) {
978
+ content += "\n";
979
+ }
980
+ content += `${key}=${value}
981
+ `;
982
+ addedVars.push(key);
983
+ }
984
+ }
985
+ await fs.writeFile(resolvedPath, content, "utf-8");
986
+ if (options?.createExample) {
987
+ const examplePath = resolvedPath.replace(/\.env$/, ".env.example");
988
+ let exampleContent = "# Environment variables for this application\n";
989
+ exampleContent += "# Copy this file to .env and fill in your values\n\n";
990
+ for (const key of Object.keys({ ...existingVars, ...variables })) {
991
+ if (key === "QUANTISH_API_KEY") {
992
+ exampleContent += `# Get your API key at https://quantish.live
993
+ `;
994
+ exampleContent += `${key}=your_api_key_here
995
+
996
+ `;
997
+ } else {
998
+ exampleContent += `${key}=
999
+ `;
1000
+ }
1001
+ }
1002
+ await fs.writeFile(examplePath, exampleContent, "utf-8");
1003
+ }
1004
+ return {
1005
+ success: true,
1006
+ data: {
1007
+ path: resolvedPath,
1008
+ added: addedVars,
1009
+ updated: updatedVars,
1010
+ skipped: skippedVars,
1011
+ exampleCreated: options?.createExample || false
1012
+ }
1013
+ };
1014
+ } catch (error2) {
1015
+ return {
1016
+ success: false,
1017
+ error: `Failed to setup env: ${error2 instanceof Error ? error2.message : String(error2)}`
1018
+ };
1019
+ }
1020
+ }
918
1021
  async function executeFilesystemTool(name, args) {
919
1022
  switch (name) {
920
1023
  case "read_file":
@@ -937,6 +1040,15 @@ async function executeFilesystemTool(name, args) {
937
1040
  args.new_string,
938
1041
  { replaceAll: args.replace_all }
939
1042
  );
1043
+ case "setup_env":
1044
+ return setupEnv(
1045
+ args.path || ".env",
1046
+ args.variables,
1047
+ {
1048
+ overwrite: args.overwrite,
1049
+ createExample: args.create_example
1050
+ }
1051
+ );
940
1052
  default:
941
1053
  return { success: false, error: `Unknown filesystem tool: ${name}` };
942
1054
  }
@@ -2566,13 +2678,21 @@ You can work with the local filesystem:
2566
2678
  - When writing code, follow existing patterns and conventions
2567
2679
  - For dangerous operations (rm, sudo), explain what you're doing
2568
2680
 
2569
- You help users build trading bots and agents by combining coding skills with trading capabilities.
2681
+ You help users build ANY application that interacts with prediction markets - trading bots, web apps, mobile backends, dashboards, notification systems, analytics tools, Discord bots, Telegram bots, and more.
2682
+
2683
+ ## Building Applications with Quantish MCP
2570
2684
 
2571
- ## Building Standalone Trading Bots
2685
+ When users ask you to create ANY application that uses prediction market data or trading (bots, APIs, web apps, scripts, etc.), you MUST use the Quantish MCP HTTP API. This is the ONLY way to access market data and trading functionality in standalone applications.
2572
2686
 
2573
- When users ask you to create trading bots or agents that run independently (not through this CLI), here's how to integrate with the Quantish MCP API:
2687
+ ### \u26A0\uFE0F CRITICAL: DO NOT USE MCP SDK DIRECTLY
2688
+ NEVER import or use these packages in standalone apps:
2689
+ - \u274C @modelcontextprotocol/sdk
2690
+ - \u274C StdioClientTransport
2691
+ - \u274C Client from MCP SDK
2574
2692
 
2575
- ### MCP API Endpoint
2693
+ These only work within the Quantish CLI itself. Standalone apps MUST use the HTTP API with fetch().
2694
+
2695
+ ### MCP HTTP API Endpoint
2576
2696
  \`\`\`
2577
2697
  POST https://quantish-sdk-production.up.railway.app/mcp/execute
2578
2698
  \`\`\`
@@ -2702,14 +2822,250 @@ async function monitorPrice(tokenId, threshold) {
2702
2822
  setInterval(() => monitorPrice(process.env.TOKEN_ID, 0.5), 60000);
2703
2823
  \`\`\`
2704
2824
 
2705
- ### Bot Best Practices
2825
+ ### Best Practices
2706
2826
  1. **Environment Variables**: Always use process.env for API keys
2707
2827
  2. **Error Handling**: Wrap all API calls in try/catch
2708
2828
  3. **Rate Limiting**: Poll at 30-60 second intervals minimum
2709
2829
  4. **Logging**: Log all trades with timestamps for debugging
2710
2830
  5. **Testing**: Test with small amounts first
2711
2831
  6. **Graceful Shutdown**: Handle SIGINT to clean up
2712
- 7. **.env.example**: Always create a template for required env vars`;
2832
+ 7. **.env.example**: Always create a template for required env vars
2833
+
2834
+ ## CRITICAL: Code Generation Rules (MUST FOLLOW)
2835
+
2836
+ When generating ANY code that uses Quantish/MCP (bots, apps, scripts, APIs, etc.):
2837
+
2838
+ ### MANDATORY Requirements
2839
+
2840
+ 1. **ALWAYS include the callTool() helper function** - Copy it EXACTLY from the template above
2841
+ 2. **ALWAYS use callTool() for ALL MCP operations** - Never use direct API calls to Polymarket
2842
+ 3. **NEVER hardcode prices, market data, or API responses** - Always fetch live data via callTool()
2843
+ 4. **NEVER comment out MCP calls** - All API calls must be real, working, executable code
2844
+ 5. **ALWAYS create .env.example** - Document all required environment variables
2845
+ 6. **ALWAYS validate QUANTISH_API_KEY exists** - Fail fast with clear error if missing
2846
+ 7. **ALWAYS use dotenv** - \`require('dotenv').config()\` at the top of every file
2847
+
2848
+ ### File Structure for ANY Application
2849
+
2850
+ When creating an application, ALWAYS create these files:
2851
+ 1. Main application file (e.g., \`app.js\`, \`bot.js\`, \`server.js\`)
2852
+ 2. \`.env.example\` with all required variables documented
2853
+ 3. \`package.json\` with dependencies (dotenv, etc.)
2854
+ 4. \`README.md\` with setup instructions
2855
+
2856
+ ### Example .env.example (ALWAYS CREATE THIS)
2857
+ \`\`\`
2858
+ # Quantish MCP API Key (required for trading)
2859
+ # Get yours at: https://quantish.live
2860
+ QUANTISH_API_KEY=your_api_key_here
2861
+
2862
+ # Market Configuration (customize for your use case)
2863
+ TOKEN_ID=your_token_id_here
2864
+ CONDITION_ID=your_condition_id_here
2865
+ \`\`\`
2866
+
2867
+ ### WRONG vs CORRECT Code Examples
2868
+
2869
+ WRONG - Hardcoded data (NEVER DO THIS):
2870
+ \`\`\`javascript
2871
+ const prices = { YES: 0.55, NO: 0.45 }; // WRONG: hardcoded
2872
+ const mockResult = { mid: "0.50" }; // WRONG: mock data
2873
+ // await callTool('place_order', {...}); // WRONG: commented out
2874
+ \`\`\`
2875
+
2876
+ CORRECT - Live MCP calls (ALWAYS DO THIS):
2877
+ \`\`\`javascript
2878
+ const priceResult = await callTool('get_price', { tokenId });
2879
+ const price = parseFloat(priceResult.mid);
2880
+ const orderResult = await callTool('place_order', {
2881
+ conditionId, tokenId, side: 'BUY', price, size
2882
+ });
2883
+ console.log('Order placed:', orderResult.orderId);
2884
+ \`\`\`
2885
+
2886
+ ### SIMPLE EXAMPLE - Copy This Pattern Exactly
2887
+
2888
+ \`\`\`javascript
2889
+ // Simple bot that searches markets - CORRECT PATTERN
2890
+ require('dotenv').config();
2891
+
2892
+ async function callTool(name, args = {}) {
2893
+ const res = await fetch('https://quantish.live/mcp/execute', {
2894
+ method: 'POST',
2895
+ headers: {
2896
+ 'Content-Type': 'application/json',
2897
+ 'X-API-Key': 'qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8'
2898
+ },
2899
+ body: JSON.stringify({
2900
+ jsonrpc: '2.0',
2901
+ method: 'tools/call',
2902
+ params: { name, arguments: args },
2903
+ id: 1
2904
+ })
2905
+ });
2906
+ const data = await res.json();
2907
+ return JSON.parse(data.result.content[0].text);
2908
+ }
2909
+
2910
+ // Use it!
2911
+ const markets = await callTool('search_markets', { query: 'bitcoin', limit: 5 });
2912
+ console.log(markets);
2913
+ \`\`\`
2914
+
2915
+ ### Complete Production-Ready Template
2916
+
2917
+ Use this as the starting point for ANY application:
2918
+
2919
+ \`\`\`javascript
2920
+ #!/usr/bin/env node
2921
+ /**
2922
+ * Quantish Application Template
2923
+ * Replace this with your application description
2924
+ */
2925
+
2926
+ require('dotenv').config();
2927
+
2928
+ // ============================================
2929
+ // MCP Configuration - DO NOT MODIFY
2930
+ // ============================================
2931
+ const TRADING_MCP_URL = 'https://quantish-sdk-production.up.railway.app/mcp/execute';
2932
+ const DISCOVERY_MCP_URL = 'https://quantish.live/mcp/execute';
2933
+ const DISCOVERY_API_KEY = 'qm_ueQeqrmvZyHtR1zuVbLYkhx0fKyVAuV8'; // Public key for discovery
2934
+
2935
+ // Validate required environment variables
2936
+ if (!process.env.QUANTISH_API_KEY) {
2937
+ console.error('ERROR: QUANTISH_API_KEY environment variable is required');
2938
+ console.error('Get your API key at: https://quantish.live');
2939
+ console.error('Then create a .env file with: QUANTISH_API_KEY=your_key_here');
2940
+ process.exit(1);
2941
+ }
2942
+
2943
+ // ============================================
2944
+ // MCP Helper Functions - COPY THESE EXACTLY
2945
+ // ============================================
2946
+
2947
+ /**
2948
+ * Call a trading tool (requires QUANTISH_API_KEY)
2949
+ * Tools: get_balances, get_positions, place_order, cancel_order, get_orders,
2950
+ * get_orderbook, get_price, get_deposit_addresses, transfer_usdc
2951
+ */
2952
+ async function callTradingTool(name, args = {}) {
2953
+ const response = await fetch(TRADING_MCP_URL, {
2954
+ method: 'POST',
2955
+ headers: {
2956
+ 'Content-Type': 'application/json',
2957
+ 'x-api-key': process.env.QUANTISH_API_KEY
2958
+ },
2959
+ body: JSON.stringify({
2960
+ jsonrpc: '2.0',
2961
+ method: 'tools/call',
2962
+ params: { name, arguments: args },
2963
+ id: Date.now()
2964
+ })
2965
+ });
2966
+
2967
+ const data = await response.json();
2968
+ if (data.error) throw new Error(data.error.message || JSON.stringify(data.error));
2969
+
2970
+ try {
2971
+ return JSON.parse(data.result.content[0].text);
2972
+ } catch {
2973
+ return data.result.content[0].text;
2974
+ }
2975
+ }
2976
+
2977
+ /**
2978
+ * Call a discovery tool (no auth required)
2979
+ * Tools: search_markets, get_market_details, get_trending_markets, find_arbitrage
2980
+ */
2981
+ async function callDiscoveryTool(name, args = {}) {
2982
+ const response = await fetch(DISCOVERY_MCP_URL, {
2983
+ method: 'POST',
2984
+ headers: {
2985
+ 'Content-Type': 'application/json',
2986
+ 'X-API-Key': DISCOVERY_API_KEY
2987
+ },
2988
+ body: JSON.stringify({
2989
+ jsonrpc: '2.0',
2990
+ method: 'tools/call',
2991
+ params: { name, arguments: args },
2992
+ id: Date.now()
2993
+ })
2994
+ });
2995
+
2996
+ const data = await response.json();
2997
+ if (data.error) throw new Error(data.error.message || JSON.stringify(data.error));
2998
+
2999
+ try {
3000
+ return JSON.parse(data.result.content[0].text);
3001
+ } catch {
3002
+ return data.result.content[0].text;
3003
+ }
3004
+ }
3005
+
3006
+ // Shorthand for common operations
3007
+ const callTool = callTradingTool; // Default to trading tools
3008
+
3009
+ // ============================================
3010
+ // Your Application Code Goes Here
3011
+ // ============================================
3012
+
3013
+ async function main() {
3014
+ console.log('Starting application...');
3015
+
3016
+ try {
3017
+ // Example: Get wallet balances
3018
+ const balances = await callTool('get_balances');
3019
+ console.log('Wallet balances:', balances);
3020
+
3021
+ // Example: Search for markets
3022
+ const markets = await callDiscoveryTool('search_markets', {
3023
+ query: 'Bitcoin',
3024
+ limit: 5
3025
+ });
3026
+ console.log('Found markets:', markets.found);
3027
+
3028
+ // Example: Get price for a token
3029
+ if (process.env.TOKEN_ID) {
3030
+ const price = await callTool('get_price', {
3031
+ tokenId: process.env.TOKEN_ID
3032
+ });
3033
+ console.log('Current price:', price.mid);
3034
+ }
3035
+
3036
+ } catch (error) {
3037
+ console.error('Error:', error.message);
3038
+ }
3039
+ }
3040
+
3041
+ // Graceful shutdown
3042
+ process.on('SIGINT', () => {
3043
+ console.log('\\nShutting down...');
3044
+ process.exit(0);
3045
+ });
3046
+
3047
+ process.on('SIGTERM', () => {
3048
+ console.log('\\nShutting down...');
3049
+ process.exit(0);
3050
+ });
3051
+
3052
+ // Run the application
3053
+ main().catch(console.error);
3054
+ \`\`\`
3055
+
3056
+ ### Application Types You Can Build
3057
+
3058
+ - **Trading Bots**: Automated trading based on price thresholds, trends, or signals
3059
+ - **Price Monitors**: Alert systems for price movements via email, SMS, Discord, Telegram
3060
+ - **Web Dashboards**: React/Next.js apps displaying market data and portfolio
3061
+ - **API Backends**: Express/Fastify servers exposing market data to frontends
3062
+ - **Analytics Tools**: Scripts that analyze historical prices and trends
3063
+ - **Arbitrage Scanners**: Tools that find and execute arbitrage opportunities
3064
+ - **Portfolio Trackers**: Apps that track positions across multiple markets
3065
+ - **Notification Services**: Webhooks that trigger on market events
3066
+ - **Discord/Telegram Bots**: Chat bots that provide market info and execute trades
3067
+
3068
+ For ALL of these, use the MCP helper functions above. Never make direct API calls to Polymarket or other services.`;
2713
3069
  var Agent = class {
2714
3070
  anthropic;
2715
3071
  mcpClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantish/agent",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "AI-powered agent for building trading bots on Polymarket",
5
5
  "type": "module",
6
6
  "bin": {