Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/akrindev_smeduverse-ai.json
T

1 line
6.2 KiB
JSON

{"repo": "akrindev/smeduverse-ai", "files": {"server/src/services/agent.ts": {"32e5e2667eb31f3ab2005e9a76d9fa001a60d667": {"t": 1785595257.7304523, "n": 5044, "h": "879db1dc01d08f33", "c": "import { ChatOpenAI } from \"@langchain/openai\";\nimport { MemorySaver, MessagesAnnotation, StateGraph } from \"@langchain/langgraph\";\nimport { ToolNode, toolsCondition } from \"@langchain/langgraph/prebuilt\";\nimport { MultiServerMCPClient } from \"@langchain/mcp-adapters\";\nimport { getSystemPrompt } from \"../prompts/system.js\";\n\n// Lazy initialization to avoid module-level crashes in serverless environments\nlet model: ChatOpenAI | null = null;\n\nfunction getModel(): ChatOpenAI {\n if (!model) {\n const OPENCODE_API_KEY = process.env.OPENCODE_API_KEY || \"\";\n const OPENCODE_API_BASE = process.env.OPENCODE_API_BASE || \"https://opencode.ai/zen/v1\";\n const OPENCODE_MODEL = process.env.OPENCODE_MODEL || \"mimo-v2.5-free\";\n\n if (!OPENCODE_API_KEY) {\n throw new Error(\"OPENCODE_API_KEY environment variable is required\");\n }\n\n model = new ChatOpenAI({\n model: OPENCODE_MODEL,\n apiKey: OPENCODE_API_KEY,\n configuration: {\n baseURL: OPENCODE_API_BASE,\n },\n temperature: 0.8,\n maxRetries: 12,\n });\n }\n return model;\n}\n\n// Lazy-initialize checkpointer to avoid module-level instantiation issues in serverless\nexport const checkpointer = new MemorySaver();\n\nconst DEFAULT_MCP_URL = \"http://localhost:2222/mcp/smeduverse\";\n\n// MCP client cache (initialized per server/key)\nlet mcpClient: MultiServerMCPClient | null = null;\nlet lastMcpKey: string | null = null;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet cachedTools: any[] = [];\n\nconst sanitizeServerUrl = (url: string) => url.trim().replace(/^\"|\"$/g, \"\").replace(/^'|'$/g, \"\");\n\nexport async function initializeMCPClient(mcpKey?: string) {\n try {\n if (mcpClient && (!mcpKey || mcpKey === lastMcpKey)) {\n return cachedTools;\n }\n\n // Determine the MCP server URL\n let serverUrl = process.env.MCP_SERVER_URL;\n\n // Optimization: In Vercel/Production, if no URL is explicitly provided, skip connection\n // This prevents hanging on localhost connections that will never succeed\n const isProduction = process.env.VERCEL === \"1\" || process.env.NODE_ENV === \"production\";\n\n if (!serverUrl) {\n if (isProduction) {\n console.log(\"No MCP_SERVER_URL provided in production environment. Skipping MCP connection.\");\n cachedTools = [];\n return cachedTools;\n }\n // Only default to localhost in local development\n serverUrl = DEFAULT_MCP_URL;\n }\n\n serverUrl = sanitizeServerUrl(serverUrl);\n console.log(`Connecting to MCP server at ${serverUrl}...`);\n\n // Build MCP server config with optional authentication\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const mcpConfig: any = {\n smeduverse: {\n url: serverUrl,\n transport: \"http\", // Explicitly use HTTP transport, not SSE\n automaticSSEFallback: false, // Disable SSE fallback since server is HTTP-only\n },\n };\n\n // Add authentication headers if mcpKey is provided\n if (mcpKey) {\n mcpConfig.smeduverse.headers = {\n Authorization: `Bearer ${mcpKey}`,\n };\n console.log(\n `Using authentication with MCP server (token length: ${mcpKey.length}, starts with: ${mcpKey.substring(0, 10)}...)`,\n );\n } else {\n console.log(`No MCP key provided, connecting without authentication`);\n }\n\n mcpClient = new MultiServerMCPClient({\n mcpServers: mcpConfig,\n });\n\n cachedTools = await mcpClient.getTools();\n lastMcpKey = mcpKey || null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n console.log(`MCP tools loaded: ${cachedTools.map((t: any) => t.name).join(\", \") || \"none\"}`);\n return cachedTools;\n } catch (error) {\n console.warn(\"Failed to connect to MCP server, continuing without tools:\", error);\n cachedTools = [];\n lastMcpKey = mcpKey || null;\n return cachedTools;\n }\n}\n\nconst createCallModel =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (availableTools: any[]) => async (state: typeof MessagesAnnotation.State) => {\n const systemMessage = {\n role: \"system\" as const,\n content: getSystemPrompt(),\n };\n const messagesWithSystem = [systemMessage, ...state.messages];\n\n // Bind tools if available\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let modelWithTools: any = getModel();\n if (availableTools.length > 0) {\n modelWithTools = getModel().bindTools(availableTools);\n }\n\n const response = await modelWithTools.invoke(messagesWithSystem);\n return { messages: [response] };\n };\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const createGraphWithTools = (availableTools: any[]) =>\n new StateGraph(MessagesAnnotation)\n .addNode(\"agent\", createCallModel(availableTools))\n .addNode(\"tools\", new ToolNode(availableTools))\n .addEdge(\"__start__\", \"agent\")\n .addConditionalEdges(\"agent\", toolsCondition, {\n tools: \"tools\",\n __end__: \"__end__\",\n })\n .addEdge(\"tools\", \"agent\")\n .compile({ checkpointer });\n"}}, ".env.example": {"32e5e2667eb31f3ab2005e9a76d9fa001a60d667": {"t": 1785595264.366677, "n": 735, "h": "3459b0c6979d90db", "c": "# Backend environment variables\nOPENCODE_API_KEY=your_opencode_api_key_here\nOPENCODE_API_BASE=https://opencode.ai/zen/v1\nOPENCODE_MODEL=mimo-v2.5-free\nMCP_SERVER_URL=http://localhost:2222/mcp/smeduverse\n\n# Frontend environment variables (must be prefixed with VITE_)\nVITE_API_ENDPOINT=http://localhost:3000/api/chat\nVITE_MCP_KEY_ENDPOINT=http://localhost:2222/mcp/key\n\n# Vercel deployment notes:\n# - Set GOOGLE_API_KEY in Vercel dashboard (Project Settings > Environment Variables)\n# - Set MCP_SERVER_URL to your production MCP server URL\n# - VITE_* variables are embedded at build time, update for production:\n# VITE_API_ENDPOINT=/api/chat (relative URL for same-origin)\n# VITE_MCP_KEY_ENDPOINT=https://your-mcp-server.com/mcp/key"}}}}