mirror of
https://github.com/wassname/HumanAgent-MCP.git
synced 2026-09-12 12:00:51 +08:00
feat: Add reconnection backoff, server start notifications, issue reporting, improved README
- Implement exponential backoff for SSE reconnection (1s → 30s max, no timeout) - Update connection status indicator (green/orange/red dot) - Reset backoff and reconnect immediately when server manually started - Add Report Issue and Request Feature options to cog menu - Add bugs field to package.json for native VS Code issue reporting - Improve README with actual usage instructions and troubleshooting - Fix status indicator to update properly on disconnect - Close EventSource to prevent browser auto-reconnect interference
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 379 KiB |
@@ -1,13 +1,73 @@
|
||||
# What
|
||||
This extension provides VSCode Github Copilot Aagent a `HumanAgent_Chat` MCP tool that forces AI assistants to communicate through a human agent instead of giving direct responses. When an AI uses this tool, it opens a chat session where humans can respond in real-time.
|
||||
# HumanAgent MCP
|
||||
|
||||
## Why
|
||||
The AI Agent is encouraged to discuss with you before running off to do its own thing - if its part way through iterating through on a problem it can stop and ask you a question - it reduces requests considerably, helps avoid runaway agent, allows you to manage multiple VSCode agents working in multiple workspaces from one web page. Allows you to append useful reminders to each response.
|
||||
|
||||
Forces GitHub Copilot to chat with you before acting. Stops runaway agents, reduces wasted API calls, lets you manage multiple workspaces from one interface.
|
||||
|
||||
## How it works
|
||||
Just install it and its ready to go.
|
||||
For more information see https://github.com/3DTek-xyz/HumanAgent-MCP/blob/master/README-Additional.md
|
||||
## Installation
|
||||
|
||||
1. Install from VS Code Marketplace
|
||||
2. Copilot automatically gets the `HumanAgent_Chat` tool
|
||||
3. Done - no configuration needed
|
||||
|
||||
## How to Use
|
||||
|
||||
### Basic Workflow
|
||||
|
||||
1. **Ask Copilot to do something** - Copilot will use the HumanAgent_Chat tool
|
||||
2. **Chat panel opens** - Green dot = connected, shows Copilot's message
|
||||
3. **You respond** - Type your answer, click Send (or use Quick Replies)
|
||||
4. **Copilot continues** - Gets your response and proceeds with the task
|
||||
|
||||
### VS Code Interface
|
||||
|
||||
**Chat Panel** (left sidebar):
|
||||
- Green dot = connected to server
|
||||
- Red dot = disconnected (auto-reconnects)
|
||||
- Quick Replies = common responses like "Yes Please Proceed"
|
||||
- Text input = always enabled, send button only active when Copilot is waiting
|
||||
|
||||
**Cog Menu** (⚙️):
|
||||
- Show Status - check server state
|
||||
- Name This Chat - set session name
|
||||
- Open Web View - manage all workspaces in browser
|
||||
- Configure MCP - start/stop/restart server
|
||||
- Report Issue / Request Feature - GitHub links
|
||||
|
||||
### Web Interface
|
||||
|
||||
Open from cog menu → **Open Web View**
|
||||
|
||||
Access all workspace chats in one browser tab at `http://localhost:3737/HumanAgent`
|
||||
- See all conversations
|
||||
- Switch between workspaces
|
||||
- Append reminders to your responses
|
||||
|
||||
### Connection Status
|
||||
|
||||
- Auto-reconnects with exponential backoff (1s → 2s → 4s → 8s → 16s → 30s max)
|
||||
- Manually starting server resets reconnection immediately
|
||||
- No timeout - will retry forever
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Red dot / disconnected:**
|
||||
- Cog menu → Configure MCP → Start Server
|
||||
- Check VS Code Output panel for errors
|
||||
|
||||
**Server won't start:**
|
||||
- Check port 3737 not in use: `lsof -i :3737`
|
||||
- Restart VS Code
|
||||
|
||||
**Copilot not using the tool:**
|
||||
- Tool registers automatically on startup
|
||||
- Try: "Use HumanAgent_Chat to discuss this with me"
|
||||
|
||||
## Development
|
||||
|
||||
Press F5 to debug - dev mode uses port 3738, production uses 3737. No conflicts.
|
||||
|
||||
## More Info
|
||||
|
||||
See [README-Additional.md](README-Additional.md) for technical details
|
||||
|
||||
## Demo
|
||||
|
||||
|
||||
+4
-1
@@ -2,12 +2,15 @@
|
||||
"name": "humanagent-mcp",
|
||||
"displayName": "HumanAgent MCP",
|
||||
"description": "MCP server for chatting with a human agent",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"publisher": "3DTek-xyz",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/3DTek-xyz/HumanAgent-MCP.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/3DTek-xyz/HumanAgent-MCP/issues"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.105.0"
|
||||
},
|
||||
|
||||
@@ -778,3 +778,194 @@
|
||||
2025-11-19T04:29:21.690Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763524368377
|
||||
2025-11-19T04:29:57.436Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763526575920
|
||||
2025-11-19T04:32:45.235Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763526722087
|
||||
2025-11-19T04:33:48.134Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763526819438
|
||||
2025-11-19T04:34:16.012Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763526845435
|
||||
2025-11-19T04:34:57.910Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763526872411
|
||||
2025-11-19T04:35:30.329Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763526912183
|
||||
2025-11-19T04:42:49.067Z - RESPONSE ENDPOINT CALLED - RequestID: 8-1763526959059
|
||||
2025-11-19T04:45:04.786Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763527451877
|
||||
2025-11-19T04:49:47.000Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763527716744
|
||||
2025-11-19T04:55:16.435Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763527861868
|
||||
2025-11-19T04:59:50.456Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763528376951
|
||||
2025-11-19T05:01:19.407Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763528462801
|
||||
2025-11-19T05:04:42.383Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763528577693
|
||||
2025-11-19T05:06:29.667Z - RESPONSE ENDPOINT CALLED - RequestID: 8-1763528696961
|
||||
2025-11-19T05:07:24.608Z - RESPONSE ENDPOINT CALLED - RequestID: 9-1763528801381
|
||||
2025-11-19T05:08:14.209Z - RESPONSE ENDPOINT CALLED - RequestID: 10-1763528854833
|
||||
2025-11-19T05:12:13.762Z - RESPONSE ENDPOINT CALLED - RequestID: 11-1763529008920
|
||||
2025-11-19T05:19:05.309Z - RESPONSE ENDPOINT CALLED - RequestID: 12-1763529536141
|
||||
2025-11-19T05:20:58.609Z - RESPONSE ENDPOINT CALLED - RequestID: 13-1763529557247
|
||||
2025-11-19T05:21:24.226Z - RESPONSE ENDPOINT CALLED - RequestID: 14-1763529676333
|
||||
2025-11-19T05:23:58.629Z - RESPONSE ENDPOINT CALLED - RequestID: 15-1763529742758
|
||||
2025-11-19T05:24:58.350Z - RESPONSE ENDPOINT CALLED - RequestID: 16-1763529855270
|
||||
2025-11-19T05:26:59.273Z - RESPONSE ENDPOINT CALLED - RequestID: 17-1763529950545
|
||||
2025-11-19T05:27:26.007Z - RESPONSE ENDPOINT CALLED - RequestID: 18-1763530027487
|
||||
2025-11-19T05:32:43.864Z - RESPONSE ENDPOINT CALLED - RequestID: 19-1763530155910
|
||||
2025-11-19T05:34:02.832Z - RESPONSE ENDPOINT CALLED - RequestID: 20-1763530392944
|
||||
2025-11-19T05:35:37.296Z - RESPONSE ENDPOINT CALLED - RequestID: 21-1763530459824
|
||||
2025-11-19T05:36:48.254Z - RESPONSE ENDPOINT CALLED - RequestID: 22-1763530562725
|
||||
2025-11-19T05:37:03.432Z - RESPONSE ENDPOINT CALLED - RequestID: 23-1763530616447
|
||||
2025-11-19T05:38:49.736Z - RESPONSE ENDPOINT CALLED - RequestID: 24-1763530641355
|
||||
2025-11-19T05:43:18.272Z - RESPONSE ENDPOINT CALLED - RequestID: 25-1763530976990
|
||||
2025-11-19T05:43:55.025Z - RESPONSE ENDPOINT CALLED - RequestID: 26-1763531008352
|
||||
2025-11-19T05:44:47.170Z - RESPONSE ENDPOINT CALLED - RequestID: 27-1763531044237
|
||||
2025-11-19T05:46:39.445Z - RESPONSE ENDPOINT CALLED - RequestID: 28-1763531167181
|
||||
2025-11-19T05:47:41.254Z - RESPONSE ENDPOINT CALLED - RequestID: 29-1763531207378
|
||||
2025-11-19T05:48:56.742Z - RESPONSE ENDPOINT CALLED - RequestID: 30-1763531284022
|
||||
2025-11-19T05:51:01.388Z - RESPONSE ENDPOINT CALLED - RequestID: 31-1763531349420
|
||||
2025-11-19T05:51:49.445Z - RESPONSE ENDPOINT CALLED - RequestID: 32-1763531470730
|
||||
2025-11-19T05:52:10.855Z - RESPONSE ENDPOINT CALLED - RequestID: 33-1763531518577
|
||||
2025-11-19T05:53:56.343Z - RESPONSE ENDPOINT CALLED - RequestID: 34-1763531573352
|
||||
2025-11-19T05:54:49.345Z - RESPONSE ENDPOINT CALLED - RequestID: 35-1763531650439
|
||||
2025-11-19T05:55:15.471Z - RESPONSE ENDPOINT CALLED - RequestID: 36-1763531699205
|
||||
2025-11-19T05:57:32.926Z - RESPONSE ENDPOINT CALLED - RequestID: 37-1763531789516
|
||||
2025-11-19T05:59:07.146Z - RESPONSE ENDPOINT CALLED - RequestID: 38-1763531863167
|
||||
2025-11-19T06:01:20.500Z - RESPONSE ENDPOINT CALLED - RequestID: 39-1763532006609
|
||||
2025-11-19T06:03:26.499Z - RESPONSE ENDPOINT CALLED - RequestID: 40-1763532091039
|
||||
2025-11-19T06:07:16.659Z - RESPONSE ENDPOINT CALLED - RequestID: 41-1763532229913
|
||||
2025-11-19T06:08:22.324Z - RESPONSE ENDPOINT CALLED - RequestID: 42-1763532481534
|
||||
2025-11-19T06:09:50.729Z - RESPONSE ENDPOINT CALLED - RequestID: 43-1763532512158
|
||||
2025-11-19T06:10:20.481Z - RESPONSE ENDPOINT CALLED - RequestID: 44-1763532601928
|
||||
2025-11-19T06:16:59.293Z - RESPONSE ENDPOINT CALLED - RequestID: 45-1763532836868
|
||||
2025-11-19T06:18:41.715Z - RESPONSE ENDPOINT CALLED - RequestID: 46-1763533052927
|
||||
2025-11-19T06:22:59.308Z - RESPONSE ENDPOINT CALLED - RequestID: 47-1763533369141
|
||||
2025-11-19T06:26:41.436Z - RESPONSE ENDPOINT CALLED - RequestID: 48-1763533404832
|
||||
2025-11-19T06:28:55.389Z - RESPONSE ENDPOINT CALLED - RequestID: 49-1763533650222
|
||||
2025-11-19T06:29:46.242Z - RESPONSE ENDPOINT CALLED - RequestID: 50-1763533751783
|
||||
2025-11-19T06:30:58.430Z - RESPONSE ENDPOINT CALLED - RequestID: 51-1763533810706
|
||||
2025-11-19T06:31:53.669Z - RESPONSE ENDPOINT CALLED - RequestID: 52-1763533903911
|
||||
2025-11-19T06:32:57.297Z - RESPONSE ENDPOINT CALLED - RequestID: 53-1763533925834
|
||||
2025-11-19T06:34:23.028Z - RESPONSE ENDPOINT CALLED - RequestID: 54-1763533987917
|
||||
2025-11-19T06:36:53.700Z - RESPONSE ENDPOINT CALLED - RequestID: 55-1763534074733
|
||||
2025-11-19T06:37:48.746Z - RESPONSE ENDPOINT CALLED - RequestID: 56-1763534245667
|
||||
2025-11-19T06:39:28.879Z - RESPONSE ENDPOINT CALLED - RequestID: 57-1763534323294
|
||||
2025-11-19T06:40:15.185Z - RESPONSE ENDPOINT CALLED - RequestID: 58-1763534405032
|
||||
2025-11-19T06:42:03.705Z - RESPONSE ENDPOINT CALLED - RequestID: 59-1763534427529
|
||||
2025-11-19T06:42:29.829Z - RESPONSE ENDPOINT CALLED - RequestID: 60-1763534536644
|
||||
2025-11-19T06:46:47.931Z - RESPONSE ENDPOINT CALLED - RequestID: 61-1763534562112
|
||||
2025-11-19T06:48:01.522Z - RESPONSE ENDPOINT CALLED - RequestID: 62-1763534819187
|
||||
2025-11-19T06:49:09.371Z - RESPONSE ENDPOINT CALLED - RequestID: 63-1763534892654
|
||||
2025-11-19T06:50:01.028Z - RESPONSE ENDPOINT CALLED - RequestID: 64-1763534958161
|
||||
2025-11-19T06:50:40.898Z - RESPONSE ENDPOINT CALLED - RequestID: 65-1763535021144
|
||||
2025-11-19T06:52:14.106Z - RESPONSE ENDPOINT CALLED - RequestID: 66-1763535065297
|
||||
2025-11-19T06:53:15.775Z - RESPONSE ENDPOINT CALLED - RequestID: 67-1763535149720
|
||||
2025-11-19T06:55:25.120Z - RESPONSE ENDPOINT CALLED - RequestID: 68-1763535249396
|
||||
2025-11-19T06:56:19.622Z - RESPONSE ENDPOINT CALLED - RequestID: 69-1763535334209
|
||||
2025-11-19T06:57:31.059Z - RESPONSE ENDPOINT CALLED - RequestID: 70-1763535430753
|
||||
2025-11-19T06:57:59.741Z - RESPONSE ENDPOINT CALLED - RequestID: 71-1763535474468
|
||||
2025-11-19T08:44:00.119Z - RESPONSE ENDPOINT CALLED - RequestID: 72-1763535564494
|
||||
2025-11-19T08:44:21.339Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763541857967
|
||||
2025-11-19T08:45:05.334Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763541892164
|
||||
2025-11-19T08:47:09.867Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763542007214
|
||||
2025-11-19T08:49:21.690Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763542141507
|
||||
2025-11-19T08:50:01.921Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763542173722
|
||||
2025-11-19T08:52:57.598Z - RESPONSE ENDPOINT CALLED - RequestID: 8-1763542309601
|
||||
2025-11-19T08:53:30.662Z - RESPONSE ENDPOINT CALLED - RequestID: 9-1763542397476
|
||||
2025-11-19T08:55:02.059Z - RESPONSE ENDPOINT CALLED - RequestID: 10-1763542459775
|
||||
2025-11-19T08:56:38.094Z - RESPONSE ENDPOINT CALLED - RequestID: 11-1763542588136
|
||||
2025-11-19T08:57:46.774Z - RESPONSE ENDPOINT CALLED - RequestID: 12-1763542629436
|
||||
2025-11-19T08:58:12.370Z - RESPONSE ENDPOINT CALLED - RequestID: 13-1763542676505
|
||||
2025-11-19T08:59:43.388Z - RESPONSE ENDPOINT CALLED - RequestID: 14-1763542773907
|
||||
2025-11-19T09:02:44.331Z - RESPONSE ENDPOINT CALLED - RequestID: 15-1763542960322
|
||||
2025-11-19T09:03:40.040Z - RESPONSE ENDPOINT CALLED - RequestID: 16-1763542979028
|
||||
2025-11-19T09:05:39.675Z - RESPONSE ENDPOINT CALLED - RequestID: 17-1763543104064
|
||||
2025-11-19T09:08:32.499Z - RESPONSE ENDPOINT CALLED - RequestID: 18-1763543258846
|
||||
2025-11-19T09:09:47.437Z - RESPONSE ENDPOINT CALLED - RequestID: 19-1763543320605
|
||||
2025-11-19T09:10:42.324Z - RESPONSE ENDPOINT CALLED - RequestID: 20-1763543396400
|
||||
2025-11-19T09:11:09.702Z - RESPONSE ENDPOINT CALLED - RequestID: 21-1763543456136
|
||||
2025-11-19T09:12:31.519Z - RESPONSE ENDPOINT CALLED - RequestID: 22-1763543491254
|
||||
2025-11-19T09:14:25.136Z - RESPONSE ENDPOINT CALLED - RequestID: 23-1763543562040
|
||||
2025-11-19T09:15:49.128Z - RESPONSE ENDPOINT CALLED - RequestID: 24-1763543688599
|
||||
2025-11-19T09:16:20.816Z - RESPONSE ENDPOINT CALLED - RequestID: 25-1763543766068
|
||||
2025-11-19T09:18:55.824Z - RESPONSE ENDPOINT CALLED - RequestID: 26-1763543827719
|
||||
2025-11-19T09:19:59.438Z - RESPONSE ENDPOINT CALLED - RequestID: 27-1763543948652
|
||||
2025-11-19T09:20:10.054Z - RESPONSE ENDPOINT CALLED - RequestID: 28-1763544008080
|
||||
2025-11-19T09:22:28.814Z - RESPONSE ENDPOINT CALLED - RequestID: 29-1763544123183
|
||||
2025-11-19T09:23:12.876Z - RESPONSE ENDPOINT CALLED - RequestID: 30-1763544179186
|
||||
2025-11-19T09:25:23.109Z - RESPONSE ENDPOINT CALLED - RequestID: 31-1763544220049
|
||||
2025-11-19T09:26:06.061Z - RESPONSE ENDPOINT CALLED - RequestID: 32-1763544345418
|
||||
2025-11-19T09:28:18.087Z - RESPONSE ENDPOINT CALLED - RequestID: 33-1763544459317
|
||||
2025-11-19T09:29:30.957Z - RESPONSE ENDPOINT CALLED - RequestID: 34-1763544517243
|
||||
2025-11-19T09:30:42.612Z - RESPONSE ENDPOINT CALLED - RequestID: 35-1763544582928
|
||||
2025-11-19T09:33:30.240Z - RESPONSE ENDPOINT CALLED - RequestID: 36-1763544694667
|
||||
2025-11-19T09:34:36.716Z - RESPONSE ENDPOINT CALLED - RequestID: 37-1763544851336
|
||||
2025-11-19T09:36:00.376Z - RESPONSE ENDPOINT CALLED - RequestID: 38-1763544920027
|
||||
2025-11-19T09:37:12.837Z - RESPONSE ENDPOINT CALLED - RequestID: 39-1763545005402
|
||||
2025-11-19T09:39:04.091Z - RESPONSE ENDPOINT CALLED - RequestID: 40-1763545057908
|
||||
2025-11-19T09:40:20.777Z - RESPONSE ENDPOINT CALLED - RequestID: 41-1763545196157
|
||||
2025-11-19T09:40:51.375Z - RESPONSE ENDPOINT CALLED - RequestID: 42-1763545233558
|
||||
2025-11-19T09:43:38.208Z - RESPONSE ENDPOINT CALLED - RequestID: 43-1763545338775
|
||||
2025-11-19T09:44:58.607Z - RESPONSE ENDPOINT CALLED - RequestID: 44-1763545471392
|
||||
2025-11-19T09:45:35.982Z - RESPONSE ENDPOINT CALLED - RequestID: 45-1763545523406
|
||||
2025-11-19T09:46:35.672Z - RESPONSE ENDPOINT CALLED - RequestID: 46-1763545576024
|
||||
2025-11-19T09:47:44.198Z - RESPONSE ENDPOINT CALLED - RequestID: 47-1763545616106
|
||||
2025-11-19T09:49:49.743Z - RESPONSE ENDPOINT CALLED - RequestID: 48-1763545704123
|
||||
2025-11-19T09:51:12.886Z - RESPONSE ENDPOINT CALLED - RequestID: 49-1763545861099
|
||||
2025-11-19T09:52:32.298Z - RESPONSE ENDPOINT CALLED - RequestID: 50-1763545890279
|
||||
2025-11-19T09:54:45.555Z - RESPONSE ENDPOINT CALLED - RequestID: 51-1763546054209
|
||||
2025-11-19T09:55:34.779Z - RESPONSE ENDPOINT CALLED - RequestID: 52-1763546098453
|
||||
2025-11-19T09:56:21.993Z - RESPONSE ENDPOINT CALLED - RequestID: 53-1763546142824
|
||||
2025-11-19T09:57:29.675Z - RESPONSE ENDPOINT CALLED - RequestID: 54-1763546204281
|
||||
2025-11-19T09:58:10.026Z - RESPONSE ENDPOINT CALLED - RequestID: 55-1763546260063
|
||||
2025-11-19T09:59:17.253Z - RESPONSE ENDPOINT CALLED - RequestID: 56-1763546300732
|
||||
2025-11-19T09:59:55.499Z - RESPONSE ENDPOINT CALLED - RequestID: 57-1763546367439
|
||||
2025-11-19T10:08:47.884Z - RESPONSE ENDPOINT CALLED - RequestID: 58-1763546915203
|
||||
2025-11-19T10:09:45.771Z - RESPONSE ENDPOINT CALLED - RequestID: 59-1763546957364
|
||||
2025-11-19T10:10:32.461Z - RESPONSE ENDPOINT CALLED - RequestID: 60-1763546994227
|
||||
2025-11-19T10:11:18.173Z - RESPONSE ENDPOINT CALLED - RequestID: 61-1763547058787
|
||||
2025-11-19T10:13:13.127Z - RESPONSE ENDPOINT CALLED - RequestID: 62-1763547097631
|
||||
2025-11-19T10:13:54.779Z - RESPONSE ENDPOINT CALLED - RequestID: 63-1763547217769
|
||||
2025-11-19T10:15:41.739Z - RESPONSE ENDPOINT CALLED - RequestID: 64-1763547322095
|
||||
2025-11-19T10:17:50.587Z - RESPONSE ENDPOINT CALLED - RequestID: 65-1763547358685
|
||||
2025-11-19T10:20:27.752Z - RESPONSE ENDPOINT CALLED - RequestID: 66-1763547609570
|
||||
2025-11-19T10:23:34.759Z - RESPONSE ENDPOINT CALLED - RequestID: 67-1763547636532
|
||||
2025-11-19T10:33:20.859Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763548391770
|
||||
2025-11-19T10:34:12.648Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763548410172
|
||||
2025-11-19T10:35:45.765Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763548538365
|
||||
2025-11-19T10:36:12.704Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763548557506
|
||||
2025-11-19T10:37:27.017Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763548590890
|
||||
2025-11-19T10:39:46.306Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763548726461
|
||||
2025-11-19T21:45:54.510Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763588690585
|
||||
2025-11-19T21:48:37.449Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763588788581
|
||||
2025-11-19T21:49:28.708Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763588935093
|
||||
2025-11-19T21:50:22.203Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763588987898
|
||||
2025-11-19T21:51:20.790Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763589037769
|
||||
2025-11-19T21:53:07.762Z - RESPONSE ENDPOINT CALLED - RequestID: 8-1763589095090
|
||||
2025-11-19T21:54:43.612Z - RESPONSE ENDPOINT CALLED - RequestID: 9-1763589204404
|
||||
2025-11-19T21:57:07.919Z - RESPONSE ENDPOINT CALLED - RequestID: 10-1763589296875
|
||||
2025-11-19T21:58:36.437Z - RESPONSE ENDPOINT CALLED - RequestID: 11-1763589457589
|
||||
2025-11-19T21:59:37.813Z - RESPONSE ENDPOINT CALLED - RequestID: 12-1763589534887
|
||||
2025-11-19T22:00:44.814Z - RESPONSE ENDPOINT CALLED - RequestID: 13-1763589596478
|
||||
2025-11-19T22:01:27.653Z - RESPONSE ENDPOINT CALLED - RequestID: 14-1763589662696
|
||||
2025-11-19T22:02:18.985Z - RESPONSE ENDPOINT CALLED - RequestID: 15-1763589708160
|
||||
2025-11-19T22:05:49.938Z - RESPONSE ENDPOINT CALLED - RequestID: 16-1763589775471
|
||||
2025-11-19T22:09:01.630Z - RESPONSE ENDPOINT CALLED - RequestID: 17-1763589970915
|
||||
2025-11-19T22:11:34.703Z - RESPONSE ENDPOINT CALLED - RequestID: 18-1763590154658
|
||||
2025-11-19T22:17:21.026Z - RESPONSE ENDPOINT CALLED - RequestID: 19-1763590464990
|
||||
2025-11-19T22:18:11.331Z - RESPONSE ENDPOINT CALLED - RequestID: 20-1763590652454
|
||||
2025-11-19T22:19:33.533Z - RESPONSE ENDPOINT CALLED - RequestID: 21-1763590713436
|
||||
2025-11-19T22:21:39.021Z - RESPONSE ENDPOINT CALLED - RequestID: 22-1763590830807
|
||||
2025-11-19T22:23:07.848Z - RESPONSE ENDPOINT CALLED - RequestID: 23-1763590968266
|
||||
2025-11-19T22:24:28.895Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763591024982
|
||||
2025-11-19T22:25:39.328Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763591108976
|
||||
2025-11-19T22:26:05.856Z - RESPONSE ENDPOINT CALLED - RequestID: 24-1763591140051
|
||||
2025-11-19T22:28:02.420Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763591157359
|
||||
2025-11-19T22:30:03.717Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763591314014
|
||||
2025-11-19T22:32:06.688Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763591499382
|
||||
2025-11-19T22:32:21.140Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763591532471
|
||||
2025-11-19T22:37:45.607Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763591415766
|
||||
2025-11-19T22:39:27.868Z - RESPONSE ENDPOINT CALLED - RequestID: 25-1763591299640
|
||||
2025-11-19T22:44:07.100Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763592071629
|
||||
2025-11-19T22:50:36.327Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763592630513
|
||||
2025-11-19T22:51:50.138Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763592645010
|
||||
2025-11-19T22:54:09.849Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763592745152
|
||||
2025-11-19T22:57:41.548Z - RESPONSE ENDPOINT CALLED - RequestID: 6-1763592881661
|
||||
2025-11-19T22:58:29.548Z - RESPONSE ENDPOINT CALLED - RequestID: 7-1763593071008
|
||||
2025-11-19T23:02:06.029Z - RESPONSE ENDPOINT CALLED - RequestID: 8-1763593228438
|
||||
2025-11-19T23:03:03.239Z - RESPONSE ENDPOINT CALLED - RequestID: 9-1763593335464
|
||||
2025-11-19T23:03:48.859Z - RESPONSE ENDPOINT CALLED - RequestID: 10-1763593421887
|
||||
2025-11-19T23:04:14.385Z - RESPONSE ENDPOINT CALLED - RequestID: 11-1763593442536
|
||||
2025-11-20T00:57:40.643Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763600226770
|
||||
2025-11-20T00:59:12.862Z - RESPONSE ENDPOINT CALLED - RequestID: 4-1763600290621
|
||||
2025-11-20T01:00:22.818Z - RESPONSE ENDPOINT CALLED - RequestID: 5-1763600364506
|
||||
2025-11-20T01:06:31.582Z - RESPONSE ENDPOINT CALLED - RequestID: 3-1763600774684
|
||||
|
||||
+63
-18
@@ -12,6 +12,7 @@ let chatTreeProvider: ChatTreeProvider;
|
||||
let mcpConfigManager: McpConfigManager;
|
||||
let workspaceSessionId: string;
|
||||
let serverManager: ServerManager;
|
||||
let SERVER_PORT: number; // Dynamic port: 3738 for dev, 3737 for production
|
||||
|
||||
// MCP Server Definition Provider for VS Code native MCP integration
|
||||
class HumanAgentMcpProvider implements vscode.McpServerDefinitionProvider {
|
||||
@@ -19,11 +20,11 @@ class HumanAgentMcpProvider implements vscode.McpServerDefinitionProvider {
|
||||
readonly onDidChangeMcpServerDefinitions = this._onDidChangeMcpServerDefinitions.event;
|
||||
private serverVersion: string = Date.now().toString();
|
||||
|
||||
constructor(private sessionId: string) {}
|
||||
constructor(private sessionId: string, private port: number) {}
|
||||
|
||||
provideMcpServerDefinitions(token: vscode.CancellationToken): vscode.ProviderResult<vscode.McpHttpServerDefinition[]> {
|
||||
// Use separate endpoint for MCP tools to avoid SSE conflicts with webview
|
||||
const serverUrl = `http://127.0.0.1:3737/mcp-tools?sessionId=${this.sessionId}`;
|
||||
const serverUrl = `http://127.0.0.1:${this.port}/mcp-tools?sessionId=${this.sessionId}`;
|
||||
const serverUri = vscode.Uri.parse(serverUrl);
|
||||
const server = new vscode.McpHttpServerDefinition('HumanAgent MCP', serverUri, {}, this.serverVersion);
|
||||
console.log(`HumanAgent MCP: Using separate MCP tools endpoint to avoid SSE conflicts (version: ${this.serverVersion})`);
|
||||
@@ -111,17 +112,21 @@ async function restoreSessionName(context: vscode.ExtensionContext, sessionId: s
|
||||
}
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
console.log('HumanAgent MCP extension is now active!');
|
||||
console.log('HumanAgent MCP extension activated!');
|
||||
|
||||
// Determine port based on extension mode (dev vs production)
|
||||
SERVER_PORT = context.extensionMode === vscode.ExtensionMode.Development ? 3738 : 3737;
|
||||
console.log(`Using port ${SERVER_PORT} (${context.extensionMode === vscode.ExtensionMode.Development ? 'development' : 'production'} mode);`);
|
||||
|
||||
// Generate or retrieve persistent workspace session ID
|
||||
workspaceSessionId = getWorkspaceSessionId(context);
|
||||
|
||||
// Initialize MCP Configuration Manager
|
||||
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||
mcpConfigManager = new McpConfigManager(workspaceRoot, context.extensionPath);
|
||||
mcpConfigManager = new McpConfigManager(workspaceRoot, context.extensionPath, SERVER_PORT);
|
||||
|
||||
// Initialize and register VS Code native MCP provider
|
||||
mcpProvider = new HumanAgentMcpProvider(workspaceSessionId);
|
||||
mcpProvider = new HumanAgentMcpProvider(workspaceSessionId, SERVER_PORT);
|
||||
context.subscriptions.push(vscode.lm.registerMcpServerDefinitionProvider('humanagent-mcp.server', mcpProvider));
|
||||
console.log('HumanAgent MCP: Registered MCP server definition provider');
|
||||
|
||||
@@ -144,7 +149,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
const serverOptions: any = {
|
||||
serverPath: serverPath,
|
||||
port: 3737,
|
||||
port: SERVER_PORT,
|
||||
host: '127.0.0.1',
|
||||
loggingEnabled: loggingEnabled,
|
||||
loggingLevel: loggingLevel
|
||||
@@ -208,7 +213,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
});
|
||||
|
||||
// Initialize Chat Webview Provider (no internal server dependency)
|
||||
const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, null, mcpConfigManager, workspaceSessionId, context, mcpProvider);
|
||||
const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, null, mcpConfigManager, workspaceSessionId, context, mcpProvider, SERVER_PORT);
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerWebviewViewProvider(ChatWebviewProvider.viewType, chatWebviewProvider)
|
||||
);
|
||||
@@ -255,6 +260,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
const success = await serverManager.ensureServerRunning();
|
||||
if (success) {
|
||||
vscode.window.showInformationMessage('HumanAgent MCP Server started successfully!');
|
||||
// Notify webview to reset reconnection backoff and try immediately
|
||||
chatWebviewProvider.notifyServerStarted();
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Failed to start HumanAgent MCP Server. Check the logs for details.');
|
||||
}
|
||||
@@ -265,11 +272,47 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
const stopServerCommand = vscode.commands.registerCommand('humanagent-mcp.stopServer', async () => {
|
||||
try {
|
||||
const success = await serverManager.stopServer();
|
||||
if (success) {
|
||||
// First try HTTP shutdown endpoint (works from any VS Code window or client)
|
||||
try {
|
||||
const http = require('http');
|
||||
const options = {
|
||||
hostname: '127.0.0.1',
|
||||
port: SERVER_PORT,
|
||||
path: '/shutdown',
|
||||
method: 'POST',
|
||||
timeout: 5000
|
||||
};
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const req = http.request(options, (res: any) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk: any) => data += chunk);
|
||||
res.on('end', () => {
|
||||
if (res.statusCode === 200) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`HTTP ${res.statusCode}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.on('timeout', () => {
|
||||
req.destroy();
|
||||
reject(new Error('Request timeout'));
|
||||
});
|
||||
req.end();
|
||||
});
|
||||
|
||||
vscode.window.showInformationMessage('HumanAgent MCP Server stopped successfully!');
|
||||
} else {
|
||||
vscode.window.showWarningMessage('Server may not have been running or failed to stop cleanly.');
|
||||
} catch (httpError) {
|
||||
// Fallback to PID kill if HTTP fails
|
||||
console.log('HTTP shutdown failed, trying PID kill:', httpError);
|
||||
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}`);
|
||||
@@ -283,6 +326,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
const success = await serverManager.ensureServerRunning();
|
||||
if (success) {
|
||||
vscode.window.showInformationMessage('HumanAgent MCP Server restarted successfully!');
|
||||
// Notify webview to reset reconnection backoff and try immediately
|
||||
chatWebviewProvider.notifyServerStarted();
|
||||
} else {
|
||||
vscode.window.showErrorMessage('Failed to restart HumanAgent MCP Server. Check the logs for details.');
|
||||
}
|
||||
@@ -410,7 +455,7 @@ async function isPortInUse(port: number): Promise<boolean> {
|
||||
// Check if MCP server is accessible and responding with retry
|
||||
async function isServerAccessible(): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/sessions', {
|
||||
const response = await fetch(`http://127.0.0.1:${SERVER_PORT}/sessions`, {
|
||||
method: 'GET',
|
||||
signal: AbortSignal.timeout(5000) // 5 second timeout
|
||||
});
|
||||
@@ -422,7 +467,7 @@ async function isServerAccessible(): Promise<boolean> {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
try {
|
||||
const retryResponse = await fetch('http://127.0.0.1:3737/sessions', {
|
||||
const retryResponse = await fetch(`http://127.0.0.1:${SERVER_PORT}/sessions`, {
|
||||
method: 'GET',
|
||||
signal: AbortSignal.timeout(5000)
|
||||
});
|
||||
@@ -442,7 +487,7 @@ async function isServerAccessible(): Promise<boolean> {
|
||||
// Check if session exists on server by testing a simple MCP call with retry
|
||||
async function validateSessionWithServer(sessionId: string): Promise<boolean> {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/mcp', {
|
||||
const response = await fetch(`http://127.0.0.1:${SERVER_PORT}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -466,7 +511,7 @@ async function validateSessionWithServer(sessionId: string): Promise<boolean> {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
try {
|
||||
const retryResponse = await fetch('http://127.0.0.1:3737/mcp', {
|
||||
const retryResponse = await fetch(`http://127.0.0.1:${SERVER_PORT}/mcp`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
@@ -516,7 +561,7 @@ async function registerSessionWithStandaloneServer(sessionId: string, forceRereg
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/sessions/register', {
|
||||
const response = await fetch(`http://127.0.0.1:${SERVER_PORT}/sessions/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(requestBody)
|
||||
@@ -536,7 +581,7 @@ async function registerSessionWithStandaloneServer(sessionId: string, forceRereg
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
try {
|
||||
const retryResponse = await fetch('http://127.0.0.1:3737/sessions/register', {
|
||||
const retryResponse = await fetch(`http://127.0.0.1:${SERVER_PORT}/sessions/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(requestBody)
|
||||
@@ -560,7 +605,7 @@ async function registerSessionWithStandaloneServer(sessionId: string, forceRereg
|
||||
// Unregister session with standalone server via HTTP
|
||||
async function unregisterSessionWithStandaloneServer(sessionId: string): Promise<void> {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/sessions/unregister', {
|
||||
const response = await fetch(`http://127.0.0.1:${SERVER_PORT}/sessions/unregister`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionId })
|
||||
|
||||
@@ -20,7 +20,7 @@ export class McpConfigManager {
|
||||
private static readonly SERVER_NAME = 'humanagent-mcp';
|
||||
private static readonly GLOBAL_CONFIG_KEY = 'mcp.servers';
|
||||
|
||||
constructor(private workspaceRoot?: string, private extensionPath?: string) {
|
||||
constructor(private workspaceRoot?: string, private extensionPath?: string, private port: number = 3737) {
|
||||
if (!extensionPath) {
|
||||
throw new Error('Extension path is required');
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export class McpConfigManager {
|
||||
// Configure our MCP server (HTTP transport) - no sessionId in URL
|
||||
const serverConfig: any = {
|
||||
type: 'http',
|
||||
url: 'http://127.0.0.1:3737/mcp'
|
||||
url: `http://127.0.0.1:${this.port}/mcp`
|
||||
};
|
||||
|
||||
// Add our server to the config
|
||||
@@ -98,7 +98,7 @@ export class McpConfigManager {
|
||||
// Configure our MCP server (HTTP transport) - no sessionId in URL
|
||||
const serverConfig: any = {
|
||||
type: 'http',
|
||||
url: 'http://127.0.0.1:3737/mcp'
|
||||
url: `http://127.0.0.1:${this.port}/mcp`
|
||||
};
|
||||
|
||||
// Get current global MCP servers configuration
|
||||
|
||||
@@ -15,7 +15,9 @@ class StandaloneMcpServer {
|
||||
// Use the parent directory of the dist folder as workspace path
|
||||
// This ensures log file is created where it can be properly cleared
|
||||
const workspacePath = require('path').resolve(__dirname, '..');
|
||||
this.server = new McpServer(undefined, workspacePath);
|
||||
// Get port from environment variable (set by ServerManager)
|
||||
const port = process.env.HUMANAGENT_MCP_PORT ? parseInt(process.env.HUMANAGENT_MCP_PORT) : undefined;
|
||||
this.server = new McpServer(undefined, workspacePath, port);
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
|
||||
+91
-4
@@ -127,8 +127,11 @@ export class McpServer extends EventEmitter {
|
||||
private sseClients: Map<string, http.ServerResponse> = new Map(); // Per-session SSE connections (VS Code webviews)
|
||||
private webInterfaceConnections: Set<http.ServerResponse> = new Set(); // Web interface connections (all browsers)
|
||||
|
||||
constructor(private sessionId?: string, private workspacePath?: string) {
|
||||
constructor(private sessionId?: string, private workspacePath?: string, port?: number) {
|
||||
super();
|
||||
if (port) {
|
||||
this.port = port;
|
||||
}
|
||||
this.debugLogger = new DebugLogger(this.workspacePath);
|
||||
this.chatManager = new ChatManager(this.debugLogger); // Initialize centralized chat management with logging
|
||||
|
||||
@@ -583,6 +586,10 @@ export class McpServer extends EventEmitter {
|
||||
// Session management, response, tools, reload, messages, and chat endpoints
|
||||
await this.handleSessionEndpoint(req, res);
|
||||
return;
|
||||
} else if (req.url === '/shutdown' && req.method === 'POST') {
|
||||
// Server shutdown endpoint - allows any client to gracefully stop the server
|
||||
await this.handleShutdownEndpoint(req, res);
|
||||
return;
|
||||
} else {
|
||||
this.debugLogger.log('HTTP', `404 - Invalid endpoint: ${req.url}`);
|
||||
res.statusCode = 404;
|
||||
@@ -822,6 +829,30 @@ export class McpServer extends EventEmitter {
|
||||
res.end('Method Not Allowed');
|
||||
}
|
||||
|
||||
private async handleShutdownEndpoint(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
||||
this.debugLogger.log('INFO', 'Shutdown request received via HTTP');
|
||||
|
||||
try {
|
||||
// Send success response immediately before shutting down
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, message: 'Server shutting down...' }));
|
||||
|
||||
// Give response time to send before stopping
|
||||
setTimeout(async () => {
|
||||
this.debugLogger.log('INFO', 'Initiating server shutdown...');
|
||||
await this.stop();
|
||||
process.exit(0);
|
||||
}, 500);
|
||||
|
||||
} catch (error) {
|
||||
this.debugLogger.log('ERROR', 'Shutdown error:', error);
|
||||
res.statusCode = 500;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: false, error: String(error) }));
|
||||
}
|
||||
}
|
||||
|
||||
private async handleMcpToolsEndpoint(req: http.IncomingMessage, res: http.ServerResponse, reqUrl: URL): Promise<void> {
|
||||
// MCP tools endpoint - handles MCP protocol for VS Code extension without SSE conflicts
|
||||
this.debugLogger.log('HTTP', `MCP Tools: ${req.method} ${req.url}`);
|
||||
@@ -1260,6 +1291,9 @@ export class McpServer extends EventEmitter {
|
||||
padding: 10px 15px;
|
||||
background-color: var(--vscode-panel-background);
|
||||
border-bottom: 1px solid var(--vscode-border);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
@@ -1267,6 +1301,29 @@ export class McpServer extends EventEmitter {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.shutdown-button {
|
||||
background-color: #d73a49;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.shutdown-button:hover {
|
||||
background-color: #cb2431;
|
||||
}
|
||||
|
||||
.shutdown-button svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
background-color: var(--vscode-panel-background);
|
||||
@@ -1485,6 +1542,12 @@ export class McpServer extends EventEmitter {
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1><span class="status-indicator"></span>HumanAgent Multi-Session Chat</h1>
|
||||
<button class="shutdown-button" onclick="shutdownServer()" title="Stop Server">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path d="M8 0a1 1 0 0 1 1 1v6a1 1 0 1 1-2 0V1a1 1 0 0 1 1-1z"/>
|
||||
<path d="M11.5 3.5a5 5 0 1 1-7 0 1 1 0 0 1 1.4-1.4 3 3 0 1 0 4.2 0 1 1 0 0 1 1.4 1.4z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="tabs-container" id="tabs">
|
||||
@@ -1522,6 +1585,30 @@ export class McpServer extends EventEmitter {
|
||||
|
||||
// Web interface is stateless - gets pending requests from server state
|
||||
|
||||
// Server shutdown function
|
||||
async function shutdownServer() {
|
||||
if (!confirm('Are you sure you want to stop the server? This will disconnect all clients.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/shutdown', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('Server is shutting down...');
|
||||
// Close the window after a moment
|
||||
setTimeout(() => window.close(), 1000);
|
||||
} else {
|
||||
alert('Failed to stop server: ' + response.statusText);
|
||||
}
|
||||
} catch (error) {
|
||||
alert('Error stopping server: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Tab switching
|
||||
document.getElementById('tabs').addEventListener('click', (e) => {
|
||||
if (e.target.classList.contains('tab')) {
|
||||
@@ -1692,11 +1779,11 @@ export class McpServer extends EventEmitter {
|
||||
} catch (error) {
|
||||
console.error('Failed to send response:', error);
|
||||
addMessageToUI(sessionId, 'assistant', \`Error: \${error.message}\`, null, null);
|
||||
} finally {
|
||||
// Re-enable send button
|
||||
// Re-enable button only on error since we won't get SSE state update
|
||||
button.disabled = false;
|
||||
textarea.focus();
|
||||
}
|
||||
// Note: Button is re-enabled by SSE 'waiting_for_response' state, not here
|
||||
textarea.focus();
|
||||
}
|
||||
|
||||
function addMessageToUI(sessionId, role, content, source, timestamp) {
|
||||
|
||||
@@ -184,7 +184,9 @@ export class ServerManager {
|
||||
...process.env,
|
||||
// Pass logging configuration from extension settings
|
||||
HUMANAGENT_LOGGING_ENABLED: this.options.loggingEnabled ? 'true' : 'false',
|
||||
HUMANAGENT_LOGGING_LEVEL: this.options.loggingLevel || 'INFO'
|
||||
HUMANAGENT_LOGGING_LEVEL: this.options.loggingLevel || 'INFO',
|
||||
// Pass port to standalone server
|
||||
HUMANAGENT_MCP_PORT: this.options.port.toString()
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
mcpConfigManager?: McpConfigManager,
|
||||
private readonly workspaceSessionId?: string,
|
||||
private readonly context?: vscode.ExtensionContext,
|
||||
private readonly mcpProvider?: any
|
||||
private readonly mcpProvider?: any,
|
||||
private readonly port: number = 3737
|
||||
) {
|
||||
this.mcpServer = mcpServer;
|
||||
this.mcpConfigManager = mcpConfigManager;
|
||||
@@ -117,6 +118,14 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
this.updateWebview();
|
||||
}
|
||||
|
||||
public notifyServerStarted() {
|
||||
if (this._view) {
|
||||
this._view.webview.postMessage({
|
||||
type: 'serverStarted'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resolveWebviewView(webviewView: vscode.WebviewView, context: vscode.WebviewViewResolveContext, _token: vscode.CancellationToken) {
|
||||
this._view = webviewView;
|
||||
|
||||
@@ -181,7 +190,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
responseBody.images = images;
|
||||
}
|
||||
|
||||
const response = await fetch('http://localhost:3737/response', {
|
||||
const response = await fetch(`http://localhost:${this.port}/response`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -279,7 +288,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
// Get current tool configuration from server - NO FALLBACKS!
|
||||
const response = await fetch('http://localhost:3737/tools');
|
||||
const response = await fetch(`http://localhost:${this.port}/tools`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch tools from server: ${response.status}`);
|
||||
}
|
||||
@@ -406,6 +415,12 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
case 'openWebView':
|
||||
await this.openWebInterface();
|
||||
break;
|
||||
case 'reportIssue':
|
||||
vscode.env.openExternal(vscode.Uri.parse('https://github.com/3DTek-xyz/HumanAgent-MCP/issues/new'));
|
||||
break;
|
||||
case 'requestFeature':
|
||||
vscode.env.openExternal(vscode.Uri.parse('https://github.com/3DTek-xyz/HumanAgent-MCP/issues/new'));
|
||||
break;
|
||||
}
|
||||
|
||||
// Update status after action
|
||||
@@ -443,7 +458,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
// Send session name to server
|
||||
const response = await fetch('http://localhost:3737/sessions/name', {
|
||||
const response = await fetch(`http://localhost:${this.port}/sessions/name`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@@ -495,7 +510,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
private async openWebInterface() {
|
||||
try {
|
||||
const webUrl = 'http://localhost:3737/HumanAgent';
|
||||
const webUrl = `http://localhost:${this.port}/HumanAgent`;
|
||||
|
||||
// Open in external browser
|
||||
await vscode.env.openExternal(vscode.Uri.parse(webUrl));
|
||||
@@ -788,7 +803,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
<div class="input-area">
|
||||
<div class="input-container">
|
||||
<input type="text" class="message-input" id="messageInput" placeholder="Type your response..." ${hasPendingResponse ? '' : 'disabled'}>
|
||||
<input type="text" class="message-input" id="messageInput" placeholder="Type your response...">
|
||||
<select class="quick-replies" id="quickReplies" onchange="selectQuickReply()" ${hasPendingResponse ? '' : 'disabled'}>
|
||||
<option value="">Quick Replies...</option>
|
||||
<option value="Yes Please Proceed">Yes Please Proceed</option>
|
||||
@@ -968,13 +983,12 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
{ text: '📊 Show Status', action: 'requestServerStatus' },
|
||||
{ text: window.overrideFileExists ? '📁 Recreate Override File' : '📁 Create Override File', action: 'overridePrompt' },
|
||||
{ text: '📝 Name This Chat', action: 'nameSession' },
|
||||
{ text: '🌐 Open Web View', action: 'openWebView' }
|
||||
{ text: '🌐 Open Web View', action: 'openWebView' },
|
||||
{ text: '⚙️ Configure MCP', action: 'configure' },
|
||||
{ text: '🐛 Report Issue', action: 'reportIssue' },
|
||||
{ text: '💡 Request Feature', action: 'requestFeature' }
|
||||
];
|
||||
|
||||
// Override file changes require VS Code restart/reload to take effect
|
||||
|
||||
options.push({ text: '⚙️ Configure MCP', action: 'configure' });
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -1025,12 +1039,49 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
// Update override file existence and refresh cog menu
|
||||
window.overrideFileExists = message.exists;
|
||||
console.log('Updated overrideFileExists to:', message.exists);
|
||||
} else if (message.type === 'serverStarted') {
|
||||
// Server was manually started - reset backoff and reconnect immediately
|
||||
console.log('🚀 Server started - resetting reconnection backoff and reconnecting immediately');
|
||||
reconnectAttempts = 0;
|
||||
if (reconnectTimeout) {
|
||||
clearTimeout(reconnectTimeout);
|
||||
}
|
||||
connectionInProgress = false;
|
||||
setupSSEConnection();
|
||||
}
|
||||
});
|
||||
|
||||
// Set up SSE connection for real-time server events
|
||||
let currentEventSource = null;
|
||||
let connectionInProgress = false;
|
||||
let reconnectAttempts = 0;
|
||||
let reconnectTimeout = null;
|
||||
const MAX_RECONNECT_DELAY = 30000; // 30 seconds max
|
||||
const BASE_RECONNECT_DELAY = 1000; // Start at 1 second
|
||||
|
||||
function updateConnectionStatus(connected, error = false) {
|
||||
const statusElement = document.getElementById('server-status-text');
|
||||
const statusDot = document.querySelector('.status-dot');
|
||||
|
||||
if (statusElement) {
|
||||
if (connected) {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Connected)';
|
||||
if (statusDot) statusDot.style.backgroundColor = '#4caf50';
|
||||
} else if (error) {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Disconnected)';
|
||||
if (statusDot) statusDot.style.backgroundColor = '#f44336';
|
||||
} else {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Connecting...)';
|
||||
if (statusDot) statusDot.style.backgroundColor = '#ff9800';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getReconnectDelay() {
|
||||
// Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s, 30s, ...
|
||||
const delay = Math.min(BASE_RECONNECT_DELAY * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY);
|
||||
return delay;
|
||||
}
|
||||
|
||||
function setupSSEConnection() {
|
||||
if (connectionInProgress) {
|
||||
@@ -1048,7 +1099,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
console.log('Setting up SSE connection to MCP server for session:', sessionId);
|
||||
const eventSource = new EventSource(\`http://localhost:3737/mcp?sessionId=\${sessionId}\`);
|
||||
const eventSource = new EventSource(\`http://localhost:${this.port}/mcp?sessionId=\${sessionId}\`);
|
||||
currentEventSource = eventSource;
|
||||
|
||||
// Enhanced connection health monitoring
|
||||
@@ -1072,7 +1123,12 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
console.error(' - Reconnecting...');
|
||||
eventSource.close();
|
||||
connectionInProgress = false;
|
||||
setTimeout(setupSSEConnection, 1000);
|
||||
updateConnectionStatus(false, true);
|
||||
const delay = getReconnectDelay();
|
||||
reconnectAttempts++;
|
||||
console.log('🔄 Reconnecting after heartbeat timeout in ' + (delay/1000) + 's (attempt #' + reconnectAttempts + ')...');
|
||||
if (reconnectTimeout) clearTimeout(reconnectTimeout);
|
||||
reconnectTimeout = setTimeout(setupSSEConnection, delay);
|
||||
}, 25000); // Timeout after 25 seconds (2.5x heartbeat interval)
|
||||
}
|
||||
|
||||
@@ -1084,6 +1140,8 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
connectionStartTime = Date.now();
|
||||
messageCount = 0;
|
||||
connectionInProgress = false; // Connection successful, allow future connections
|
||||
reconnectAttempts = 0; // Reset backoff on successful connection
|
||||
updateConnectionStatus(true);
|
||||
resetHeartbeatTimeout();
|
||||
};
|
||||
|
||||
@@ -1131,10 +1189,25 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
const stateNames = ['CONNECTING', 'OPEN', 'CLOSED'];
|
||||
console.error(' EventSource state:', stateNames[eventSource.readyState] || 'UNKNOWN');
|
||||
|
||||
// Reset connection state and try to reconnect after 5 seconds
|
||||
// CRITICAL: Close the EventSource to prevent automatic browser reconnection
|
||||
eventSource.close();
|
||||
|
||||
// Update status to disconnected
|
||||
updateConnectionStatus(false, true);
|
||||
|
||||
// Reset connection state and try to reconnect with exponential backoff
|
||||
connectionInProgress = false;
|
||||
console.log('🔄 Reconnecting SSE in 5 seconds...');
|
||||
setTimeout(setupSSEConnection, 5000);
|
||||
const delay = getReconnectDelay();
|
||||
reconnectAttempts++;
|
||||
|
||||
console.log('🔄 Reconnecting SSE in ' + (delay/1000) + 's (attempt #' + reconnectAttempts + ')...');
|
||||
|
||||
// Clear any existing reconnect timeout
|
||||
if (reconnectTimeout) {
|
||||
clearTimeout(reconnectTimeout);
|
||||
}
|
||||
|
||||
reconnectTimeout = setTimeout(setupSSEConnection, delay);
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
@@ -1188,9 +1261,9 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
// Clear pending request
|
||||
currentPendingRequestId = null;
|
||||
|
||||
// Disable input controls
|
||||
// Disable send button and quick replies (but keep text input enabled)
|
||||
const quickReplies = document.getElementById('quickReplies');
|
||||
if (messageInput && sendButton) {
|
||||
if (sendButton) {
|
||||
sendButton.disabled = true;
|
||||
quickReplies.disabled = true;
|
||||
}
|
||||
@@ -1245,7 +1318,7 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
// Load conversation history from server
|
||||
async function loadConversationHistory() {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/sessions/${this.workspaceSessionId}/messages');
|
||||
const response = await fetch('http://127.0.0.1:${this.port}/sessions/${this.workspaceSessionId}/messages');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
const messagesContainer = document.getElementById('messages');
|
||||
|
||||
Reference in New Issue
Block a user