polydev-ai 1.10.1 → 1.10.2

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/mcp/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-perspectives",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "Multi-model AI perspectives - query GPT 5.2, Claude Opus 4.5, Gemini 3, and Grok 4.1 simultaneously. Get diverse perspectives when stuck or need enhanced reasoning. Achieved 74.6% on SWE-bench Verified.",
5
5
  "author": "Polydev AI",
6
6
  "license": "MIT",
package/mcp/server.js CHANGED
@@ -1803,7 +1803,7 @@ class MCPServer {
1803
1803
  );
1804
1804
  }
1805
1805
 
1806
- const serverUrl = 'https://www.polydev.ai/api/x-search';
1806
+ const serverUrl = 'https://polydev.ai/api/x-search';
1807
1807
 
1808
1808
  try {
1809
1809
  const response = await fetch(serverUrl, {
@@ -1863,7 +1863,7 @@ class MCPServer {
1863
1863
  );
1864
1864
  }
1865
1865
 
1866
- const serverUrl = 'https://www.polydev.ai/api/generate-image';
1866
+ const serverUrl = 'https://polydev.ai/api/generate-image';
1867
1867
 
1868
1868
  try {
1869
1869
  const response = await fetch(serverUrl, {
@@ -507,6 +507,10 @@ Token will be saved automatically after login.`
507
507
  // Handle CLI tools locally (support both prefixed and unprefixed names)
508
508
  if (this.isCliTool(toolName)) {
509
509
  return await this.handleLocalCliTool(request);
510
+ } else if (toolName === 'search_x' || toolName === 'polydev.search_x') {
511
+ return await this.handleSearchX(params, id);
512
+ } else if (toolName === 'generate_image' || toolName === 'polydev.generate_image') {
513
+ return await this.handleGenerateImage(params, id);
510
514
  } else {
511
515
  // Forward non-CLI tools to remote server
512
516
  const result = await this.forwardToRemoteServer(request);
@@ -1730,6 +1734,156 @@ To re-login: /polydev:login`
1730
1734
  }
1731
1735
  }
1732
1736
 
1737
+ /**
1738
+ * Handle X search tool locally — calls polydev.ai API
1739
+ */
1740
+ async handleSearchX(params, id) {
1741
+ const args = params.arguments || {};
1742
+ console.error('[Stdio Wrapper] Handling search_x locally');
1743
+
1744
+ if (!args.query || typeof args.query !== 'string') {
1745
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Error: query is required and must be a string' }], isError: true } };
1746
+ }
1747
+
1748
+ const userToken = args.user_token || this.userToken;
1749
+ if (!userToken) {
1750
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Authentication required for X search.\nUse the "login" tool first, or pass user_token parameter.' }], isError: true } };
1751
+ }
1752
+
1753
+ try {
1754
+ const response = await fetch('https://polydev.ai/api/x-search', {
1755
+ method: 'POST',
1756
+ headers: {
1757
+ 'Content-Type': 'application/json',
1758
+ 'Authorization': `Bearer ${userToken}`,
1759
+ 'User-Agent': 'polydev-stdio-wrapper/1.0.0'
1760
+ },
1761
+ body: JSON.stringify({
1762
+ query: args.query,
1763
+ user_token: userToken,
1764
+ model: args.model || 'grok-4-1-fast-reasoning'
1765
+ })
1766
+ });
1767
+
1768
+ if (!response.ok) {
1769
+ const errorData = await response.json().catch(() => ({}));
1770
+ if (response.status === 429) {
1771
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Free X search limit reached (50 searches).\n\nTo continue:\n1. Get an xAI API key at https://console.x.ai\n2. Add it at https://polydev.ai/dashboard/models (select "X-AI" provider)\n\nWith your own key, you get unlimited X searches.' }], isError: true } };
1772
+ }
1773
+ throw new Error(errorData.error || `X search failed: HTTP ${response.status}`);
1774
+ }
1775
+
1776
+ const result = await response.json();
1777
+
1778
+ // Format response
1779
+ let formatted = '# X Search Results\n\n';
1780
+ if (result.answer) {
1781
+ formatted += `## Summary\n${result.answer}\n\n`;
1782
+ }
1783
+ if (result.search_results && result.search_results.length > 0) {
1784
+ formatted += '## Posts Found\n\n';
1785
+ result.search_results.forEach((post, i) => {
1786
+ formatted += `### ${i + 1}. ${post.author || 'Unknown'}\n`;
1787
+ if (post.snippet) formatted += `${post.snippet}\n`;
1788
+ if (post.url) formatted += `[View post](${post.url})\n`;
1789
+ if (post.date) formatted += `*${post.date}*\n`;
1790
+ formatted += '\n';
1791
+ });
1792
+ }
1793
+ if (result.using_free_tier) {
1794
+ formatted += `---\n*Free tier: ${result.free_searches_remaining} searches remaining of 50*\n`;
1795
+ }
1796
+ if (result.model) {
1797
+ formatted += `\n*Model: ${result.model} | Latency: ${result.latency_ms}ms*\n`;
1798
+ }
1799
+
1800
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: formatted }] } };
1801
+ } catch (error) {
1802
+ console.error('[Stdio Wrapper] X search error:', error.message);
1803
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: `X search failed: ${error.message}` }], isError: true } };
1804
+ }
1805
+ }
1806
+
1807
+ /**
1808
+ * Handle image generation tool locally — calls polydev.ai API
1809
+ */
1810
+ async handleGenerateImage(params, id) {
1811
+ const args = params.arguments || {};
1812
+ console.error('[Stdio Wrapper] Handling generate_image locally');
1813
+
1814
+ if (!args.prompt || typeof args.prompt !== 'string') {
1815
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Error: prompt is required and must be a string' }], isError: true } };
1816
+ }
1817
+
1818
+ const userToken = args.user_token || this.userToken;
1819
+ if (!userToken) {
1820
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: 'Authentication required for image generation.\nUse the "login" tool first, or pass user_token parameter.' }], isError: true } };
1821
+ }
1822
+
1823
+ try {
1824
+ const response = await fetch('https://polydev.ai/api/generate-image', {
1825
+ method: 'POST',
1826
+ headers: {
1827
+ 'Content-Type': 'application/json',
1828
+ 'Authorization': `Bearer ${userToken}`,
1829
+ 'User-Agent': 'polydev-stdio-wrapper/1.0.0'
1830
+ },
1831
+ body: JSON.stringify({
1832
+ prompt: args.prompt,
1833
+ user_token: userToken,
1834
+ provider: args.provider || 'openai',
1835
+ model: args.model,
1836
+ size: args.size || '1024x1024',
1837
+ quality: args.quality || 'auto'
1838
+ })
1839
+ });
1840
+
1841
+ if (!response.ok) {
1842
+ const errorData = await response.json().catch(() => ({}));
1843
+ if (response.status === 400 && errorData.setup_url) {
1844
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: `No ${errorData.provider || 'API'} key found for image generation.\n\nImage generation requires your own API key:\n1. Get an API key from OpenAI (https://platform.openai.com) or Google AI (https://aistudio.google.com)\n2. Add it at https://polydev.ai/dashboard/models\n\nSupported providers: OpenAI (gpt-image-1.5) and Google Gemini` }], isError: true } };
1845
+ }
1846
+ throw new Error(errorData.error || `Image generation failed: HTTP ${response.status}`);
1847
+ }
1848
+
1849
+ const result = await response.json();
1850
+
1851
+ // Save image to file if we have base64 data
1852
+ if (result.image_base64) {
1853
+ try {
1854
+ const timestamp = Date.now();
1855
+ const filename = `polydev-image-${timestamp}.png`;
1856
+ const outputDir = path.join(os.homedir(), '.polydev', 'images');
1857
+ if (!fs.existsSync(outputDir)) {
1858
+ fs.mkdirSync(outputDir, { recursive: true });
1859
+ }
1860
+ const outputPath = path.join(outputDir, filename);
1861
+ fs.writeFileSync(outputPath, Buffer.from(result.image_base64, 'base64'));
1862
+ result.saved_to = outputPath;
1863
+ console.error(`[Stdio Wrapper] Image saved to: ${outputPath}`);
1864
+ } catch (saveError) {
1865
+ console.error('[Stdio Wrapper] Failed to save image:', saveError.message);
1866
+ }
1867
+ }
1868
+
1869
+ // Format response
1870
+ let formatted = '# Image Generated\n\n';
1871
+ formatted += `**Provider**: ${result.provider || 'openai'}\n`;
1872
+ formatted += `**Model**: ${result.model || 'gpt-image-1.5'}\n`;
1873
+ if (result.size) formatted += `**Size**: ${result.size}\n`;
1874
+ if (result.revised_prompt) formatted += `**Revised prompt**: ${result.revised_prompt}\n`;
1875
+ if (result.text_response) formatted += `**Description**: ${result.text_response}\n`;
1876
+ if (result.saved_to) formatted += `\n**Saved to**: \`${result.saved_to}\`\n`;
1877
+ if (result.image_base64) formatted += `\nImage data: ${(result.image_base64.length / 1024).toFixed(0)}KB base64 PNG\n`;
1878
+ if (result.latency_ms) formatted += `\n*Latency: ${result.latency_ms}ms*\n`;
1879
+
1880
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: formatted }] } };
1881
+ } catch (error) {
1882
+ console.error('[Stdio Wrapper] Image generation error:', error.message);
1883
+ return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: `Image generation failed: ${error.message}` }], isError: true } };
1884
+ }
1885
+ }
1886
+
1733
1887
  /**
1734
1888
  * Check if a tool is a CLI tool that should be handled locally
1735
1889
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polydev-ai",
3
- "version": "1.10.1",
3
+ "version": "1.10.2",
4
4
  "engines": {
5
5
  "node": ">=20.x <=22.x"
6
6
  },