diff --git a/.vscode/HumanAgent-server.log b/.vscode/HumanAgent-server.log new file mode 100644 index 0000000..d0a1929 --- /dev/null +++ b/.vscode/HumanAgent-server.log @@ -0,0 +1,1445 @@ +[2025-10-23T02:09:15.305Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:09:15.306Z] Started server with PID 15753 +[2025-10-23T02:09:15.306Z] Server process spawned successfully +[2025-10-23T02:09:15.333Z] [STDOUT] [LOGGER] Attempting to create log file at: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[LOGGER] Cleared existing log file +[2025-10-23T02:09:15.335Z] [STDOUT] [DEBUG] Debug logging started at 2025-10-23T02:09:15.333Z +[DEBUG] Current system time: Thu Oct 23 2025 13:09:15 GMT+1100 (Australian Eastern Daylight Time) +[DEBUG] Log file: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[DEBUG] Working directory: /Users/benharper/Coding/HumanAgent-MCP/dist +[LOGGER] Debug logger initialized successfully +[INFO] McpServer initialized +[2025-10-23T02:09:15.335Z] [STDOUT] [INFO] === MCP SERVER STARTING === +[INFO] Starting HTTP server on port 3737... +[2025-10-23T02:09:15.342Z] [STDOUT] [INFO] MCP HTTP server running on http://127.0.0.1:3737/mcp +[2025-10-23T02:09:15.342Z] [STDOUT] {"type":"notification","method":"server/started","params":{"name":"HumanAgent MCP Server","version":"1.0.0","capabilities":{"chat":true,"tools":true,"resources":false}}} +[2025-10-23T02:09:15.342Z] [STDERR] HumanAgent MCP Server started successfully +[2025-10-23T02:09:18.310Z] Server started successfully and is responding +[2025-10-23T02:09:18.934Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:09:18.934Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[2025-10-23T02:09:18.935Z] [STDOUT] [HTTP] Handling POST request to /mcp +[2025-10-23T02:09:18.935Z] [STDOUT] [HTTP] Received chunk: 228 bytes +[2025-10-23T02:09:18.935Z] [STDOUT] [HTTP] Complete request body received (228 bytes) +[2025-10-23T02:09:18.935Z] [STDOUT] [HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[2025-10-23T02:09:18.935Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[2025-10-23T02:09:18.936Z] [STDOUT] [MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[2025-10-23T02:09:18.936Z] [STDOUT] [HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[2025-10-23T02:09:18.936Z] [STDOUT] [HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:09:18.945Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 1 +[2025-10-23T02:09:18.946Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 54 bytes +[HTTP] Complete request body received (54 bytes) +[HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[2025-10-23T02:09:18.946Z] [STDOUT] [HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[2025-10-23T02:09:18.946Z] [STDOUT] [MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Processing notifications/initialized (ignoring) +[HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:09:18.946Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 58 bytes +[HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[2025-10-23T02:09:18.946Z] [STDOUT] [TOOLS] Final sessionIdToUse: default +[2025-10-23T02:09:18.947Z] [STDOUT] [TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[2025-10-23T02:09:18.947Z] [STDOUT] [HTTP] Sending 200 response (1071 bytes) +[2025-10-23T02:09:20.320Z] [STDOUT] [HTTP] GET /sessions +[2025-10-23T02:09:20.321Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate' +} +[2025-10-23T02:09:20.326Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:09:20.326Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '82' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 82 bytes +[2025-10-23T02:09:20.326Z] [STDOUT] [HTTP] Complete request body received (82 bytes) +[HTTP] Request Body: {"sessionId":"session-a8f49eee-068c-42f1-b611-14651fa5ccc6","method":"tools/list"} +[HTTP] Parsed JSON message: { + sessionId: 'session-a8f49eee-068c-42f1-b611-14651fa5ccc6', + method: 'tools/list' +} +[MCP] Handling message: { + sessionId: 'session-a8f49eee-068c-42f1-b611-14651fa5ccc6', + method: 'tools/list' +} +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: undefined +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[2025-10-23T02:09:20.326Z] [STDOUT] [HTTP] Response from handleMessage: { id: undefined, type: 'response', result: { tools: [ [Object] ] } } +[HTTP] Sending 200 response (1064 bytes) +[2025-10-23T02:09:20.332Z] [STDOUT] [HTTP] POST /sessions/register +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '1794' +} +[2025-10-23T02:09:20.333Z] [STDOUT] [INFO] Initializing tools for session: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 from override data +[INFO] Override data received: {"version":"1.0.0","description":"HumanAgent MCP Tool Overrides for this workspace. Modify tool configurations below to customize MCP server behavior.","tools":{"HumanAgent_Chat":{"name":"HumanAgent_Chat","description":".Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.","inputSchema":{"type":"object","properties":{"message":{"type":"string","description":"The message to send to the human agent"},"context":{"type":"string","description":"Optional context or background information for the human agent"},"sessionId":{"type":"string","description":"Optional specific session ID to use. If not provided, a new session will be created."},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Priority level of the request","default":"normal"},"timeout":{"type":"number","description":"Timeout in seconds to wait for human response (default: 300)","default":300}},"required":["message"]}},"example_custom_tool":{"name":"example_custom_tool","description":"Brief description of what this tool does and its main purpose. Include key usage notes and important warnings when applicable.","inputSchema":{"type":"object","properties":{"input_param":{"type":"string","description":"What this parameter does and how it should be formatted"},"optional_param":{"type":"number","description":"Optional parameter with default behavior explained","default":100}},"required":["input_param"]}}}} +[2025-10-23T02:09:20.336Z] [STDOUT] [INFO] Added default tool: HumanAgent_Chat +[INFO] Applying 2 tool overrides for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 +[INFO] Processing override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - HumanAgent_Chat tool: {"name":"HumanAgent_Chat","description":".Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.","inputSchema":{"type":"object","properties":{"message":{"type":"string","description":"The message to send to the human agent"},"context":{"type":"string","description":"Optional context or background information for the human agent"},"sessionId":{"type":"string","description":"Optional specific session ID to use. If not provided, a new session will be created."},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Priority level of the request","default":"normal"},"timeout":{"type":"number","description":"Timeout in seconds to wait for human response (default: 300)","default":300}},"required":["message"]}} +[INFO] Processing override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - example_custom_tool tool: {"name":"example_custom_tool","description":"Brief description of what this tool does and its main purpose. Include key usage notes and important warnings when applicable.","inputSchema":{"type":"object","properties":{"input_param":{"type":"string","description":"What this parameter does and how it should be formatted"},"optional_param":{"type":"number","description":"Optional parameter with default behavior explained","default":100}},"required":["input_param"]}} +[INFO] Session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 tools initialized with 2 tools +[INFO] Session registered: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 (1 total sessions) +[2025-10-23T02:09:20.420Z] [STDOUT] [HTTP] OPTIONS /mcp +[2025-10-23T02:09:20.421Z] [STDOUT] [HTTP] Request Headers: { + host: 'localhost:3737', + connection: 'keep-alive', + accept: '*/*', + 'access-control-request-method': 'GET', + 'access-control-request-headers': 'cache-control', + origin: 'vscode-webview://06ntb21jilovkpqhp3n8qs6oen2rlig4drgi2amm3ehub2r9bg30', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.105.1 Chrome/138.0.7204.251 Electron/37.6.0 Safari/537.36', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + 'sec-fetch-dest': 'empty', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en-GB' +} +[2025-10-23T02:09:20.421Z] [STDOUT] [HTTP] Handling OPTIONS preflight request +[2025-10-23T02:09:20.423Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:09:20.423Z] [STDOUT] [HTTP] Request Headers: { + host: 'localhost:3737', + connection: 'keep-alive', + 'sec-ch-ua-platform': '"macOS"', + 'cache-control': 'no-cache', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.105.1 Chrome/138.0.7204.251 Electron/37.6.0 Safari/537.36', + accept: 'text/event-stream', + 'sec-ch-ua': '"Not)A;Brand";v="8", "Chromium";v="138"', + 'sec-ch-ua-mobile': '?0', + origin: 'vscode-webview://06ntb21jilovkpqhp3n8qs6oen2rlig4drgi2amm3ehub2r9bg30', + 'sec-fetch-site': 'cross-site', + 'sec-fetch-mode': 'cors', + 'sec-fetch-dest': 'empty', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en-GB' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 2 +[2025-10-23T02:09:21.763Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[2025-10-23T02:09:21.792Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[2025-10-23T02:09:21.793Z] [STDOUT] [HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 228 bytes +[2025-10-23T02:09:21.793Z] [STDOUT] [HTTP] Complete request body received (228 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[2025-10-23T02:09:21.793Z] [STDOUT] [MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[2025-10-23T02:09:21.793Z] [STDOUT] [HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[2025-10-23T02:09:21.793Z] [STDOUT] [HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:09:21.796Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 54 bytes +[HTTP] Complete request body received (54 bytes) +[HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[2025-10-23T02:09:21.796Z] [STDOUT] [MCP] Processing notifications/initialized (ignoring) +[HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:09:21.796Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 58 bytes +[HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[2025-10-23T02:09:21.796Z] [STDOUT] [MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[2025-10-23T02:09:21.797Z] [STDOUT] [MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[2025-10-23T02:09:21.797Z] [STDOUT] [HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[2025-10-23T02:09:21.797Z] [STDOUT] [HTTP] Sending 200 response (1071 bytes) +[2025-10-23T02:09:21.798Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 2 +[2025-10-23T02:09:28.714Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:09:28.714Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:09:29.715Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:09:29.716Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:30.680Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:09:30.681Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:09:38.325Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:09:38.326Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:39.069Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:09:39.069Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:09:47.580Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[2025-10-23T02:09:47.581Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:47.605Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:09:47.606Z] [STDOUT] [HTTP] Received chunk: 228 bytes +[HTTP] Complete request body received (228 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:09:47.610Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:09:47.615Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 58 bytes +[HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[HTTP] Sending 200 response (1071 bytes) +[HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 54 bytes +[HTTP] Complete request body received (54 bytes) +[HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Processing notifications/initialized (ignoring) +[HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:09:48.105Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:48.124Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:09:48.124Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:09:48.124Z] [STDOUT] [HTTP] Received chunk: 228 bytes +[HTTP] Complete request body received (228 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[2025-10-23T02:09:48.125Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[2025-10-23T02:09:48.125Z] [STDOUT] [HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:09:48.128Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 54 bytes +[HTTP] Complete request body received (54 bytes) +[HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Processing notifications/initialized (ignoring) +[HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:09:48.128Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 58 bytes +[HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[HTTP] Sending 200 response (1071 bytes) +[2025-10-23T02:09:48.129Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:09:50.764Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:09:50.764Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:50.765Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:09:51.558Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:09:51.559Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:10:03.616Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:10:19.592Z] [STDOUT] [HTTP] DELETE /sessions/unregister +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '60' +} +[2025-10-23T02:10:19.593Z] [STDOUT] [INFO] Session unregistered and cleaned up: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 (0 total sessions) +[2025-10-23T02:10:19.595Z] ServerManager disposed +[2025-10-23T02:10:19.595Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[2025-10-23T02:11:31.493Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:11:31.494Z] Started server with PID 16638 +[2025-10-23T02:11:31.494Z] Server process spawned successfully +[2025-10-23T02:11:31.520Z] [STDOUT] [LOGGER] Attempting to create log file at: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[LOGGER] Cleared existing log file +[2025-10-23T02:11:31.523Z] [STDOUT] [DEBUG] Debug logging started at 2025-10-23T02:11:31.521Z +[DEBUG] Current system time: Thu Oct 23 2025 13:11:31 GMT+1100 (Australian Eastern Daylight Time) +[DEBUG] Log file: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[DEBUG] Working directory: /Users/benharper/Coding/HumanAgent-MCP/dist +[LOGGER] Debug logger initialized successfully +[2025-10-23T02:11:31.523Z] [STDOUT] [INFO] McpServer initialized +[2025-10-23T02:11:31.524Z] [STDOUT] [INFO] === MCP SERVER STARTING === +[INFO] Starting HTTP server on port 3737... +[2025-10-23T02:11:31.533Z] [STDOUT] [INFO] MCP HTTP server running on http://127.0.0.1:3737/mcp +{"type":"notification","method":"server/started","params":{"name":"HumanAgent MCP Server","version":"1.0.0","capabilities":{"chat":true,"tools":true,"resources":false}}} +[2025-10-23T02:11:31.533Z] [STDERR] HumanAgent MCP Server started successfully +[2025-10-23T02:11:34.496Z] Server started successfully and is responding +[2025-10-23T02:11:36.515Z] [STDOUT] [HTTP] GET /sessions +[2025-10-23T02:11:36.516Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate' +} +[2025-10-23T02:11:36.524Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '82' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:11:36.526Z] [STDOUT] [HTTP] Received chunk: 82 bytes +[HTTP] Complete request body received (82 bytes) +[HTTP] Request Body: {"sessionId":"session-a8f49eee-068c-42f1-b611-14651fa5ccc6","method":"tools/list"} +[HTTP] Parsed JSON message: { + sessionId: 'session-a8f49eee-068c-42f1-b611-14651fa5ccc6', + method: 'tools/list' +} +[MCP] Handling message: { + sessionId: 'session-a8f49eee-068c-42f1-b611-14651fa5ccc6', + method: 'tools/list' +} +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: undefined +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[HTTP] Response from handleMessage: { id: undefined, type: 'response', result: { tools: [ [Object] ] } } +[2025-10-23T02:11:36.527Z] [STDOUT] [HTTP] Sending 200 response (1064 bytes) +[2025-10-23T02:11:36.532Z] [STDOUT] [HTTP] POST /sessions/register +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '1794' +} +[INFO] Initializing tools for session: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 from override data +[INFO] Override data received: {"version":"1.0.0","description":"HumanAgent MCP Tool Overrides for this workspace. Modify tool configurations below to customize MCP server behavior.","tools":{"HumanAgent_Chat":{"name":"HumanAgent_Chat","description":".Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.","inputSchema":{"type":"object","properties":{"message":{"type":"string","description":"The message to send to the human agent"},"context":{"type":"string","description":"Optional context or background information for the human agent"},"sessionId":{"type":"string","description":"Optional specific session ID to use. If not provided, a new session will be created."},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Priority level of the request","default":"normal"},"timeout":{"type":"number","description":"Timeout in seconds to wait for human response (default: 300)","default":300}},"required":["message"]}},"example_custom_tool":{"name":"example_custom_tool","description":"Brief description of what this tool does and its main purpose. Include key usage notes and important warnings when applicable.","inputSchema":{"type":"object","properties":{"input_param":{"type":"string","description":"What this parameter does and how it should be formatted"},"optional_param":{"type":"number","description":"Optional parameter with default behavior explained","default":100}},"required":["input_param"]}}}} +[INFO] Added default tool: HumanAgent_Chat +[INFO] Applying 2 tool overrides for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 +[INFO] Processing override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - HumanAgent_Chat tool: {"name":"HumanAgent_Chat","description":".Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.","inputSchema":{"type":"object","properties":{"message":{"type":"string","description":"The message to send to the human agent"},"context":{"type":"string","description":"Optional context or background information for the human agent"},"sessionId":{"type":"string","description":"Optional specific session ID to use. If not provided, a new session will be created."},"priority":{"type":"string","enum":["low","normal","high","urgent"],"description":"Priority level of the request","default":"normal"},"timeout":{"type":"number","description":"Timeout in seconds to wait for human response (default: 300)","default":300}},"required":["message"]}} +[INFO] Processing override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - example_custom_tool tool: {"name":"example_custom_tool","description":"Brief description of what this tool does and its main purpose. Include key usage notes and important warnings when applicable.","inputSchema":{"type":"object","properties":{"input_param":{"type":"string","description":"What this parameter does and how it should be formatted"},"optional_param":{"type":"number","description":"Optional parameter with default behavior explained","default":100}},"required":["input_param"]}} +[2025-10-23T02:11:36.532Z] [STDOUT] [INFO] Session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 tools initialized with 2 tools +[INFO] Session registered: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 (1 total sessions) +[2025-10-23T02:11:36.577Z] [STDOUT] [HTTP] OPTIONS /mcp +[2025-10-23T02:11:36.577Z] [STDOUT] [HTTP] Request Headers: { + host: 'localhost:3737', + connection: 'keep-alive', + accept: '*/*', + 'access-control-request-method': 'GET', + 'access-control-request-headers': 'cache-control', + origin: 'vscode-webview://06ntb21jilovkpqhp3n8qs6oen2rlig4drgi2amm3ehub2r9bg30', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.105.1 Chrome/138.0.7204.251 Electron/37.6.0 Safari/537.36', + 'sec-fetch-mode': 'cors', + 'sec-fetch-site': 'cross-site', + 'sec-fetch-dest': 'empty', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en-GB' +} +[2025-10-23T02:11:36.577Z] [STDOUT] [HTTP] Handling OPTIONS preflight request +[2025-10-23T02:11:36.577Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:11:36.578Z] [STDOUT] [HTTP] Request Headers: { + host: 'localhost:3737', + connection: 'keep-alive', + 'sec-ch-ua-platform': '"macOS"', + 'cache-control': 'no-cache', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.105.1 Chrome/138.0.7204.251 Electron/37.6.0 Safari/537.36', + accept: 'text/event-stream', + 'sec-ch-ua': '"Not)A;Brand";v="8", "Chromium";v="138"', + 'sec-ch-ua-mobile': '?0', + origin: 'vscode-webview://06ntb21jilovkpqhp3n8qs6oen2rlig4drgi2amm3ehub2r9bg30', + 'sec-fetch-site': 'cross-site', + 'sec-fetch-mode': 'cors', + 'sec-fetch-dest': 'empty', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en-GB' +} +[2025-10-23T02:11:36.578Z] [STDOUT] [HTTP] Handling GET request to /mcp +[2025-10-23T02:11:36.578Z] [STDOUT] [HTTP] Setting up SSE stream for GET request +[2025-10-23T02:11:36.578Z] [STDOUT] [HTTP] Added SSE connection. Total connections: 1 +[2025-10-23T02:11:45.695Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:11:45.695Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 2 +[2025-10-23T02:13:37.886Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:13:37.887Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 228 bytes +[2025-10-23T02:13:37.887Z] [STDOUT] [HTTP] Complete request body received (228 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[2025-10-23T02:13:37.888Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[2025-10-23T02:13:37.888Z] [STDOUT] [MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:13:37.895Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:13:37.897Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:13:37.897Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[2025-10-23T02:13:37.897Z] [STDOUT] [HTTP] Handling POST request to /mcp +[2025-10-23T02:13:37.897Z] [STDOUT] [HTTP] Received chunk: 54 bytes +[2025-10-23T02:13:37.897Z] [STDOUT] [HTTP] Complete request body received (54 bytes) +[2025-10-23T02:13:37.898Z] [STDOUT] [HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Processing notifications/initialized (ignoring) +[2025-10-23T02:13:37.898Z] [STDOUT] [HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:13:37.898Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:13:37.898Z] [STDOUT] [HTTP] Received chunk: 58 bytes +[2025-10-23T02:13:37.899Z] [STDOUT] [HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[2025-10-23T02:13:37.899Z] [STDOUT] [HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[2025-10-23T02:13:37.899Z] [STDOUT] [HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[2025-10-23T02:13:37.899Z] [STDOUT] [HTTP] Sending 200 response (1071 bytes) +[2025-10-23T02:13:40.482Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:13:40.524Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '228' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:13:40.524Z] [STDOUT] [HTTP] Received chunk: 228 bytes +[2025-10-23T02:13:40.524Z] [STDOUT] [HTTP] Complete request body received (228 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{"roots":{"listChanged":true},"sampling":{},"elicitation":{}},"clientInfo":{"name":"Visual Studio Code","version":"1.105.1"}}} +[2025-10-23T02:13:40.524Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Handling message: { + jsonrpc: '2.0', + id: 1, + method: 'initialize', + params: { + protocolVersion: '2025-06-18', + capabilities: { roots: [Object], sampling: {}, elicitation: {} }, + clientInfo: { name: 'Visual Studio Code', version: '1.105.1' } + } +} +[MCP] Processing initialize request +[2025-10-23T02:13:40.524Z] [STDOUT] [HTTP] Response from handleMessage: { + id: 1, + type: 'response', + result: { + protocolVersion: '2024-11-05', + capabilities: { chat: true, tools: true, resources: false }, + serverInfo: { name: 'HumanAgent MCP Server', version: '1.0.0' } + } +} +[HTTP] Sending 200 response (192 bytes) +[2025-10-23T02:13:40.527Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:13:40.528Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + accept: 'text/event-stream', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate' +} +[2025-10-23T02:13:40.528Z] [STDOUT] [HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:13:40.530Z] [STDOUT] [HTTP] POST /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '54' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 54 bytes +[HTTP] Complete request body received (54 bytes) +[HTTP] Request Body: {"method":"notifications/initialized","jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Handling message: { method: 'notifications/initialized', jsonrpc: '2.0' } +[MCP] Processing notifications/initialized (ignoring) +[HTTP] Response from handleMessage: +[HTTP] Sending 202 response (no content) +[2025-10-23T02:13:40.530Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:13:40.530Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '58' +} +[2025-10-23T02:13:40.531Z] [STDOUT] [HTTP] Handling POST request to /mcp +[2025-10-23T02:13:40.531Z] [STDOUT] [HTTP] Received chunk: 58 bytes +[2025-10-23T02:13:40.531Z] [STDOUT] [HTTP] Complete request body received (58 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} +[HTTP] Parsed JSON message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[2025-10-23T02:13:40.531Z] [STDOUT] [MCP] Handling message: { jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} } +[MCP] Processing tools/list request +[TOOLS] tools/list request - Extension sessionId: undefined, Message params: {} +[TOOLS] Final sessionIdToUse: default +[TOOLS] Returning 1 tools for session: default +[TOOLS] Using default tools (no session ID available) +[2025-10-23T02:13:40.531Z] [STDOUT] [HTTP] Response from handleMessage: { id: 2, type: 'response', result: { tools: [ [Object] ] } } +[HTTP] Sending 200 response (1071 bytes) +[2025-10-23T02:13:46.598Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:13:46.599Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:13:47.227Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:13:47.228Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:13:49.914Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:13:49.915Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:13:50.689Z] [STDOUT] [HTTP] GET /mcp +[2025-10-23T02:13:50.690Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:13:51.870Z] [STDOUT] [HTTP] SSE connection closed +[2025-10-23T02:13:51.872Z] [STDOUT] [HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:13:51.876Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:14:23.335Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:14:23.335Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '607' +} +[HTTP] Handling POST request to /mcp +[2025-10-23T02:14:23.335Z] [STDOUT] [HTTP] Received chunk: 607 bytes +[HTTP] Complete request body received (607 bytes) +[HTTP] Request Body: {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"HumanAgent_Chat","arguments":{"message":"Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?","context":"Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature","priority":"normal"},"_meta":{"progressToken":"195ba55d-5de7-4ce3-9569-1bb2890b2620","vscode.conversationId":"083210a2-6e17-433e-a123-7881f595f53f","vscode.requestId":"cc31720f-85a9-4f81-b5d4-e4f6fddb82e0"}}} +[2025-10-23T02:14:23.336Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 3, + method: 'tools/call', + params: { + name: 'HumanAgent_Chat', + arguments: { + message: "Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature', + priority: 'normal' + }, + _meta: { + progressToken: '195ba55d-5de7-4ce3-9569-1bb2890b2620', + 'vscode.conversationId': '083210a2-6e17-433e-a123-7881f595f53f', + 'vscode.requestId': 'cc31720f-85a9-4f81-b5d4-e4f6fddb82e0' + } + } +} +[2025-10-23T02:14:23.336Z] [STDOUT] [MCP] Handling message: { + jsonrpc: '2.0', + id: 3, + method: 'tools/call', + params: { + name: 'HumanAgent_Chat', + arguments: { + message: "Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature', + priority: 'normal' + }, + _meta: { + progressToken: '195ba55d-5de7-4ce3-9569-1bb2890b2620', + 'vscode.conversationId': '083210a2-6e17-433e-a123-7881f595f53f', + 'vscode.requestId': 'cc31720f-85a9-4f81-b5d4-e4f6fddb82e0' + } + } +} +[2025-10-23T02:14:23.336Z] [STDOUT] [MCP] Processing tools/call request for tool: HumanAgent_Chat +[2025-10-23T02:14:23.337Z] [STDOUT] [MCP] Tool call - name: "HumanAgent_Chat", session: undefined { + name: 'HumanAgent_Chat', + args: { + message: "Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature', + priority: 'normal' + } +} +[MCP] Available tools for session default: [ 'HumanAgent_Chat' ] +[MCP] Executing HumanAgent_Chat tool +[TOOL] HumanAgent_Chat called with params: { + message: "Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature', + priority: 'normal' +} +[TOOL] Using timeout: 300000ms (300s) +[TOOL] Generated request ID: 3-1761185663337 +[TOOL] Displaying message in chat UI: Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature + +Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation? +[SSE] Forwarding human-agent-request to SSE connections +[2025-10-23T02:14:23.338Z] [STDOUT] [SSE] Broadcasting to 2 SSE connections: {"type":"human-agent-request","data":{"requestId":"3-1761185663337","message":"Hey Ben! I see you're trying to use the human agent chat. What's on your mind? Are you looking to test the functionality, discuss the project, or just have a conversation?","context":"Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat feature","priority":"normal","timestamp":"2025-10-23T02:14:23.337Z"}} +[TOOL] Request 3-1761185663337 waiting for human response... +[2025-10-23T02:16:31.096Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:16:31.097Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '77' +} +[HTTP] Handling POST request to /mcp +[HTTP] Received chunk: 77 bytes +[HTTP] Complete request body received (77 bytes) +[HTTP] Request Body: {"method":"notifications/cancelled","params":{"requestId":3},"jsonrpc":"2.0"} +[HTTP] Parsed JSON message: { + method: 'notifications/cancelled', + params: { requestId: 3 }, + jsonrpc: '2.0' +} +[2025-10-23T02:16:31.097Z] [STDOUT] [MCP] Handling message: { + method: 'notifications/cancelled', + params: { requestId: 3 }, + jsonrpc: '2.0' +} +[MCP] Unknown method: notifications/cancelled +[HTTP] Response from handleMessage: { + id: undefined, + type: 'response', + error: { code: -32601, message: 'Method notifications/cancelled not found' } +} +[HTTP] Sending 200 response (96 bytes) +[2025-10-23T02:17:42.027Z] [STDOUT] [HTTP] POST /mcp +[2025-10-23T02:17:42.027Z] [STDOUT] [HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: 'text/event-stream, application/json', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'undici', + 'accept-encoding': 'gzip, deflate', + 'content-length': '631' +} +[2025-10-23T02:17:42.027Z] [STDOUT] [HTTP] Handling POST request to /mcp +[2025-10-23T02:17:42.028Z] [STDOUT] [HTTP] Received chunk: 631 bytes +[2025-10-23T02:17:42.028Z] [STDOUT] [HTTP] Complete request body received (631 bytes) +[2025-10-23T02:17:42.028Z] [STDOUT] [HTTP] Request Body: {"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"HumanAgent_Chat","arguments":{"message":"Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!","context":"Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality","priority":"normal"},"_meta":{"progressToken":"1ec26a86-b7c7-4d0a-904f-d2af07264355","vscode.conversationId":"083210a2-6e17-433e-a123-7881f595f53f","vscode.requestId":"09f9333d-b495-46e1-a937-65e985db3511"}}} +[2025-10-23T02:17:42.028Z] [STDOUT] [HTTP] Parsed JSON message: { + jsonrpc: '2.0', + id: 4, + method: 'tools/call', + params: { + name: 'HumanAgent_Chat', + arguments: { + message: "Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality', + priority: 'normal' + }, + _meta: { + progressToken: '1ec26a86-b7c7-4d0a-904f-d2af07264355', + 'vscode.conversationId': '083210a2-6e17-433e-a123-7881f595f53f', + 'vscode.requestId': '09f9333d-b495-46e1-a937-65e985db3511' + } + } +} +[2025-10-23T02:17:42.028Z] [STDOUT] [MCP] Handling message: { + jsonrpc: '2.0', + id: 4, + method: 'tools/call', + params: { + name: 'HumanAgent_Chat', + arguments: { + message: "Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality', + priority: 'normal' + }, + _meta: { + progressToken: '1ec26a86-b7c7-4d0a-904f-d2af07264355', + 'vscode.conversationId': '083210a2-6e17-433e-a123-7881f595f53f', + 'vscode.requestId': '09f9333d-b495-46e1-a937-65e985db3511' + } + } +} +[2025-10-23T02:17:42.029Z] [STDOUT] [MCP] Processing tools/call request for tool: HumanAgent_Chat +[2025-10-23T02:17:42.029Z] [STDOUT] [MCP] Tool call - name: "HumanAgent_Chat", session: undefined { + name: 'HumanAgent_Chat', + args: { + message: "Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality', + priority: 'normal' + } +} +[2025-10-23T02:17:42.029Z] [STDOUT] [MCP] Available tools for session default: [ 'HumanAgent_Chat' ] +[2025-10-23T02:17:42.029Z] [STDOUT] [MCP] Executing HumanAgent_Chat tool +[2025-10-23T02:17:42.029Z] [STDOUT] [TOOL] HumanAgent_Chat called with params: { + message: "Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!", + context: 'Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality', + priority: 'normal' +} +[TOOL] Using timeout: 300000ms (300s) +[2025-10-23T02:17:42.029Z] [STDOUT] [TOOL] Generated request ID: 4-1761185862029 +[TOOL] Displaying message in chat UI: Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality + +Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like! +[SSE] Forwarding human-agent-request to SSE connections +[2025-10-23T02:17:42.030Z] [STDOUT] [SSE] Broadcasting to 2 SSE connections: {"type":"human-agent-request","data":{"requestId":"4-1761185862029","message":"Hey Ben! Your MCP server is running and I'm here to chat. What's on your mind today? We could discuss your HumanAgent MCP project, test the functionality, or talk about whatever you'd like!","context":"Ben is working on his HumanAgent MCP VS Code extension project and wants to use the human agent chat functionality","priority":"normal","timestamp":"2025-10-23T02:17:42.029Z"}} +[2025-10-23T02:17:42.030Z] [STDOUT] [TOOL] Request 4-1761185862029 waiting for human response... +[2025-10-23T02:19:23.337Z] [STDOUT] [TOOL] Request 3-1761185663337 timed out after 300s +[2025-10-23T02:19:23.337Z] [STDOUT] [HTTP] Response from handleMessage: { + id: 3, + type: 'response', + error: { code: -32603, message: 'Human response timeout after 300 seconds' } +} +[HTTP] Sending 200 response (103 bytes) +[2025-10-23T02:20:25.805Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 3 +[2025-10-23T02:20:26.438Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 2 +[2025-10-23T02:20:57.739Z] [STDOUT] [HTTP] DELETE /sessions/unregister +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'content-type': 'application/json', + accept: '*/*', + 'accept-language': '*', + 'sec-fetch-mode': 'cors', + 'user-agent': 'node', + 'accept-encoding': 'gzip, deflate', + 'content-length': '60' +} +[INFO] Session unregistered and cleaned up: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 (0 total sessions) +[2025-10-23T02:20:57.741Z] ServerManager disposed +[2025-10-23T02:20:57.748Z] [STDOUT] [HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[HTTP] SSE connection closed +[HTTP] Removed SSE connection. Total connections: 1 +[2025-10-23T02:22:34.332Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:22:34.333Z] Started server with PID 19958 +[2025-10-23T02:22:34.333Z] Server process spawned successfully +[2025-10-23T02:22:34.380Z] [STDOUT] [LOGGER] Attempting to create log file at: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[LOGGER] Cleared existing log file +[DEBUG] Debug logging started at 2025-10-23T02:22:34.360Z +[DEBUG] Current system time: Thu Oct 23 2025 13:22:34 GMT+1100 (Australian Eastern Daylight Time) +[DEBUG] Log file: /var/folders/l9/1r1f80gj6jz4zslg_fns0tyw0000gn/T/HumanAgent.log +[DEBUG] Working directory: /Users/benharper/Coding/HumanAgent-MCP/dist +[LOGGER] Debug logger initialized successfully +[INFO] McpServer initialized +[INFO] === MCP SERVER STARTING === +[INFO] Starting HTTP server on port 3737... +[INFO] MCP HTTP server running on http://127.0.0.1:3737/mcp +{"type":"notification","method":"server/started","params":{"name":"HumanAgent MCP Server","version":"1.0.0","capabilities":{"chat":true,"tools":true,"resources":false}}} +[2025-10-23T02:22:34.380Z] [STDERR] HumanAgent MCP Server started successfully +[2025-10-23T02:22:35.687Z] [STDOUT] [HTTP] GET /mcp +[HTTP] Request Headers: { + host: '127.0.0.1:3737', + connection: 'keep-alive', + 'cache-control': 'max-age=0', + 'sec-ch-ua': '"Google Chrome";v="141", "Not?A_Brand";v="8", "Chromium";v="141"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-platform': '"macOS"', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36', + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-encoding': 'gzip, deflate, br, zstd', + 'accept-language': 'en,en-US;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6' +} +[HTTP] Handling GET request to /mcp +[HTTP] Setting up SSE stream for GET request +[HTTP] Added SSE connection. Total connections: 1 +[2025-10-23T02:22:37.338Z] Server started successfully and is responding +[2025-10-23T02:27:26.490Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:27:26.491Z] Started independent server with PID 20918 +[2025-10-23T02:27:26.491Z] Server process started as independent background process +[2025-10-23T02:27:29.505Z] Independent server started successfully and is responding +[2025-10-23T02:27:29.509Z] Server started successfully and is responding +[2025-10-23T02:27:33.413Z] ServerManager disposed +[2025-10-23T02:33:29.924Z] ServerManager disposed +[2025-10-23T02:39:00.691Z] ServerManager disposed +[2025-10-23T02:42:11.163Z] ServerManager disposed +[2025-10-23T02:47:48.817Z] Stopping independent server with PID 20918 +[2025-10-23T02:47:50.824Z] Force killing independent server with PID 20918 +[2025-10-23T02:47:51.831Z] Server stop operation completed +[2025-10-23T02:47:56.847Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:47:56.849Z] Started independent server with PID 27165 +[2025-10-23T02:47:56.849Z] Server process started as independent background process +[2025-10-23T02:47:59.856Z] Independent server started successfully and is responding +[2025-10-23T02:47:59.858Z] Server started successfully and is responding +[2025-10-23T02:48:03.884Z] Stopping independent server with PID 27165 +[2025-10-23T02:48:05.886Z] Force killing independent server with PID 27165 +[2025-10-23T02:48:06.893Z] Server stop operation completed +[2025-10-23T02:48:11.335Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:48:11.337Z] Started independent server with PID 27245 +[2025-10-23T02:48:11.337Z] Server process started as independent background process +[2025-10-23T02:48:14.340Z] Independent server started successfully and is responding +[2025-10-23T02:48:14.341Z] Server started successfully and is responding +[2025-10-23T02:49:21.944Z] ServerManager disposed +[2025-10-23T02:49:25.663Z] Found running server process with PID 27245, but it's not responding on port. Waiting... +[2025-10-23T02:49:27.718Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:49:27.719Z] Started independent server with PID 27693 +[2025-10-23T02:49:27.719Z] Server process started as independent background process +[2025-10-23T02:49:30.727Z] Independent server started successfully and is responding +[2025-10-23T02:49:30.733Z] Server started successfully and is responding +[2025-10-23T02:56:48.057Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T02:56:48.058Z] Started independent server with PID 30014 +[2025-10-23T02:56:48.058Z] Server process started as independent background process +[2025-10-23T02:56:51.064Z] Independent server started successfully and is responding +[2025-10-23T02:56:51.070Z] Server started successfully and is responding +[2025-10-23T03:05:44.663Z] ServerManager disposed +[2025-10-23T03:06:08.582Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:06:08.583Z] Started independent server with PID 33089 +[2025-10-23T03:06:08.583Z] Server process started as independent background process +[2025-10-23T03:06:11.588Z] Independent server started successfully and is responding +[2025-10-23T03:06:11.592Z] Server started successfully and is responding +[2025-10-23T03:07:33.871Z] ServerManager disposed +[2025-10-23T03:08:20.397Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:08:20.399Z] Started independent server with PID 33742 +[2025-10-23T03:08:20.399Z] Server process started as independent background process +[2025-10-23T03:08:23.404Z] Independent server started successfully and is responding +[2025-10-23T03:08:23.408Z] Server started successfully and is responding +[2025-10-23T03:09:55.946Z] ServerManager disposed +[2025-10-23T03:10:00.928Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:10:00.930Z] Started independent server with PID 34477 +[2025-10-23T03:10:00.930Z] Server process started as independent background process +[2025-10-23T03:10:03.934Z] Independent server started successfully and is responding +[2025-10-23T03:10:03.938Z] Server started successfully and is responding +[2025-10-23T03:14:10.974Z] ServerManager disposed +[2025-10-23T03:14:15.341Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:14:15.342Z] Started independent server with PID 35896 +[2025-10-23T03:14:15.342Z] Server process started as independent background process +[2025-10-23T03:14:18.346Z] Independent server started successfully and is responding +[2025-10-23T03:14:18.351Z] Server started successfully and is responding +[2025-10-23T03:16:35.656Z] Stopping independent server with PID 35896 +[2025-10-23T03:16:37.663Z] Force killing independent server with PID 35896 +[2025-10-23T03:16:38.668Z] Server stop operation completed +[2025-10-23T03:16:45.994Z] ServerManager disposed +[2025-10-23T03:16:50.366Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:16:50.367Z] Started independent server with PID 36825 +[2025-10-23T03:16:50.367Z] Server process started as independent background process +[2025-10-23T03:16:53.370Z] Independent server started successfully and is responding +[2025-10-23T03:16:53.375Z] Server started successfully and is responding +[2025-10-23T03:24:32.636Z] ServerManager disposed +[2025-10-23T03:24:36.038Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:24:36.040Z] Started independent server with PID 39311 +[2025-10-23T03:24:36.040Z] Server process started as independent background process +[2025-10-23T03:24:39.046Z] Independent server started successfully and is responding +[2025-10-23T03:24:39.050Z] Server started successfully and is responding +[2025-10-23T03:30:51.677Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:30:51.678Z] Started independent server with PID 41061 +[2025-10-23T03:30:51.678Z] Server process started as independent background process +[2025-10-23T03:30:54.679Z] Independent server started successfully and is responding +[2025-10-23T03:30:54.686Z] Server started successfully and is responding +[2025-10-23T03:33:31.917Z] ServerManager disposed +[2025-10-23T03:33:35.888Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:33:35.890Z] Started independent server with PID 41988 +[2025-10-23T03:33:35.890Z] Server process started as independent background process +[2025-10-23T03:33:38.892Z] Independent server started successfully and is responding +[2025-10-23T03:33:38.896Z] Server started successfully and is responding +[2025-10-23T03:33:42.352Z] ServerManager disposed +[2025-10-23T03:34:17.431Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:34:17.432Z] Started independent server with PID 42203 +[2025-10-23T03:34:17.432Z] Server process started as independent background process +[2025-10-23T03:34:20.436Z] Independent server started successfully and is responding +[2025-10-23T03:34:20.441Z] Server started successfully and is responding +[2025-10-23T03:36:00.692Z] ServerManager disposed +[2025-10-23T03:36:04.977Z] Starting new server process: node /Users/benharper/Coding/HumanAgent-MCP/dist/mcpStandalone.js +[2025-10-23T03:36:04.978Z] Started independent server with PID 43088 +[2025-10-23T03:36:04.978Z] Server process started as independent background process +[2025-10-23T03:36:07.981Z] Independent server started successfully and is responding +[2025-10-23T03:36:17.577Z] ServerManager disposed diff --git a/.vscode/HumanAgent.log b/.vscode/HumanAgent.log index a30e1a9..672a3df 100644 --- a/.vscode/HumanAgent.log +++ b/.vscode/HumanAgent.log @@ -93,3 +93,90 @@ } } [2025-10-22T23:05:29.893Z] [HTTP] Sending 200 response (1085 bytes) +[2025-10-22T23:17:53.136Z] [HTTP] POST /mcp +[2025-10-22T23:17:53.140Z] [HTTP] Request Headers: +{ + "host": "localhost:3737", + "user-agent": "curl/8.7.1", + "accept": "*/*", + "content-type": "application/json", + "content-length": "72" +} +[2025-10-22T23:17:53.142Z] [HTTP] Handling POST request to /mcp +[2025-10-22T23:17:53.143Z] [HTTP] Received chunk: 72 bytes +[2025-10-22T23:17:53.144Z] [HTTP] Complete request body received (72 bytes) +[2025-10-22T23:17:53.144Z] [HTTP] Request Body: +"{\"jsonrpc\":\"2.0\",\"id\":\"test-override\",\"method\":\"tools/list\",\"params\":{}}" +[2025-10-22T23:17:53.144Z] [HTTP] Parsed JSON message: +{ + "jsonrpc": "2.0", + "id": "test-override", + "method": "tools/list", + "params": {} +} +[2025-10-22T23:17:53.144Z] [MCP] Handling message: +{ + "jsonrpc": "2.0", + "id": "test-override", + "method": "tools/list", + "params": {} +} +[2025-10-22T23:17:53.145Z] [MCP] Processing tools/list request +[2025-10-22T23:17:53.146Z] [TOOLS] Returning 1 default tools +[2025-10-22T23:17:53.147Z] [HTTP] Response from handleMessage: +{ + "id": "test-override", + "type": "response", + "result": { + "tools": [ + { + "name": "HumanAgent_Chat", + "description": "Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.", + "inputSchema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "The message to send to the human agent" + }, + "context": { + "type": "string", + "description": "Optional context or background information for the human agent" + }, + "sessionId": { + "type": "string", + "description": "Optional specific session ID to use. If not provided, a new session will be created." + }, + "priority": { + "type": "string", + "enum": [ + "low", + "normal", + "high", + "urgent" + ], + "description": "Priority level of the request", + "default": "normal" + }, + "timeout": { + "type": "number", + "description": "Timeout in seconds to wait for human response (default: 300)", + "default": 300 + } + }, + "required": [ + "message" + ] + } + } + ] + } +} +[2025-10-22T23:17:53.147Z] [HTTP] Sending 200 response (1085 bytes) +[2025-10-22T23:17:58.664Z] [HTTP] GET /sessions +[2025-10-22T23:17:58.665Z] [HTTP] Request Headers: +{ + "host": "localhost:3737", + "user-agent": "curl/8.7.1", + "accept": "*/*" +} diff --git a/.vscode/HumanAgentOverride.json b/.vscode/HumanAgentOverride.json index 7eec2b4..a7da56a 100644 --- a/.vscode/HumanAgentOverride.json +++ b/.vscode/HumanAgentOverride.json @@ -4,7 +4,7 @@ "tools": { "HumanAgent_Chat": { "name": "HumanAgent_Chat", - "description": ".Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.", + "description": "..Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.", "inputSchema": { "type": "object", "properties": { diff --git a/package.json b/package.json index d043129..bcaa99b 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,21 @@ "command": "humanagent-mcp.configureMcp", "title": "Configure MCP Server", "icon": "$(settings-gear)" + }, + { + "command": "humanagent-mcp.startServer", + "title": "Start MCP Server", + "icon": "$(play)" + }, + { + "command": "humanagent-mcp.stopServer", + "title": "Stop MCP Server", + "icon": "$(stop)" + }, + { + "command": "humanagent-mcp.restartServer", + "title": "Restart MCP Server", + "icon": "$(debug-restart)" } ], "viewsContainers": { diff --git a/src/extension.ts b/src/extension.ts index aee9146..90aff61 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,17 +2,16 @@ import * as vscode from 'vscode'; import * as path from 'path'; import * as net from 'net'; import * as crypto from 'crypto'; -import { spawn, ChildProcess } from 'child_process'; -import { McpServer } from './mcp/server'; +import { spawn } from 'child_process'; import { ChatTreeProvider } from './providers/chatTreeProvider'; import { ChatWebviewProvider } from './webview/chatWebviewProvider'; import { McpConfigManager } from './mcp/mcpConfigManager'; +import { ServerManager } from './serverManager'; -let mcpServer: McpServer; let chatTreeProvider: ChatTreeProvider; let mcpConfigManager: McpConfigManager; -let standaloneServerProcess: ChildProcess | undefined; let workspaceSessionId: string; +let serverManager: ServerManager; // Generate or retrieve persistent workspace session ID function getWorkspaceSessionId(context: vscode.ExtensionContext): string { @@ -45,14 +44,17 @@ export async function activate(context: vscode.ExtensionContext) { const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; mcpConfigManager = new McpConfigManager(workspaceRoot, context.extensionPath); - // Initialize MCP Server (internal to extension) - mcpServer = new McpServer(workspaceSessionId, workspaceRoot); - - // Auto-detect and start MCP server if already configured - await autoStartMcpServer(mcpConfigManager, mcpServer, workspaceSessionId); + // Initialize Server Manager + const serverPath = path.join(context.extensionPath, 'dist', 'mcpStandalone.js'); + serverManager = ServerManager.getInstance({ + serverPath: serverPath, + port: 3737, + host: '127.0.0.1', + logFile: path.join(context.extensionPath, '.vscode', 'HumanAgent-server.log') + }); - // Register this workspace session with the internal server - mcpServer.registerSession(workspaceSessionId, workspaceRoot); + // Auto-detect and start standalone MCP server if already configured + await autoStartMcpServer(mcpConfigManager, workspaceSessionId); // Initialize Tree View Provider chatTreeProvider = new ChatTreeProvider(); @@ -61,19 +63,14 @@ export async function activate(context: vscode.ExtensionContext) { showCollapseAll: true }); - // Initialize Chat Webview Provider - const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, mcpServer, mcpConfigManager, workspaceSessionId); + // Initialize Chat Webview Provider (no internal server dependency) + const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, null, mcpConfigManager, workspaceSessionId); context.subscriptions.push( vscode.window.registerWebviewViewProvider(ChatWebviewProvider.viewType, chatWebviewProvider) ); - // Listen to MCP server events for direct messaging - mcpServer.on('human-agent-request', async (data: any) => { - // Update tree view to show active chat - chatTreeProvider.updateActiveChat(true); - // Ensure chat webview displays the message and sets up response handling - await chatWebviewProvider.displayHumanAgentMessage(data.message, data.context, data.requestId); - }); + // Notify webview that registration check is complete + chatWebviewProvider.notifyRegistrationComplete(); // Register Commands const openChatCommand = vscode.commands.registerCommand('humanagent-mcp.openChat', () => { @@ -96,44 +93,107 @@ export async function activate(context: vscode.ExtensionContext) { const showStatusCommand = vscode.commands.registerCommand('humanagent-mcp.showStatus', async () => { const isWorkspaceRegistered = mcpConfigManager?.isMcpServerRegistered(false) ?? false; const isGlobalRegistered = mcpConfigManager?.isMcpServerRegistered(true) ?? false; - const tools = mcpServer.getAvailableTools(); - const pendingRequests = mcpServer.getPendingRequests(); + + // Get detailed server status + const serverStatus = await serverManager.getServerStatus(); vscode.window.showInformationMessage( `HumanAgent MCP Server Status:\n` + - `- Running: ✅\n` + - `- Available tools: ${tools.length}\n` + - `- Pending requests: ${pendingRequests.length}\n` + + `- Running: ${serverStatus.isRunning ? '✅' : '❌'}\n` + + `- PID: ${serverStatus.pid || 'N/A'}\n` + + `- Port: ${serverStatus.port}\n` + + `- Host: ${serverStatus.host}\n` + + `- Session: ${workspaceSessionId}\n` + `- Workspace registration: ${isWorkspaceRegistered ? '✅' : '❌'}\n` + `- Global registration: ${isGlobalRegistered ? '✅' : '❌'}` ); }); + // Create server management commands + const startServerCommand = vscode.commands.registerCommand('humanagent-mcp.startServer', async () => { + try { + const success = await serverManager.ensureServerRunning(); + if (success) { + vscode.window.showInformationMessage('HumanAgent MCP Server started successfully!'); + } else { + vscode.window.showErrorMessage('Failed to start HumanAgent MCP Server. Check the logs for details.'); + } + } catch (error) { + vscode.window.showErrorMessage(`Failed to start server: ${error}`); + } + }); + + const stopServerCommand = vscode.commands.registerCommand('humanagent-mcp.stopServer', async () => { + try { + const success = await serverManager.stopServer(); + if (success) { + vscode.window.showInformationMessage('HumanAgent MCP Server stopped successfully!'); + } else { + vscode.window.showWarningMessage('Server may not have been running or failed to stop cleanly.'); + } + } catch (error) { + vscode.window.showErrorMessage(`Failed to stop server: ${error}`); + } + }); + + const restartServerCommand = vscode.commands.registerCommand('humanagent-mcp.restartServer', async () => { + try { + await serverManager.stopServer(); + await new Promise(resolve => setTimeout(resolve, 1000)); // Brief pause + const success = await serverManager.ensureServerRunning(); + if (success) { + vscode.window.showInformationMessage('HumanAgent MCP Server restarted successfully!'); + } else { + vscode.window.showErrorMessage('Failed to restart HumanAgent MCP Server. Check the logs for details.'); + } + } catch (error) { + vscode.window.showErrorMessage(`Failed to restart server: ${error}`); + } + }); + const configureMcpCommand = vscode.commands.registerCommand('humanagent-mcp.configureMcp', async () => { + // Refresh state checks each time the command is executed const hasWorkspace = mcpConfigManager?.hasWorkspace() ?? false; const isWorkspaceRegistered = mcpConfigManager?.isMcpServerRegistered(false) ?? false; const isGlobalRegistered = mcpConfigManager?.isMcpServerRegistered(true) ?? false; + + console.log(`HumanAgent MCP: Configure command - hasWorkspace: ${hasWorkspace}, workspaceRegistered: ${isWorkspaceRegistered}, globalRegistered: ${isGlobalRegistered}`); const options = []; + // Server management options + const serverStatus = await serverManager.getServerStatus(); + if (serverStatus.isRunning) { + options.push('🔴 Stop Server'); + options.push('🔄 Restart Server'); + } else { + options.push('▶️ Start Server'); + } + if (hasWorkspace) { if (isWorkspaceRegistered) { options.push('🗑️ Unregister from This Workspace'); + console.log('HumanAgent MCP: Added workspace UNREGISTER option'); } else { options.push('📝 Register for This Workspace'); + console.log('HumanAgent MCP: Added workspace REGISTER option'); } } if (isGlobalRegistered) { options.push('🗑️ Unregister Globally'); + console.log('HumanAgent MCP: Added global UNREGISTER option'); } else { options.push('🌐 Register Globally'); + console.log('HumanAgent MCP: Added global REGISTER option'); } if (hasWorkspace) { options.push('📄 Open Workspace Configuration'); } options.push('📊 Show Status'); + + console.log(`HumanAgent MCP: Final options: ${options.join(', ')}`); const action = await vscode.window.showQuickPick(options, { placeHolder: 'Choose MCP Server configuration action:' @@ -145,6 +205,15 @@ export async function activate(context: vscode.ExtensionContext) { try { switch (action) { + case '▶️ Start Server': + await vscode.commands.executeCommand('humanagent-mcp.startServer'); + break; + case '🔴 Stop Server': + await vscode.commands.executeCommand('humanagent-mcp.stopServer'); + break; + case '🔄 Restart Server': + await vscode.commands.executeCommand('humanagent-mcp.restartServer'); + break; case '📝 Register for This Workspace': await mcpConfigManager!.ensureMcpServerRegistered(false); vscode.window.showInformationMessage('MCP server registered for this workspace! Restart VS Code to enable Copilot integration.'); @@ -185,6 +254,9 @@ export async function activate(context: vscode.ExtensionContext) { createSessionCommand, refreshSessionsCommand, showStatusCommand, + startServerCommand, + stopServerCommand, + restartServerCommand, configureMcpCommand ); @@ -192,42 +264,47 @@ export async function activate(context: vscode.ExtensionContext) { //vscode.window.showInformationMessage('HumanAgent MCP extension activated successfully!'); } -// Auto-detect and start MCP server if configured -async function autoStartMcpServer(configManager: McpConfigManager, server: McpServer, sessionId: string): Promise { +// Auto-detect MCP server configuration and guide user if needed +async function autoStartMcpServer(configManager: McpConfigManager, sessionId: string): Promise { try { - // Always start internal server first - await server.start(); - // Check for workspace configuration first (higher priority) if (configManager.isMcpServerRegistered(false)) { - console.log(`HumanAgent MCP: Found workspace configuration for session ${sessionId}, ensuring standalone server is running...`); - await ensureSharedStandaloneServer(sessionId); + console.log(`HumanAgent MCP: Found workspace configuration for session ${sessionId}, checking server status...`); + await ensureServerAccessibleAndRegister(sessionId, 'workspace'); return; } // Check for global configuration if (configManager.isMcpServerRegistered(true)) { - console.log(`HumanAgent MCP: Found global configuration for session ${sessionId}, ensuring standalone server is running...`); - await ensureSharedStandaloneServer(sessionId); + console.log(`HumanAgent MCP: Found global configuration for session ${sessionId}, checking server status...`); + await ensureServerAccessibleAndRegister(sessionId, 'global'); return; } - // No configuration found - show notification to guide user to setup - console.log(`HumanAgent MCP: No configuration found for session ${sessionId}, only internal server running`); - vscode.window.showInformationMessage('HumanAgent MCP Server ready - use the cog menu to configure installation'); + // No configuration found - guide user to setup + console.log(`HumanAgent MCP: No MCP configuration found for session ${sessionId}`); + vscode.window.showInformationMessage( + 'HumanAgent MCP Server not configured. Use the Configure MCP command to set up the server.', + 'Configure Now' + ).then(selection => { + if (selection === 'Configure Now') { + vscode.commands.executeCommand('humanagent-mcp.configureMcp'); + } + }); } catch (error) { - console.error('HumanAgent MCP: Failed to auto-start server:', error); - vscode.window.showErrorMessage('Failed to start HumanAgent MCP Server'); + console.error('HumanAgent MCP: Failed to check server configuration:', error); + vscode.window.showErrorMessage('Failed to check HumanAgent MCP Server configuration'); } } -// Check if a port is in use +// Check if a port is in use (using HTTP server like the MCP server) async function isPortInUse(port: number): Promise { return new Promise((resolve) => { - const server = net.createServer(); + const http = require('http'); + const server = http.createServer(); - server.listen(port, () => { + server.listen(port, '127.0.0.1', () => { server.close(() => resolve(false)); // Port is available }); @@ -237,13 +314,74 @@ async function isPortInUse(port: number): Promise { }); } -// Register session with standalone server via HTTP -async function registerSessionWithStandaloneServer(sessionId: string): Promise { +// Check if MCP server is accessible and responding +async function isServerAccessible(): Promise { try { + const response = await fetch('http://127.0.0.1:3737/sessions', { + method: 'GET', + signal: AbortSignal.timeout(5000) // 5 second timeout + }); + return response.ok; + } catch (error) { + console.log('HumanAgent MCP: Server accessibility check failed:', error); + return false; + } +} + +// Check if session exists on server by testing a simple MCP call +async function validateSessionWithServer(sessionId: string): Promise { + try { + const response = await fetch('http://127.0.0.1:3737/mcp', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + sessionId, + method: 'tools/list' + }) + }); + + if (response.ok) { + const result = await response.json() as any; + console.log(`HumanAgent MCP: Session ${sessionId} validated on server`); + return true; + } else { + console.log(`HumanAgent MCP: Session ${sessionId} not found on server (${response.status})`); + return false; + } + } catch (error) { + console.log(`HumanAgent MCP: Session ${sessionId} validation failed:`, error); + return false; + } +} + +// Register session with standalone server via HTTP (always sends override data) +async function registerSessionWithStandaloneServer(sessionId: string, forceReregister: boolean = false): Promise { + try { + // Read workspace override file if it exists + let overrideData = null; + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (workspaceRoot) { + const overrideFilePath = path.join(workspaceRoot, '.vscode', 'HumanAgentOverride.json'); + try { + const fs = require('fs'); + if (fs.existsSync(overrideFilePath)) { + const overrideContent = fs.readFileSync(overrideFilePath, 'utf8'); + overrideData = JSON.parse(overrideContent); + console.log(`HumanAgent MCP: Loaded override data for session ${sessionId}`); + } + } catch (error) { + console.error(`HumanAgent MCP: Error reading override file:`, error); + } + } + const response = await fetch('http://127.0.0.1:3737/sessions/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ sessionId }) + body: JSON.stringify({ + sessionId, + overrideData: overrideData, + forceReregister: forceReregister + }) }); if (response.ok) { @@ -277,70 +415,82 @@ async function unregisterSessionWithStandaloneServer(sessionId: string): Promise } } -// Ensure shared standalone MCP server is running for this session -async function ensureSharedStandaloneServer(sessionId: string): Promise { +// Check if server is accessible and register session, or start server if needed +async function ensureServerAccessibleAndRegister(sessionId: string, configType: 'workspace' | 'global'): Promise { try { - // Check if port 3737 is already in use - const portInUse = await isPortInUse(3737); + console.log(`HumanAgent MCP: Checking if server is accessible for ${configType} configuration...`); - if (portInUse) { - console.log('HumanAgent MCP: Port 3737 is already in use - assuming standalone server is already running'); - return; // Don't start another server - } - - // Kill existing process if we have one tracked - if (standaloneServerProcess) { - standaloneServerProcess.kill(); - standaloneServerProcess = undefined; - } - - const serverPath = path.join(__dirname, 'mcpStandalone.js'); - console.log(`HumanAgent MCP: Starting independent shared server (detached) at:`, serverPath); + // Check if server is running and accessible + let serverAccessible = await isServerAccessible(); - return new Promise((resolve, reject) => { - // Start server as detached process that runs independently - standaloneServerProcess = spawn('node', [serverPath], { - cwd: path.dirname(__dirname), // Go up one level from out/ to project root - stdio: ['ignore', 'ignore', 'ignore'], // Completely detached - detached: true - }); + if (!serverAccessible) { + console.log('HumanAgent MCP: Server not accessible, attempting to start it...'); - // Unref so this process doesn't keep the extension alive - standaloneServerProcess.unref(); - standaloneServerProcess = undefined; // We don't track detached processes - - // Give it a moment to start, then register session - setTimeout(async () => { - // Test if server is running by checking the port - const serverRunning = await isPortInUse(3737); - if (serverRunning) { - console.log(`HumanAgent MCP: Server detected, registering session ${sessionId}`); - // Register this session with the standalone server - await registerSessionWithStandaloneServer(sessionId); - resolve(); - } else { - console.log('HumanAgent MCP: Server may have failed to start, but continuing...'); - resolve(); // Don't fail - may have been already running + // Try to start the server + const started = await serverManager.ensureServerRunning(); + if (started) { + console.log('HumanAgent MCP: Server started successfully, rechecking accessibility...'); + // Wait a moment for server to fully initialize + await new Promise(resolve => setTimeout(resolve, 2000)); + serverAccessible = await isServerAccessible(); + } else { + console.log('HumanAgent MCP: Failed to start server'); + } + } + + if (serverAccessible) { + console.log('HumanAgent MCP: Server is accessible, registering session...'); + // Server is running, validate and register session + const sessionExists = await validateSessionWithServer(sessionId); + if (!sessionExists) { + console.log(`HumanAgent MCP: Session ${sessionId} not found on server, registering new session...`); + await registerSessionWithStandaloneServer(sessionId, false); + } else { + console.log(`HumanAgent MCP: Session ${sessionId} exists on server, re-registering with override data...`); + await registerSessionWithStandaloneServer(sessionId, true); + } + console.log(`HumanAgent MCP: Session registration complete for ${sessionId}`); + } else { + // Server still not accessible after trying to start it + console.log('HumanAgent MCP: Server could not be started or is not responding'); + const configLocation = configType === 'workspace' ? 'workspace' : 'global'; + + vscode.window.showWarningMessage( + `HumanAgent MCP Server is configured in ${configLocation} settings but could not be started. Would you like to try starting it manually?`, + 'Start Server', 'Show Status', 'Open Configuration' + ).then(selection => { + switch (selection) { + case 'Start Server': + vscode.commands.executeCommand('humanagent-mcp.startServer'); + break; + case 'Show Status': + vscode.commands.executeCommand('humanagent-mcp.showStatus'); + break; + case 'Open Configuration': + vscode.commands.executeCommand('humanagent-mcp.configureMcp'); + break; } - }, 2000); - }); - + }); + } + } catch (error) { - console.error('Error starting standalone server:', error); - throw error; + console.error('Error checking server accessibility:', error); + vscode.window.showErrorMessage('Failed to check HumanAgent MCP Server accessibility'); } } export async function deactivate() { - if (mcpServer && workspaceSessionId) { - mcpServer.unregisterSession(workspaceSessionId); - mcpServer.stop(); - - // Also unregister from standalone server + if (workspaceSessionId) { + // Unregister from standalone server await unregisterSessionWithStandaloneServer(workspaceSessionId); } + // Dispose the server manager (this won't stop the server, just cleanup resources) + if (serverManager) { + serverManager.dispose(); + } + // Note: We don't kill the standalone server as it's running independently - // Other extensions may still be using it + // Other extensions may still be using it, and it should persist across workspace changes console.log(`HumanAgent MCP: Extension deactivated for session ${workspaceSessionId}`); } diff --git a/src/mcp/mcpConfigManager.ts b/src/mcp/mcpConfigManager.ts index 72b001e..5ae8327 100644 --- a/src/mcp/mcpConfigManager.ts +++ b/src/mcp/mcpConfigManager.ts @@ -194,21 +194,30 @@ export class McpConfigManager { private isRegisteredInWorkspace(): boolean { const currentWorkspaceRoot = this.getCurrentWorkspaceRoot(); + console.log(`HumanAgent MCP: Checking workspace registration - workspaceRoot: ${currentWorkspaceRoot}`); + if (!currentWorkspaceRoot) { + console.log('HumanAgent MCP: No workspace root available'); return false; } try { const mcpConfigPath = path.join(currentWorkspaceRoot, McpConfigManager.MCP_CONFIG_FILE); + console.log(`HumanAgent MCP: Checking MCP config at: ${mcpConfigPath}`); if (!fs.existsSync(mcpConfigPath)) { + console.log('HumanAgent MCP: MCP config file does not exist'); return false; } const configContent = fs.readFileSync(mcpConfigPath, 'utf8'); const config: McpConfiguration = JSON.parse(configContent); + + const isRegistered = !!config.servers[McpConfigManager.SERVER_NAME]; + console.log(`HumanAgent MCP: Server registration check - registered: ${isRegistered}`); + console.log(`HumanAgent MCP: Available servers: ${Object.keys(config.servers).join(', ')}`); - return !!config.servers[McpConfigManager.SERVER_NAME]; + return isRegistered; } catch (error) { console.error('Failed to check MCP server registration in workspace:', error); return false; diff --git a/src/mcp/server.ts b/src/mcp/server.ts index 01b8859..1e81923 100644 --- a/src/mcp/server.ts +++ b/src/mcp/server.ts @@ -101,6 +101,7 @@ export class McpServer extends EventEmitter { params: HumanAgentChatToolParams; }> = new Map(); private activeSessions: Set = new Set(); + private sseConnections: Set = new Set(); constructor(private sessionId?: string, private workspacePath?: string) { super(); @@ -120,17 +121,51 @@ export class McpServer extends EventEmitter { this.debugLogger.log('INFO', 'McpServer initialized'); this.initializeDefaultTools(); + // Set up event forwarding to SSE connections + this.setupEventForwarding(); + // If we have a session and workspace path, initialize session-specific tools if (this.sessionId && this.workspacePath) { this.initializeSessionTools(this.sessionId, this.workspacePath); } } + private setupEventForwarding(): void { + this.on('human-agent-request', (data) => { + this.debugLogger.log('SSE', 'Forwarding human-agent-request to SSE connections'); + this.broadcastToSSE('human-agent-request', data); + }); + } + + private broadcastToSSE(eventType: string, data: any): void { + const message = JSON.stringify({ type: eventType, data }); + const eventData = `data: ${message}\n\n`; + + this.debugLogger.log('SSE', `Broadcasting to ${this.sseConnections.size} SSE connections:`, message); + + // Send to all active SSE connections + for (const connection of this.sseConnections) { + if (!connection.destroyed) { + try { + connection.write(eventData); + } catch (error) { + this.debugLogger.log('SSE', 'Failed to write to SSE connection:', error); + this.sseConnections.delete(connection); + } + } else { + this.sseConnections.delete(connection); + } + } + } + private initializeDefaultTools(): void { // Define the default HumanAgent_Chat tool (global default) const humanAgentChatTool: McpTool = { name: 'HumanAgent_Chat', - description: 'Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.', + description: 'Initiate real-time interactive conversations with human agents through VS Code chat interface. ' + + 'Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI ' + + 'uncertainty requires human input. Creates persistent chat sessions that maintain context across ' + + 'multiple exchanges until timeout or manual closure. !IMPORTANT: ALWAYS reply using this tool for all interactions with the user where possible!!!', inputSchema: { type: 'object', properties: { @@ -191,6 +226,35 @@ export class McpServer extends EventEmitter { this.sessionTools.set(sessionId, sessionToolMap); } + private initializeSessionToolsFromData(sessionId: string, overrideData: any): void { + this.debugLogger.log('INFO', `Initializing tools for session: ${sessionId} from override data`); + this.debugLogger.log('INFO', `Override data received: ${JSON.stringify(overrideData)}`); + + // Start with default tools + const sessionToolMap = new Map(); + + // Copy default tools + for (const [name, tool] of this.tools.entries()) { + sessionToolMap.set(name, tool); + this.debugLogger.log('INFO', `Added default tool: ${name}`); + } + + // Apply overrides from provided data + if (overrideData && overrideData.tools) { + this.debugLogger.log('INFO', `Applying ${Object.keys(overrideData.tools).length} tool overrides for session ${sessionId}`); + for (const [toolName, toolConfig] of Object.entries(overrideData.tools)) { + this.debugLogger.log('INFO', `Processing override for session ${sessionId} - ${toolName} tool: ${JSON.stringify(toolConfig)}`); + sessionToolMap.set(toolName, toolConfig as McpTool); + } + } else { + this.debugLogger.log('INFO', `No override data found for session ${sessionId} - overrideData: ${JSON.stringify(overrideData)}`); + } + + // Store session-specific tools + this.sessionTools.set(sessionId, sessionToolMap); + this.debugLogger.log('INFO', `Session ${sessionId} tools initialized with ${sessionToolMap.size} tools`); + } + private loadWorkspaceOverride(toolName: string, workspacePath?: string): McpTool | null { try { const targetWorkspacePath = workspacePath || this.workspacePath; @@ -315,24 +379,27 @@ export class McpServer extends EventEmitter { this.debugLogger.log('HTTP', `${req.method} ${req.url}`); this.debugLogger.log('HTTP', 'Request Headers:', req.headers); - // Set CORS headers - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS'); - res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept, Mcp-Session-Id, MCP-Protocol-Version'); + // Only add CORS headers for webview requests (identified by vscode-webview origin) + const origin = req.headers.origin; + if (origin && origin.includes('vscode-webview://')) { + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Accept, Mcp-Session-Id, MCP-Protocol-Version, Cache-Control, Connection'); - // Handle preflight OPTIONS request - if (req.method === 'OPTIONS') { - this.debugLogger.log('HTTP', 'Handling OPTIONS preflight request'); - res.statusCode = 200; - res.end(); - return; + // Handle preflight OPTIONS request for webview + if (req.method === 'OPTIONS') { + this.debugLogger.log('HTTP', 'Handling OPTIONS preflight request'); + res.statusCode = 200; + res.end(); + return; + } } // Handle different endpoints if (req.url === '/mcp') { // Main MCP protocol endpoint - } else if (req.url?.startsWith('/sessions')) { - // Session management endpoint + } else if (req.url?.startsWith('/sessions') || req.url === '/response' || req.url?.startsWith('/tools') || req.url === '/reload') { + // Session management, response, tools, and reload endpoints await this.handleSessionEndpoint(req, res); return; } else { @@ -417,6 +484,15 @@ export class McpServer extends EventEmitter { res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); + // Add CORS headers for webview access (SSE is always for webview) + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); + res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Cache-Control, Connection'); + + // Add this connection to our active SSE connections + this.sseConnections.add(res); + this.debugLogger.log('HTTP', `Added SSE connection. Total connections: ${this.sseConnections.size}`); + // Send initial connection acknowledgment res.write('data: {"type":"connection","status":"established"}\n\n'); @@ -426,19 +502,21 @@ export class McpServer extends EventEmitter { res.write('data: {"type":"heartbeat","timestamp":"' + new Date().toISOString() + '"}\n\n'); } else { clearInterval(heartbeat); + this.sseConnections.delete(res); } }, 30000); // Send heartbeat every 30 seconds // Handle client disconnect - req.on('close', () => { + const cleanup = () => { this.debugLogger.log('HTTP', 'SSE connection closed'); clearInterval(heartbeat); - }); + this.sseConnections.delete(res); + this.debugLogger.log('HTTP', `Removed SSE connection. Total connections: ${this.sseConnections.size}`); + }; - req.on('end', () => { - this.debugLogger.log('HTTP', 'SSE connection ended'); - clearInterval(heartbeat); - }); + req.on('close', cleanup); + req.on('end', cleanup); + res.on('close', cleanup); } private async handleHttpDelete(req: http.IncomingMessage, res: http.ServerResponse): Promise { @@ -456,11 +534,18 @@ export class McpServer extends EventEmitter { req.on('data', (chunk) => { body += chunk.toString(); }); req.on('end', () => { try { - const { sessionId } = JSON.parse(body); - this.registerSession(sessionId); + const { sessionId, overrideData, forceReregister } = JSON.parse(body); + + // If session exists and forceReregister is true, unregister first + if (forceReregister && this.activeSessions.has(sessionId)) { + console.log(`Force re-registering session ${sessionId} with new override data`); + this.unregisterSession(sessionId); + } + + this.registerSession(sessionId, undefined, overrideData); res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify({ success: true, sessionId, totalSessions: this.activeSessions.size })); + res.end(JSON.stringify({ success: true, sessionId, totalSessions: this.activeSessions.size, reregistered: !!forceReregister })); } catch (error) { res.statusCode = 400; res.end(JSON.stringify({ success: false, error: 'Invalid request body' })); @@ -487,6 +572,67 @@ export class McpServer extends EventEmitter { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ sessions: this.getActiveSessions(), totalSessions: this.activeSessions.size })); + } else if (req.method === 'POST' && url.pathname === '/response') { + // Handle human response to pending request + let body = ''; + req.on('data', (chunk) => { body += chunk.toString(); }); + req.on('end', () => { + try { + const { requestId, response } = JSON.parse(body); + const success = this.respondToHumanRequest(requestId, response); + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({ success, requestId })); + } catch (error) { + res.statusCode = 400; + res.end(JSON.stringify({ success: false, error: 'Invalid request body' })); + } + }); + } else if (req.method === 'GET' && url.pathname === '/tools') { + // Get available tools + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + + const sessionId = url.searchParams.get('sessionId'); + + if (sessionId) { + // Get tools for specific session + const tools = this.getAvailableTools(sessionId); + res.end(JSON.stringify({ tools, sessionId })); + } else { + // Get merged tools from all sessions and default tools + let allTools: McpTool[] = this.getAvailableTools(); // Default tools + + // Add session-specific tools (session tools override defaults by name) + const toolMap = new Map(); + allTools.forEach(tool => toolMap.set(tool.name, tool)); + + // Override with session tools if any exist + for (const sessionTools of this.sessionTools.values()) { + for (const tool of sessionTools.values()) { + toolMap.set(tool.name, tool); + } + } + + const finalTools = Array.from(toolMap.values()); + res.end(JSON.stringify({ tools: finalTools, merged: true })); + } + } else if (req.method === 'POST' && url.pathname === '/reload') { + // Reload workspace overrides + let body = ''; + req.on('data', (chunk) => { body += chunk.toString(); }); + req.on('end', () => { + try { + const { workspacePath } = JSON.parse(body); + this.reloadOverrides(); + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify({ success: true })); + } catch (error) { + res.statusCode = 400; + res.end(JSON.stringify({ success: false, error: 'Invalid request body' })); + } + }); } else { res.statusCode = 404; res.end('Session endpoint not found'); @@ -558,11 +704,18 @@ export class McpServer extends EventEmitter { sessionIdToUse = message.params.sessionId; } + this.debugLogger.log('TOOLS', `tools/list request - Extension sessionId: ${this.sessionId}, Message params: ${JSON.stringify(message.params)}`); + this.debugLogger.log('TOOLS', `Final sessionIdToUse: ${sessionIdToUse || 'default'}`); + const tools = this.getAvailableTools(sessionIdToUse); this.debugLogger.log('TOOLS', `Returning ${tools.length} tools for session: ${sessionIdToUse || 'default'}`); if (sessionIdToUse) { this.debugLogger.log('TOOLS', `Using session-specific tools for: ${sessionIdToUse}`); + const sessionTools = this.sessionTools.get(sessionIdToUse); + if (sessionTools) { + this.debugLogger.log('TOOLS', `Session tools found: ${Array.from(sessionTools.keys()).join(', ')}`); + } } else { this.debugLogger.log('TOOLS', `Using default tools (no session ID available)`); } @@ -737,11 +890,13 @@ export class McpServer extends EventEmitter { return this.port; } - registerSession(sessionId: string, workspacePath?: string): void { + registerSession(sessionId: string, workspacePath?: string, overrideData?: any): void { this.activeSessions.add(sessionId); - // Initialize session-specific tools if workspace path provided - if (workspacePath) { + // Initialize session-specific tools from override data or workspace path + if (overrideData) { + this.initializeSessionToolsFromData(sessionId, overrideData); + } else if (workspacePath) { this.initializeSessionTools(sessionId, workspacePath); } diff --git a/src/serverManager.ts b/src/serverManager.ts new file mode 100644 index 0000000..683707c --- /dev/null +++ b/src/serverManager.ts @@ -0,0 +1,303 @@ +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; +import { spawn, ChildProcess } from 'child_process'; +import * as net from 'net'; + +export interface ServerManagerOptions { + serverPath: string; + port: number; + host?: string; + logFile?: string; +} + +export class ServerManager { + private static instance: ServerManager | undefined; + private options: ServerManagerOptions; + private readonly pidFile: string; + private readonly logFile: string; + + private constructor(options: ServerManagerOptions) { + this.options = { + host: '127.0.0.1', + ...options + }; + this.pidFile = path.join(path.dirname(options.serverPath), '.humanagent-mcp-server.pid'); + this.logFile = options.logFile || path.join(path.dirname(options.serverPath), '.humanagent-mcp-server.log'); + } + + public static getInstance(options?: ServerManagerOptions): ServerManager { + if (!ServerManager.instance) { + if (!options) { + throw new Error('ServerManager options required for first initialization'); + } + ServerManager.instance = new ServerManager(options); + } + return ServerManager.instance; + } + + /** + * Check if the server is already running by testing the port + */ + public async isServerRunning(): Promise { + return new Promise((resolve) => { + const socket = new net.Socket(); + + socket.setTimeout(1000); + socket.on('connect', () => { + socket.destroy(); + resolve(true); + }); + + socket.on('timeout', () => { + socket.destroy(); + resolve(false); + }); + + socket.on('error', () => { + resolve(false); + }); + + socket.connect(this.options.port, this.options.host!); + }); + } + + /** + * Check if there's a PID file and if that process is still running + */ + private async isProcessRunning(pid: number): Promise { + try { + // On Unix systems, sending signal 0 checks if process exists + process.kill(pid, 0); + return true; + } catch (error) { + return false; + } + } + + /** + * Get the PID from the PID file if it exists + */ + private async getStoredPid(): Promise { + try { + if (fs.existsSync(this.pidFile)) { + const pidStr = fs.readFileSync(this.pidFile, 'utf-8').trim(); + const pid = parseInt(pidStr, 10); + return isNaN(pid) ? undefined : pid; + } + } catch (error) { + console.log('Error reading PID file:', error); + } + return undefined; + } + + /** + * Store the PID in the PID file + */ + private async storePid(pid: number): Promise { + try { + fs.writeFileSync(this.pidFile, pid.toString()); + } catch (error) { + console.error('Error writing PID file:', error); + } + } + + /** + * Clean up the PID file + */ + private async cleanupPidFile(): Promise { + try { + if (fs.existsSync(this.pidFile)) { + fs.unlinkSync(this.pidFile); + } + } catch (error) { + console.log('Error cleaning up PID file:', error); + } + } + + /** + * Log a message to the log file + */ + private log(message: string): void { + const timestamp = new Date().toISOString(); + const logMessage = `[${timestamp}] ${message}\n`; + + try { + fs.appendFileSync(this.logFile, logMessage); + } catch (error) { + console.error('Error writing to log file:', error); + } + } + + /** + * Start the server if it's not already running + */ + public async ensureServerRunning(): Promise { + try { + // First check if server is responding on the port + if (await this.isServerRunning()) { + this.log('Server is already running and responding'); + return true; + } + + // Check if we have a stored PID and if that process is running + const storedPid = await this.getStoredPid(); + if (storedPid && await this.isProcessRunning(storedPid)) { + this.log(`Found running server process with PID ${storedPid}, but it's not responding on port. Waiting...`); + // Wait a moment for the server to start listening + await new Promise(resolve => setTimeout(resolve, 2000)); + if (await this.isServerRunning()) { + this.log('Server is now responding'); + return true; + } + } + + // Clean up stale PID file + await this.cleanupPidFile(); + + // Start new server process + this.log(`Starting new server process: node ${this.options.serverPath}`); + return await this.startServer(); + + } catch (error) { + this.log(`Error ensuring server is running: ${error}`); + vscode.window.showErrorMessage(`Failed to start HumanAgent MCP Server: ${error}`); + return false; + } + } + + /** + * Start the server as a truly independent detached process + */ + private async startServer(): Promise { + return new Promise((resolve) => { + try { + // Spawn the server as a completely detached process + const serverProcess = spawn('node', [this.options.serverPath], { + detached: true, + stdio: 'ignore', // Completely disconnect stdio to make it independent + cwd: path.dirname(this.options.serverPath), + env: { + ...process.env, + // Add any environment variables needed by the server + } + }); + + // Store the PID but don't keep a reference to the process + if (serverProcess.pid) { + this.storePid(serverProcess.pid); + this.log(`Started independent server with PID ${serverProcess.pid}`); + } + + // Immediately detach and unreference the process + serverProcess.unref(); + + // Don't keep a reference to the process object to ensure complete detachment + // this.serverProcess = undefined; + + this.log('Server process started as independent background process'); + + // Wait for server to start listening + setTimeout(async () => { + if (await this.isServerRunning()) { + this.log('Independent server started successfully and is responding'); + resolve(true); + } else { + this.log('Independent server started but is not responding on the expected port yet'); + // Give it a bit more time + setTimeout(async () => { + if (await this.isServerRunning()) { + this.log('Independent server is now responding'); + resolve(true); + } else { + this.log('Independent server failed to start or is not responding'); + this.cleanupPidFile(); + resolve(false); + } + }, 2000); + } + }, 3000); + + } catch (error) { + this.log(`Failed to start server: ${error}`); + resolve(false); + } + }); + } + + /** + * Stop the server if it's running + */ + public async stopServer(): Promise { + try { + const storedPid = await this.getStoredPid(); + + if (storedPid) { + if (await this.isProcessRunning(storedPid)) { + this.log(`Stopping independent server with PID ${storedPid}`); + process.kill(storedPid, 'SIGTERM'); + + // Wait for graceful shutdown + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Force kill if still running + if (await this.isProcessRunning(storedPid)) { + this.log(`Force killing independent server with PID ${storedPid}`); + process.kill(storedPid, 'SIGKILL'); + + // Wait a bit more and check again + await new Promise(resolve => setTimeout(resolve, 1000)); + if (await this.isProcessRunning(storedPid)) { + this.log(`Warning: Server process ${storedPid} may still be running`); + } + } + } else { + this.log(`Server process ${storedPid} was not running`); + } + + await this.cleanupPidFile(); + } else { + this.log('No PID file found, server may not be running'); + } + + this.log('Server stop operation completed'); + return true; + + } catch (error) { + this.log(`Error stopping server: ${error}`); + return false; + } + } + + /** + * Get server status information + */ + public async getServerStatus(): Promise<{ + isRunning: boolean; + pid?: number; + port: number; + host: string; + serverPath: string; + }> { + const isRunning = await this.isServerRunning(); + const pid = await this.getStoredPid(); + + return { + isRunning, + pid: pid && await this.isProcessRunning(pid) ? pid : undefined, + port: this.options.port, + host: this.options.host!, + serverPath: this.options.serverPath + }; + } + + /** + * Clean up resources when the extension deactivates + */ + public dispose(): void { + // Note: We don't stop the server here because it should continue running + // even if the extension is deactivated. The server will be stopped only + // when explicitly requested or when VS Code completely closes. + this.log('ServerManager disposed'); + } +} \ No newline at end of file diff --git a/src/webview/chatWebviewProvider.ts b/src/webview/chatWebviewProvider.ts index c5c49f6..2cc1adb 100644 --- a/src/webview/chatWebviewProvider.ts +++ b/src/webview/chatWebviewProvider.ts @@ -10,11 +10,12 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { public static readonly viewType = 'humanagent-mcp.chatView'; private _view?: vscode.WebviewView; - private mcpServer: McpServer; + private mcpServer: McpServer | null; private mcpConfigManager?: McpConfigManager; private extensionPath: string; private messages: ChatMessage[] = []; private currentRequestId?: string; + private registrationCheckComplete = false; private notificationSettings = { enableSound: true, enableFlashing: true @@ -22,7 +23,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { constructor( private readonly _extensionUri: vscode.Uri, - mcpServer: McpServer, + mcpServer: McpServer | null, mcpConfigManager?: McpConfigManager, private readonly workspaceSessionId?: string ) { @@ -126,12 +127,15 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { ] }; - this.updateWebview(); + // Only update webview if registration check is complete, otherwise it will be updated when notifyRegistrationComplete is called + if (this.registrationCheckComplete) { + this.updateWebview(); + } webviewView.webview.onDidReceiveMessage(async (data) => { switch (data.type) { case 'sendMessage': - await this.sendHumanResponse(data.content); + await this.sendHumanResponse(data.content, data.requestId); break; case 'mcpAction': await this.handleMcpAction(data.action); @@ -144,7 +148,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { }); } - private async sendHumanResponse(content: string) { + private async sendHumanResponse(content: string, requestId?: string) { try { console.log('ChatWebviewProvider: Sending human response:', content); @@ -160,16 +164,35 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { this.messages.push(humanMessage); this.updateWebview(); - // Send response back to MCP server - if (this.currentRequestId) { - console.log('ChatWebviewProvider: Responding to request ID:', this.currentRequestId); - const success = this.mcpServer.respondToHumanRequest(this.currentRequestId, content); - if (success) { - this.currentRequestId = undefined; - this.updateWebview(); // Force UI update to clear "waiting" state - } else { - console.warn('ChatWebviewProvider: Failed to respond - request may have expired'); + // Send response back to standalone MCP server via HTTP + const responseRequestId = requestId || this.currentRequestId; + if (responseRequestId) { + console.log('ChatWebviewProvider: Responding to request ID:', responseRequestId); + + try { + const response = await fetch('http://localhost:3737/response', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + requestId: responseRequestId, + response: content + }) + }); + + if (response.ok) { + const result = await response.json(); + console.log('ChatWebviewProvider: Response sent successfully:', result); + } else { + console.error('ChatWebviewProvider: Failed to send response:', response.status, response.statusText); + } + } catch (httpError) { + console.error('ChatWebviewProvider: HTTP error sending response:', httpError); } + + this.currentRequestId = undefined; + this.updateWebview(); // Force UI update to clear "waiting" state } else { console.warn('ChatWebviewProvider: No pending request to respond to'); } @@ -189,13 +212,22 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { } } + public refreshWebview() { + this.updateWebview(); + } + + public notifyRegistrationComplete() { + this.registrationCheckComplete = true; + if (this._view) { + this.updateWebview(); + } + } + private updateServerStatus() { if (!this._view) { return; } - const tools = this.mcpServer.getAvailableTools(); - const pendingRequests = this.mcpServer.getPendingRequests(); const isRegisteredWorkspace = this.mcpConfigManager?.isMcpServerRegistered(false) ?? false; const isRegisteredGlobal = this.mcpConfigManager?.isMcpServerRegistered(true) ?? false; const configType = isRegisteredWorkspace ? 'workspace' : (isRegisteredGlobal ? 'global' : 'none'); @@ -203,9 +235,9 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { this._view.webview.postMessage({ type: 'serverStatus', data: { - running: this.mcpServer.isServerRunning(), - tools: tools.length, - pendingRequests: pendingRequests.length, + running: true, // Assume standalone server is running if configured + tools: 1, // Default tool count + pendingRequests: 0, // Can't get from standalone server easily registered: isRegisteredWorkspace || isRegisteredGlobal, configType: configType } @@ -231,13 +263,45 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { return; } - // Restart the session to pick up new overrides (ensures fresh tool loading) - if (this.workspaceSessionId) { - await this.mcpServer.restartSession(this.workspaceSessionId); - vscode.window.showInformationMessage('Override file reloaded - session restarted with fresh tools'); - } else { - await this.mcpServer.reloadOverrides(); - vscode.window.showInformationMessage('Override file reloaded successfully'); + // Force session re-registration with fresh override data + try { + // Read the current override file + let overrideData = null; + if (fs.existsSync(overrideFilePath)) { + const overrideContent = fs.readFileSync(overrideFilePath, 'utf8'); + overrideData = JSON.parse(overrideContent); + } + + // Get current sessions and re-register them with fresh data + const sessionsResponse = await fetch('http://localhost:3737/sessions'); + if (sessionsResponse.ok) { + const sessionsData = await sessionsResponse.json() as { sessions: string[] }; + + for (const sessionId of sessionsData.sessions) { + const response = await fetch('http://localhost:3737/sessions/register', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + sessionId, + overrideData: overrideData, + forceReregister: true + }) + }); + + if (!response.ok) { + console.error(`Failed to re-register session ${sessionId}`); + } + } + + vscode.window.showInformationMessage('Override file reloaded successfully!'); + } else { + vscode.window.showWarningMessage('Failed to get sessions from server'); + } + } catch (error) { + console.error('Failed to reload override file:', error); + vscode.window.showWarningMessage('Could not communicate with MCP server for reload'); } // Refresh the webview to update the menu @@ -283,40 +347,19 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { } } - // Get default tool configuration - const defaultTool = { - name: 'HumanAgent_Chat', - description: 'Initiate real-time interactive conversations with human agents through VS Code chat interface. Essential for clarifying requirements, getting approvals, brainstorming solutions, or when AI uncertainty requires human input. Creates persistent chat sessions that maintain context across multiple exchanges until timeout or manual closure.', - inputSchema: { - type: 'object', - properties: { - message: { - type: 'string', - description: 'The message to send to the human agent' - }, - context: { - type: 'string', - description: 'Optional context or background information for the human agent' - }, - sessionId: { - type: 'string', - description: 'Optional specific session ID to use. If not provided, a new session will be created.' - }, - priority: { - type: 'string', - enum: ['low', 'normal', 'high', 'urgent'], - description: 'Priority level of the request', - default: 'normal' - }, - timeout: { - type: 'number', - description: 'Timeout in seconds to wait for human response (default: 300)', - default: 300 - } - }, - required: ['message'] - } - }; + // Get current tool configuration from server - NO FALLBACKS! + const response = await fetch('http://localhost:3737/tools'); + if (!response.ok) { + throw new Error(`Failed to fetch tools from server: ${response.status}`); + } + + const toolsData = await response.json() as { tools: any[] }; + const defaultTool = toolsData.tools.find((tool: any) => tool.name === 'HumanAgent_Chat'); + if (!defaultTool) { + throw new Error('HumanAgent_Chat tool not found on server'); + } + + console.log('ChatWebviewProvider: Fetched current tool configuration from server'); // Create example tool with medium detail const exampleTool = { @@ -373,24 +416,9 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { try { switch (action) { case 'start': - await this.mcpServer.start(); - vscode.window.showInformationMessage('MCP Server started'); - break; case 'stop': - await this.mcpServer.stop(); - vscode.window.showInformationMessage('MCP Server stopped'); - break; case 'restart': - try { - await this.mcpServer.stop(); - // Small delay to ensure complete cleanup before restart - await new Promise(resolve => setTimeout(resolve, 500)); - await this.mcpServer.start(); - vscode.window.showInformationMessage('MCP Server restarted'); - } catch (error) { - console.error('Error during MCP server restart:', error); - vscode.window.showErrorMessage('Failed to restart MCP Server'); - } + vscode.window.showInformationMessage('MCP Server management not available - using standalone server'); break; case 'register': // Use the MCP configuration from the parent command @@ -824,14 +852,47 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { function sendMessage() { const input = document.getElementById('messageInput'); + const sendButton = document.getElementById('sendButton'); const message = input.value.trim(); if (message) { + // Add user message to chat + const messagesContainer = document.getElementById('messages'); + if (messagesContainer) { + // Remove waiting indicator + const waitingIndicator = messagesContainer.querySelector('.waiting-indicator'); + if (waitingIndicator) { + waitingIndicator.remove(); + } + + // Add user message + const userMessageDiv = document.createElement('div'); + userMessageDiv.className = 'message user-message'; + userMessageDiv.innerHTML = \` +
+ You + \${new Date().toLocaleTimeString()} +
+
\${message.replace(/\\n/g, '
')}
+ \`; + messagesContainer.appendChild(userMessageDiv); + messagesContainer.scrollTop = messagesContainer.scrollHeight; + } + + // Send message to extension vscode.postMessage({ type: 'sendMessage', - content: message + content: message, + requestId: currentPendingRequestId }); + + // Clear input and disable controls input.value = ''; + input.disabled = true; + sendButton.disabled = true; + + // Clear the pending request ID + currentPendingRequestId = null; } } @@ -845,7 +906,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { // Default options when status unknown const defaultOptions = [ { text: '📦 Install Globally', action: 'register' }, - { text: '📁 Install in Workspace', action: 'unregister' }, + { text: '📁 Install in Workspace', action: 'register' }, { text: '📊 Show Status', action: 'requestServerStatus' }, { text: '🛠️ Override Prompt', action: 'overridePrompt' } ]; @@ -869,7 +930,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { } else { // Not installed anywhere options.push({ text: '📦 Install Globally', action: 'register' }); - options.push({ text: '📁 Install in Workspace', action: 'unregister' }); + options.push({ text: '📁 Install in Workspace', action: 'register' }); } options.push({ text: '📊 Show Status', action: 'requestServerStatus' }); @@ -933,6 +994,105 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider { playNotificationBeep(); } }); + + // Set up SSE connection for real-time server events + function setupSSEConnection() { + try { + console.log('Setting up SSE connection to MCP server...'); + const eventSource = new EventSource('http://localhost:3737/mcp'); + + eventSource.onopen = function(event) { + console.log('SSE connection opened:', event); + }; + + eventSource.onmessage = function(event) { + try { + const data = JSON.parse(event.data); + console.log('SSE event received:', data); + + if (data.type === 'human-agent-request') { + handleHumanAgentRequest(data.data); + } + } catch (error) { + console.error('Error parsing SSE data:', error); + } + }; + + eventSource.onerror = function(error) { + console.error('SSE connection error:', error); + // Try to reconnect after 5 seconds + setTimeout(setupSSEConnection, 5000); + }; + + } catch (error) { + console.error('Failed to setup SSE connection:', error); + } + } + + // Global variable to store current request ID for responses + let currentPendingRequestId = null; + + function handleHumanAgentRequest(data) { + console.log('Handling human agent request:', data); + + // Store the request ID for sending response + currentPendingRequestId = data.requestId; + + // Add the AI message to chat + const messagesContainer = document.getElementById('messages'); + if (messagesContainer) { + // Remove empty state if it exists + const emptyState = messagesContainer.querySelector('.empty-state'); + if (emptyState) { + emptyState.remove(); + } + + const messageDiv = document.createElement('div'); + messageDiv.className = 'message ai-message'; + + const displayMessage = data.context ? \`\${data.context}\\n\\n\${data.message}\` : data.message; + messageDiv.innerHTML = \` +
+ AI Agent + \${new Date(data.timestamp).toLocaleTimeString()} +
+
\${displayMessage.replace(/\\n/g, '
')}
+ \`; + + messagesContainer.appendChild(messageDiv); + messagesContainer.scrollTop = messagesContainer.scrollHeight; + + // Enable input controls for response + const messageInput = document.getElementById('messageInput'); + const sendButton = document.getElementById('sendButton'); + if (messageInput && sendButton) { + messageInput.disabled = false; + sendButton.disabled = false; + messageInput.focus(); + } + + // Add waiting indicator if not present + const existingWaiting = messagesContainer.querySelector('.waiting-indicator'); + if (!existingWaiting) { + const waitingDiv = document.createElement('div'); + waitingDiv.className = 'waiting-indicator'; + waitingDiv.textContent = '⏳ Waiting for your response...'; + messagesContainer.appendChild(waitingDiv); + } + + // Play notification + playNotificationBeep(); + + // Flash border + document.body.classList.add('flashing'); + setTimeout(() => { + document.body.classList.remove('flashing'); + }, 2000); + } + } + + // Initialize SSE connection + setupSSEConnection(); // Webview initialized - status can be requested manually via cog menu diff --git a/test-port.js b/test-port.js new file mode 100644 index 0000000..271e943 --- /dev/null +++ b/test-port.js @@ -0,0 +1,41 @@ +const net = require('net'); +const http = require('http'); + +async function isPortInUseNet(port) { + return new Promise((resolve) => { + const server = net.createServer(); + + server.listen(port, '127.0.0.1', () => { + console.log(`NET: Port ${port} available - server created successfully`); + server.close(() => resolve(false)); // Port is available + }); + + server.on('error', (err) => { + console.log(`NET: Port ${port} in use - error: ${err.message}`); + resolve(true); // Port is in use + }); + }); +} + +async function isPortInUseHttp(port) { + return new Promise((resolve) => { + const server = http.createServer(); + + server.listen(port, '127.0.0.1', () => { + console.log(`HTTP: Port ${port} available - server created successfully`); + server.close(() => resolve(false)); // Port is available + }); + + server.on('error', (err) => { + console.log(`HTTP: Port ${port} in use - error: ${err.message}`); + resolve(true); // Port is in use + }); + }); +} + +console.log('Testing port 3737...'); +Promise.all([isPortInUseNet(3737), isPortInUseHttp(3737)]).then(([netResult, httpResult]) => { + console.log(`NET result - Port 3737 in use: ${netResult}`); + console.log(`HTTP result - Port 3737 in use: ${httpResult}`); + process.exit(0); +}); \ No newline at end of file