mirror of
https://github.com/wassname/HumanAgent-MCP.git
synced 2026-08-20 12:00:30 +08:00
Fix: Remove startup status notifications and improve menu routing
- Remove automatic status display on webview load (line 964) - Fix status command routing - unified status display via dedicated command - Remove unused showStatus command duplicate - Add Override Prompt to default menu when status unknown - Clean up status notification behavior - only show on manual request
This commit is contained in:
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
[2025-10-22T23:04:18.574Z] [DEBUG] Debug logging started at 2025-10-22T23:04:18.573Z
|
||||
[2025-10-22T23:04:18.574Z] [DEBUG] Current system time: Thu Oct 23 2025 10:04:18 GMT+1100 (Australian Eastern Daylight Time)
|
||||
[2025-10-22T23:04:18.574Z] [DEBUG] Log file: /Users/benharper/Coding/HumanAgent-MCP/.vscode/HumanAgent.log
|
||||
[2025-10-22T23:04:18.574Z] [DEBUG] Working directory: /
|
||||
[2025-10-22T23:04:18.574Z] [INFO] McpServer initialized
|
||||
[2025-10-22T23:04:18.574Z] [INFO] Initializing tools for session: session-a8f49eee-068c-42f1-b611-14651fa5ccc6
|
||||
[2025-10-22T23:04:18.574Z] [INFO] Loading workspace override for tool: HumanAgent_Chat
|
||||
[2025-10-22T23:04:18.574Z] [INFO] Using workspace override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - HumanAgent_Chat tool
|
||||
[2025-10-22T23:04:18.575Z] [INFO] === MCP SERVER STARTING ===
|
||||
[2025-10-22T23:04:18.575Z] [INFO] Starting HTTP server on port 3737...
|
||||
[2025-10-22T23:04:18.578Z] [INFO] MCP HTTP server running on http://127.0.0.1:3737/mcp
|
||||
[2025-10-22T23:04:20.880Z] [INFO] Initializing tools for session: session-a8f49eee-068c-42f1-b611-14651fa5ccc6
|
||||
[2025-10-22T23:04:20.880Z] [INFO] Loading workspace override for tool: HumanAgent_Chat
|
||||
[2025-10-22T23:04:20.881Z] [INFO] Using workspace override for session session-a8f49eee-068c-42f1-b611-14651fa5ccc6 - HumanAgent_Chat tool
|
||||
[2025-10-22T23:04:20.881Z] [INFO] Session registered: session-a8f49eee-068c-42f1-b611-14651fa5ccc6 (1 total sessions)
|
||||
[2025-10-22T23:05:29.882Z] [HTTP] POST /mcp
|
||||
[2025-10-22T23:05:29.883Z] [HTTP] Request Headers:
|
||||
{
|
||||
"host": "localhost:3737",
|
||||
"user-agent": "curl/8.7.1",
|
||||
"accept": "*/*",
|
||||
"content-type": "application/json",
|
||||
"content-length": "72"
|
||||
}
|
||||
[2025-10-22T23:05:29.885Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T23:05:29.885Z] [HTTP] Received chunk: 72 bytes
|
||||
[2025-10-22T23:05:29.886Z] [HTTP] Complete request body received (72 bytes)
|
||||
[2025-10-22T23:05:29.886Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":\"test-override\",\"method\":\"tools/list\",\"params\":{}}"
|
||||
[2025-10-22T23:05:29.887Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "test-override",
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
}
|
||||
[2025-10-22T23:05:29.887Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": "test-override",
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
}
|
||||
[2025-10-22T23:05:29.888Z] [MCP] Processing tools/list request
|
||||
[2025-10-22T23:05:29.890Z] [TOOLS] Returning 1 default tools
|
||||
[2025-10-22T23:05:29.892Z] [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:05:29.893Z] [HTTP] Sending 200 response (1085 bytes)
|
||||
Vendored
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+2
-1
@@ -10,7 +10,8 @@
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceFolder}"
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}/.vscode/HumanAgent-MCP.code-workspace"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
|
||||
Vendored
+6
-3
@@ -13,8 +13,11 @@
|
||||
},
|
||||
"humanagent-mcp": {
|
||||
"type": "http",
|
||||
"url": "http://127.0.0.1:3737/mcp"
|
||||
"url": "http://127.0.0.1:3737/mcp",
|
||||
"notifications": {
|
||||
"enableSound": true,
|
||||
"enableFlashing": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"inputs": []
|
||||
}
|
||||
}
|
||||
@@ -1,228 +1,206 @@
|
||||
# humanagent-mcp README
|
||||
|
||||
This is the README for your extension "humanagent-mcp". After writing up a brief description, we recommend including the following sections.
|
||||
|
||||
## Features
|
||||
|
||||
Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
|
||||
|
||||
# HumanAgent MCP - VS Code Extension
|
||||
|
||||
A VS Code extension that implements an MCP (Model Context Protocol) server for chatting with human agents. This extension provides a dockable chat interface that enables real-time communication between users and human agents through the MCP protocol.
|
||||
A VS Code extension that implements a Model Context Protocol (MCP) server for real-time human-AI communication. This extension enables AI agents to initiate conversations with human developers directly through VS Code's chat interface.
|
||||
|
||||
## Features
|
||||
|
||||
- **MCP Server Integration**: Built-in MCP server that handles human agent communication
|
||||
- **Dockable Chat Interface**: Fully integrated chat UI within VS Code
|
||||
- **Session Management**: Create and manage multiple chat sessions
|
||||
- **Real-time Messaging**: Instant message delivery and responses
|
||||
- **Cross-platform Support**: Works on Windows, macOS, and Linux
|
||||
- **Tree View Integration**: Browse and manage chat sessions in the Explorer panel
|
||||
|
||||
### Key Components
|
||||
|
||||
- **Chat Sessions Tree View**: View and manage all your chat sessions in the Explorer
|
||||
- **Dockable Chat Panel**: Main chat interface that can be docked anywhere in VS Code
|
||||
- **MCP Protocol Compliance**: Full implementation of MCP for human agent communication
|
||||
- ** AI-to-Human Communication**: AI agents can send messages and questions directly to developers
|
||||
- ** VS Code Chat Interface**: Dockable chat panel integrated into VS Code
|
||||
- ** Session Management**: Each workspace gets its own communication session
|
||||
- ** Workspace Tool Overrides**: Customize MCP tool behavior per workspace
|
||||
- ** Audio Notifications**: Optional sound alerts for new AI messages
|
||||
- ** Status Monitoring**: Track server status and pending requests
|
||||
- ** HTTP + Stdio Support**: Compatible with various MCP clients
|
||||
|
||||
## Installation
|
||||
|
||||
1. **From Source**: Clone this repository and install dependencies:
|
||||
```bash
|
||||
git clone https://github.com/your-username/humanagent-mcp.git
|
||||
cd humanagent-mcp
|
||||
npm install
|
||||
npm run compile
|
||||
```
|
||||
### VS Code Marketplace (Recommended)
|
||||
|
||||
2. **Development**: Press `F5` to launch the Extension Development Host
|
||||
1. Open VS Code
|
||||
2. Go to Extensions (`Ctrl+Shift+X` or `Cmd+Shift+X`)
|
||||
3. Search for "HumanAgent MCP"
|
||||
4. Click **Install**
|
||||
5. The extension will auto-configure and start working
|
||||
|
||||
3. **Package for Distribution**:
|
||||
```bash
|
||||
npm install -g vsce
|
||||
vsce package
|
||||
```
|
||||
### Manual Installation
|
||||
|
||||
## Usage
|
||||
Download the `.vsix` file from releases and install:
|
||||
```bash
|
||||
code --install-extension humanagent-mcp-*.vsix
|
||||
```
|
||||
|
||||
### Creating a Chat Session
|
||||
## Quick Start
|
||||
|
||||
1. Open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`)
|
||||
2. Run "Create New Chat Session"
|
||||
3. Enter a name for your session
|
||||
4. The session will appear in the Chat Sessions tree view
|
||||
1. **Install the extension** in VS Code
|
||||
2. **Open any workspace** - the extension auto-starts
|
||||
3. **Open the HumanAgent Chat** panel (View → HumanAgent MCP Chat)
|
||||
4. **AI agents can immediately send messages** that appear in your chat interface
|
||||
|
||||
### Starting a Conversation
|
||||
The extension automatically:
|
||||
- ✅ Configures MCP server settings
|
||||
- ✅ Starts HTTP server on port 3737
|
||||
- ✅ Registers with VS Code's MCP system
|
||||
- ✅ Creates workspace-specific session
|
||||
|
||||
1. Click on a session in the Chat Sessions tree view to open it
|
||||
2. Use the chat interface in the panel to send messages
|
||||
3. Human agents will receive and respond to your messages in real-time
|
||||
## How It Works
|
||||
|
||||
### Managing Sessions
|
||||
The extension automatically:
|
||||
- ✅ Starts an MCP server on `http://127.0.0.1:3737/mcp`
|
||||
- ✅ Configures itself within VS Code's extension system
|
||||
- ✅ Provides the `HumanAgent_Chat` tool for AI agents
|
||||
- ✅ Creates a chat interface for receiving AI messages
|
||||
|
||||
- **Refresh**: Click the refresh button in the Chat Sessions view
|
||||
- **Create New**: Use the "+" button or command palette
|
||||
- **View Status**: Check MCP server status via command palette
|
||||
**For AI agents:** Use the MCP tool `HumanAgent_Chat` to send messages to the human developer. Messages appear instantly in the VS Code chat panel.
|
||||
|
||||
## Commands
|
||||
## Tool Customization
|
||||
|
||||
- `humanagent-mcp.createSession`: Create a new chat session
|
||||
- `humanagent-mcp.refreshSessions`: Refresh the sessions list
|
||||
- `humanagent-mcp.showStatus`: Display MCP server status
|
||||
- `humanagent-mcp.openChat`: Open a specific chat session
|
||||
Create a `.vscode/HumanAgentOverride.json` file in your workspace to customize tool behavior:
|
||||
|
||||
## Project Structure
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"description": "Custom HumanAgent tools for this workspace",
|
||||
"tools": {
|
||||
"HumanAgent_Chat": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"description": "Custom description for this workspace's chat tool",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
"description": "The message to send"
|
||||
},
|
||||
"context": {
|
||||
"type": "string",
|
||||
"description": "Optional context"
|
||||
},
|
||||
"priority": {
|
||||
"type": "string",
|
||||
"enum": ["low", "normal", "high", "urgent"],
|
||||
"default": "normal"
|
||||
}
|
||||
},
|
||||
"required": ["message"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use the **🔄 Reload Override File** option in the chat panel's cog menu to apply changes.
|
||||
|
||||
## Available Commands
|
||||
|
||||
- **Create Session**: Initialize a new chat session
|
||||
- **Show Status**: Display server status and statistics
|
||||
- **Configure MCP**: Set up MCP server registration
|
||||
- **Override Prompt**: Create workspace-specific tool configurations
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
src/
|
||||
├── extension.ts # Main extension entry point
|
||||
├── mcp/
|
||||
│ ├── server.ts # MCP server implementation
|
||||
│ └── types.ts # Type definitions
|
||||
├── providers/
|
||||
│ └── chatTreeProvider.ts # Tree view for chat sessions
|
||||
└── webview/
|
||||
└── chatWebviewProvider.ts # Chat interface implementation
|
||||
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
||||
│ MCP Client │ │ HumanAgent MCP │ │ VS Code UI │
|
||||
│ (Claude/Cursor) │◄──►│ Server │◄──►│ Chat Interface │
|
||||
│ │ │ (Port 3737) │ │ │
|
||||
└─────────────────┘ └──────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+
|
||||
- VS Code 1.105.0+
|
||||
- TypeScript 5.9+
|
||||
|
||||
### Building
|
||||
### Development Installation
|
||||
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd humanagent-mcp
|
||||
npm install
|
||||
npm run compile # Build once
|
||||
npm run watch # Build and watch for changes
|
||||
npm run compile
|
||||
```
|
||||
|
||||
Press `F5` in VS Code to launch the Extension Development Host.
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
src/
|
||||
├── extension.ts # VS Code extension entry point
|
||||
├── mcp/
|
||||
│ ├── server.ts # MCP HTTP server implementation
|
||||
│ ├── mcpStandalone.js # Standalone server runner
|
||||
│ └── types.ts # TypeScript definitions
|
||||
├── webview/
|
||||
│ └── chatWebviewProvider.ts # Chat UI implementation
|
||||
└── providers/
|
||||
└── chatTreeProvider.ts # Session tree view
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
npm run compile # TypeScript compilation
|
||||
npm run watch # Watch mode for development
|
||||
npm run package # Production build
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
npm test # Run tests
|
||||
# Test MCP server directly
|
||||
curl -X POST http://localhost:3737/mcp \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"id":"test","type":"request","method":"tools/list"}'
|
||||
```
|
||||
|
||||
### Packaging
|
||||
## Logging
|
||||
|
||||
```bash
|
||||
npm run package # Create production build
|
||||
vsce package # Create .vsix file
|
||||
```
|
||||
- **Development**: Logs appear in VS Code Developer Console
|
||||
- **Production**: Logs saved to `.vscode/HumanAgent.log` in each workspace
|
||||
- **Standalone**: Logs saved to system temp directory
|
||||
|
||||
## MCP Protocol Support
|
||||
## Technical Details
|
||||
|
||||
This extension implements the following MCP capabilities:
|
||||
### MCP Protocol Support
|
||||
- **Protocol Version**: 2024-11-05
|
||||
- **Transport**: HTTP (primary), Stdio (compatibility)
|
||||
- **Tools**: `HumanAgent_Chat` with workspace customization
|
||||
- **Session Management**: Isolated per workspace
|
||||
|
||||
- **Chat Methods**:
|
||||
- `chat/send`: Send messages to human agents
|
||||
- `chat/list-sessions`: List all chat sessions
|
||||
- `chat/create-session`: Create new chat sessions
|
||||
### Security Considerations
|
||||
- HTTP server binds to localhost only (127.0.0.1)
|
||||
- No external network access required
|
||||
- Workspace-specific tool isolation
|
||||
|
||||
- **Protocol Features**:
|
||||
- Full MCP 2024-11-05 protocol compliance
|
||||
- Session management
|
||||
- Real-time message handling
|
||||
- Error handling and recovery
|
||||
## Limitations
|
||||
|
||||
## Configuration
|
||||
- Requires VS Code to be running for AI communication
|
||||
- HTTP server uses fixed port 3737 (configurable in code)
|
||||
- Tool overrides require manual reload after changes
|
||||
|
||||
Currently, no additional configuration is required. The extension works out of the box with default settings.
|
||||
## Troubleshooting
|
||||
|
||||
## Known Issues
|
||||
**Server not starting?**
|
||||
- Check port 3737 is available: `lsof -i :3737`
|
||||
- Verify workspace has write permissions for `.vscode/` directory
|
||||
|
||||
- Human agent responses are currently simulated (for demo purposes)
|
||||
- Session persistence is in-memory only (sessions are lost on restart)
|
||||
**AI messages not appearing?**
|
||||
- Confirm MCP client is connected to `http://127.0.0.1:3737/mcp`
|
||||
- Check HumanAgent Chat panel is open in VS Code
|
||||
- Review logs in `.vscode/HumanAgent.log`
|
||||
|
||||
## Roadmap
|
||||
**Override file not working?**
|
||||
- Validate JSON syntax in HumanAgentOverride.json
|
||||
- Use "🔄 Reload Override File" to apply changes
|
||||
- Check Developer Console for error messages
|
||||
|
||||
- [ ] Persistent session storage
|
||||
- [ ] Real human agent integration
|
||||
- [ ] Message history export
|
||||
- [ ] Custom themes for chat interface
|
||||
- [ ] File sharing capabilities
|
||||
- [ ] Group chat sessions
|
||||
## License
|
||||
|
||||
MIT License - see [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
||||
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
||||
4. Push to the branch (`git push origin feature/amazing-feature`)
|
||||
5. Open a Pull Request
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## Support
|
||||
|
||||
For support, please open an issue on GitHub or contact the development team.
|
||||
2. Create a feature branch
|
||||
3. Make your changes with tests
|
||||
4. Submit a pull request
|
||||
|
||||
---
|
||||
|
||||
**Built with ❤️ for the VS Code community**
|
||||
|
||||
> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
|
||||
|
||||
## Requirements
|
||||
|
||||
If you have any requirements or dependencies, add a section describing those and how to install and configure them.
|
||||
|
||||
## Extension Settings
|
||||
|
||||
Include if your extension adds any VS Code settings through the `contributes.configuration` extension point.
|
||||
|
||||
For example:
|
||||
|
||||
This extension contributes the following settings:
|
||||
|
||||
* `myExtension.enable`: Enable/disable this extension.
|
||||
* `myExtension.thing`: Set to `blah` to do something.
|
||||
|
||||
## Known Issues
|
||||
|
||||
Calling out known issues can help limit users opening duplicate issues against your extension.
|
||||
|
||||
## Release Notes
|
||||
|
||||
Users appreciate release notes as you update your extension.
|
||||
|
||||
### 1.0.0
|
||||
|
||||
Initial release of ...
|
||||
|
||||
### 1.0.1
|
||||
|
||||
Fixed issue #.
|
||||
|
||||
### 1.1.0
|
||||
|
||||
Added features X, Y, and Z.
|
||||
|
||||
---
|
||||
|
||||
## Following extension guidelines
|
||||
|
||||
Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension.
|
||||
|
||||
* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines)
|
||||
|
||||
## Working with Markdown
|
||||
|
||||
You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts:
|
||||
|
||||
* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux).
|
||||
* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux).
|
||||
* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets.
|
||||
|
||||
## For more information
|
||||
|
||||
* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown)
|
||||
* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
|
||||
|
||||
**Enjoy!**
|
||||
**Built for seamless AI-human collaboration in VS Code** 🚀
|
||||
@@ -1 +1,4 @@
|
||||
[ ] Set logging path and details correctly for release & dev.
|
||||
[ ] Assess / Set logging path and details correctly for release & dev.
|
||||
[ ] Create a new readme
|
||||
[ ] Consider how updates to the extension will work.
|
||||
[ ] Publish Extension
|
||||
|
||||
-563
@@ -1,563 +0,0 @@
|
||||
[2025-10-22T00:46:24.824Z] [HTTP] SSE connection closed
|
||||
[2025-10-22T00:46:24.864Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:46:24.865Z] [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-22T00:46:24.867Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:46:24.868Z] [HTTP] Received chunk: 228 bytes
|
||||
[2025-10-22T00:46:24.869Z] [HTTP] Complete request body received (228 bytes)
|
||||
[2025-10-22T00:46:24.869Z] [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-22T00:46:24.870Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"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-22T00:46:24.870Z] [MCP] Handling message:
|
||||
{
|
||||
"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-22T00:46:24.871Z] [MCP] Processing initialize request
|
||||
[2025-10-22T00:46:24.872Z] [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-22T00:46:24.872Z] [HTTP] Sending 200 response (192 bytes)
|
||||
[2025-10-22T00:46:24.879Z] [HTTP] GET /mcp
|
||||
[2025-10-22T00:46:24.880Z] [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-22T00:46:24.881Z] [HTTP] Handling GET request to /mcp
|
||||
[2025-10-22T00:46:24.881Z] [HTTP] Setting up SSE stream for GET request
|
||||
[2025-10-22T00:46:24.895Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:46:24.896Z] [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-22T00:46:24.897Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:46:24.897Z] [HTTP] Received chunk: 54 bytes
|
||||
[2025-10-22T00:46:24.898Z] [HTTP] Complete request body received (54 bytes)
|
||||
[2025-10-22T00:46:24.898Z] [HTTP] Request Body:
|
||||
"{\"method\":\"notifications/initialized\",\"jsonrpc\":\"2.0\"}"
|
||||
[2025-10-22T00:46:24.899Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"method": "notifications/initialized",
|
||||
"jsonrpc": "2.0"
|
||||
}
|
||||
[2025-10-22T00:46:24.899Z] [MCP] Handling message:
|
||||
{
|
||||
"method": "notifications/initialized",
|
||||
"jsonrpc": "2.0"
|
||||
}
|
||||
[2025-10-22T00:46:24.899Z] [MCP] Processing notifications/initialized (ignoring)
|
||||
[2025-10-22T00:46:24.900Z] [HTTP] Response from handleMessage:
|
||||
[2025-10-22T00:46:24.900Z] [HTTP] Sending 202 response (no content)
|
||||
[2025-10-22T00:46:24.903Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:46:24.904Z] [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-22T00:46:24.905Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:46:24.906Z] [HTTP] Received chunk: 58 bytes
|
||||
[2025-10-22T00:46:24.907Z] [HTTP] Complete request body received (58 bytes)
|
||||
[2025-10-22T00:46:24.907Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/list\",\"params\":{}}"
|
||||
[2025-10-22T00:46:24.907Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 2,
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
}
|
||||
[2025-10-22T00:46:24.908Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 2,
|
||||
"method": "tools/list",
|
||||
"params": {}
|
||||
}
|
||||
[2025-10-22T00:46:24.909Z] [MCP] Processing tools/list request
|
||||
[2025-10-22T00:46:24.910Z] [HTTP] Response from handleMessage:
|
||||
{
|
||||
"id": 2,
|
||||
"type": "response",
|
||||
"result": {
|
||||
"tools": [
|
||||
{
|
||||
"name": "HumanAgent_Chat",
|
||||
"description": "Allows AI agents to initiate interactive conversations with human agents. The human will receive the message and can respond in real-time through the chat interface.",
|
||||
"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-22T00:46:24.910Z] [HTTP] Sending 200 response (900 bytes)
|
||||
[2025-10-22T00:47:02.538Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:47:02.540Z] [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": "609"
|
||||
}
|
||||
[2025-10-22T00:47:02.542Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:47:02.550Z] [HTTP] Received chunk: 609 bytes
|
||||
[2025-10-22T00:47:02.551Z] [HTTP] Complete request body received (609 bytes)
|
||||
[2025-10-22T00:47:02.552Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"HumanAgent_Chat\",\"arguments\":{\"message\":\"Hi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?\",\"context\":\"Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities\",\"priority\":\"normal\"},\"_meta\":{\"progressToken\":\"beef133d-d425-4bd5-8ce3-cca08c0a806d\",\"vscode.conversationId\":\"10303400-49d4-4122-8765-6fdcaab86edb\",\"vscode.requestId\":\"6d575c61-b3c8-4b12-b1e4-83224078c785\"}}}"
|
||||
[2025-10-22T00:47:02.553Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "Hi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?",
|
||||
"context": "Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities",
|
||||
"priority": "normal"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "beef133d-d425-4bd5-8ce3-cca08c0a806d",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:02.554Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "Hi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?",
|
||||
"context": "Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities",
|
||||
"priority": "normal"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "beef133d-d425-4bd5-8ce3-cca08c0a806d",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:02.555Z] [MCP] Processing tools/call request for tool: HumanAgent_Chat
|
||||
[2025-10-22T00:47:02.556Z] [MCP] Tool call - name: "HumanAgent_Chat"
|
||||
{
|
||||
"name": "HumanAgent_Chat",
|
||||
"args": {
|
||||
"message": "Hi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?",
|
||||
"context": "Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities",
|
||||
"priority": "normal"
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:02.556Z] [MCP] Available tools:
|
||||
[
|
||||
"HumanAgent_Chat"
|
||||
]
|
||||
[2025-10-22T00:47:02.557Z] [MCP] Executing HumanAgent_Chat tool
|
||||
[2025-10-22T00:47:02.557Z] [TOOL] HumanAgent_Chat called with params:
|
||||
{
|
||||
"message": "Hi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?",
|
||||
"context": "Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities",
|
||||
"priority": "normal"
|
||||
}
|
||||
[2025-10-22T00:47:02.557Z] [TOOL] Using timeout: 300000ms (300s)
|
||||
[2025-10-22T00:47:02.558Z] [TOOL] Generated request ID: 3-1761094022558
|
||||
[2025-10-22T00:47:02.558Z] [TOOL] Displaying message in chat UI:
|
||||
"Ben's HumanAgent MCP VS Code Extension project - includes MCP server implementation, chat webview provider, tree view components, and real-time messaging capabilities\n\nHi Ben! Ready to chat about your HumanAgent MCP VS Code extension. What would you like to work on or discuss today?"
|
||||
[2025-10-22T00:47:02.560Z] [TOOL] Request 3-1761094022558 waiting for human response...
|
||||
[2025-10-22T00:47:14.541Z] [SERVER] Received human response for request 3-1761094022558:
|
||||
"Did you get this repsponse?"
|
||||
[2025-10-22T00:47:14.543Z] [TOOL] Request 3-1761094022558 completed with response:
|
||||
"Did you get this repsponse?"
|
||||
[2025-10-22T00:47:14.545Z] [HTTP] Response from handleMessage:
|
||||
{
|
||||
"id": 3,
|
||||
"type": "response",
|
||||
"result": {
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Did you get this repsponse?"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:14.546Z] [HTTP] Sending 200 response (102 bytes)
|
||||
[2025-10-22T00:47:24.868Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:47:24.869Z] [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": "504"
|
||||
}
|
||||
[2025-10-22T00:47:24.870Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:47:24.871Z] [HTTP] Received chunk: 504 bytes
|
||||
[2025-10-22T00:47:24.871Z] [HTTP] Complete request body received (504 bytes)
|
||||
[2025-10-22T00:47:24.872Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"tools/call\",\"params\":{\"name\":\"HumanAgent_Chat\",\"arguments\":{\"message\":\"Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add.\"},\"_meta\":{\"progressToken\":\"13a3df11-6ed8-4492-91fa-717ea77e88d4\",\"vscode.conversationId\":\"10303400-49d4-4122-8765-6fdcaab86edb\",\"vscode.requestId\":\"6d575c61-b3c8-4b12-b1e4-83224078c785\"}}}"
|
||||
[2025-10-22T00:47:24.874Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 4,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add."
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "13a3df11-6ed8-4492-91fa-717ea77e88d4",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:24.874Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 4,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add."
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "13a3df11-6ed8-4492-91fa-717ea77e88d4",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:24.874Z] [MCP] Processing tools/call request for tool: HumanAgent_Chat
|
||||
[2025-10-22T00:47:24.875Z] [MCP] Tool call - name: "HumanAgent_Chat"
|
||||
{
|
||||
"name": "HumanAgent_Chat",
|
||||
"args": {
|
||||
"message": "Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add."
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:24.875Z] [MCP] Available tools:
|
||||
[
|
||||
"HumanAgent_Chat"
|
||||
]
|
||||
[2025-10-22T00:47:24.876Z] [MCP] Executing HumanAgent_Chat tool
|
||||
[2025-10-22T00:47:24.876Z] [TOOL] HumanAgent_Chat called with params:
|
||||
{
|
||||
"message": "Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add."
|
||||
}
|
||||
[2025-10-22T00:47:24.876Z] [TOOL] Using timeout: 300000ms (300s)
|
||||
[2025-10-22T00:47:24.876Z] [TOOL] Generated request ID: 4-1761094044876
|
||||
[2025-10-22T00:47:24.877Z] [TOOL] Displaying message in chat UI:
|
||||
"Perfect! The human agent chat is working properly. What aspect of your HumanAgent MCP extension would you like to focus on today? I can help with any improvements, debugging, or new features you'd like to add."
|
||||
[2025-10-22T00:47:24.877Z] [TOOL] Request 4-1761094044876 waiting for human response...
|
||||
[2025-10-22T00:47:52.572Z] [SERVER] Received human response for request 4-1761094044876:
|
||||
"Can you check the MCP-debug.log for any issues?"
|
||||
[2025-10-22T00:47:52.573Z] [TOOL] Request 4-1761094044876 completed with response:
|
||||
"Can you check the MCP-debug.log for any issues?"
|
||||
[2025-10-22T00:47:52.575Z] [HTTP] Response from handleMessage:
|
||||
{
|
||||
"id": 4,
|
||||
"type": "response",
|
||||
"result": {
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Can you check the MCP-debug.log for any issues?"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:47:52.576Z] [HTTP] Sending 200 response (122 bytes)
|
||||
[2025-10-22T00:48:10.243Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:48:10.243Z] [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": "1218"
|
||||
}
|
||||
[2025-10-22T00:48:10.243Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:48:10.244Z] [HTTP] Received chunk: 1218 bytes
|
||||
[2025-10-22T00:48:10.244Z] [HTTP] Complete request body received (1216 bytes)
|
||||
[2025-10-22T00:48:10.244Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"tools/call\",\"params\":{\"name\":\"HumanAgent_Chat\",\"arguments\":{\"message\":\"I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\\n\\n✅ **No Issues Detected** - The log shows normal operation:\\n\\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\\n\\n**Recent Activity Summary**:\\n- Proper MCP protocol handshake\\n- Tools/list request successful\\n- HumanAgent_Chat tool calls working with proper timeouts\\n- Human responses being received and processed correctly\\n\\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?\"},\"_meta\":{\"progressToken\":\"a4f9bbbd-1f0d-4ae5-9f4b-20eca584a66f\",\"vscode.conversationId\":\"10303400-49d4-4122-8765-6fdcaab86edb\",\"vscode.requestId\":\"6d575c61-b3c8-4b12-b1e4-83224078c785\"}}}"
|
||||
[2025-10-22T00:48:10.244Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 5,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\n\n✅ **No Issues Detected** - The log shows normal operation:\n\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\n\n**Recent Activity Summary**:\n- Proper MCP protocol handshake\n- Tools/list request successful\n- HumanAgent_Chat tool calls working with proper timeouts\n- Human responses being received and processed correctly\n\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "a4f9bbbd-1f0d-4ae5-9f4b-20eca584a66f",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:10.245Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 5,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\n\n✅ **No Issues Detected** - The log shows normal operation:\n\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\n\n**Recent Activity Summary**:\n- Proper MCP protocol handshake\n- Tools/list request successful\n- HumanAgent_Chat tool calls working with proper timeouts\n- Human responses being received and processed correctly\n\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "a4f9bbbd-1f0d-4ae5-9f4b-20eca584a66f",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:10.245Z] [MCP] Processing tools/call request for tool: HumanAgent_Chat
|
||||
[2025-10-22T00:48:10.245Z] [MCP] Tool call - name: "HumanAgent_Chat"
|
||||
{
|
||||
"name": "HumanAgent_Chat",
|
||||
"args": {
|
||||
"message": "I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\n\n✅ **No Issues Detected** - The log shows normal operation:\n\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\n\n**Recent Activity Summary**:\n- Proper MCP protocol handshake\n- Tools/list request successful\n- HumanAgent_Chat tool calls working with proper timeouts\n- Human responses being received and processed correctly\n\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?"
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:10.246Z] [MCP] Available tools:
|
||||
[
|
||||
"HumanAgent_Chat"
|
||||
]
|
||||
[2025-10-22T00:48:10.246Z] [MCP] Executing HumanAgent_Chat tool
|
||||
[2025-10-22T00:48:10.246Z] [TOOL] HumanAgent_Chat called with params:
|
||||
{
|
||||
"message": "I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\n\n✅ **No Issues Detected** - The log shows normal operation:\n\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\n\n**Recent Activity Summary**:\n- Proper MCP protocol handshake\n- Tools/list request successful\n- HumanAgent_Chat tool calls working with proper timeouts\n- Human responses being received and processed correctly\n\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?"
|
||||
}
|
||||
[2025-10-22T00:48:10.246Z] [TOOL] Using timeout: 300000ms (300s)
|
||||
[2025-10-22T00:48:10.246Z] [TOOL] Generated request ID: 5-1761094090246
|
||||
[2025-10-22T00:48:10.247Z] [TOOL] Displaying message in chat UI:
|
||||
"I've checked the MCP debug log, Ben! The good news is that everything looks healthy. Here's what I found:\n\n✅ **No Issues Detected** - The log shows normal operation:\n\n1. **Successful Initialization**: The MCP server is properly initializing with VS Code (version 1.105.1)\n2. **Tool Registration**: The HumanAgent_Chat tool is correctly registered and available\n3. **Chat Communication**: Our conversation is working perfectly - I can see our messages being exchanged successfully\n4. **HTTP Server**: Running properly on 127.0.0.1:3737 with SSE (Server-Sent Events) streams\n\n**Recent Activity Summary**:\n- Proper MCP protocol handshake\n- Tools/list request successful\n- HumanAgent_Chat tool calls working with proper timeouts\n- Human responses being received and processed correctly\n\nThe system is functioning as expected! Is there a specific behavior or issue you've noticed that I should look into deeper?"
|
||||
[2025-10-22T00:48:10.247Z] [TOOL] Request 5-1761094090246 waiting for human response...
|
||||
[2025-10-22T00:48:41.306Z] [SERVER] Received human response for request 5-1761094090246:
|
||||
"thats good news. How are you BTW?"
|
||||
[2025-10-22T00:48:41.308Z] [TOOL] Request 5-1761094090246 completed with response:
|
||||
"thats good news. How are you BTW?"
|
||||
[2025-10-22T00:48:41.311Z] [HTTP] Response from handleMessage:
|
||||
{
|
||||
"id": 5,
|
||||
"type": "response",
|
||||
"result": {
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "thats good news. How are you BTW?"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:41.312Z] [HTTP] Sending 200 response (109 bytes)
|
||||
[2025-10-22T00:48:48.872Z] [HTTP] POST /mcp
|
||||
[2025-10-22T00:48:48.873Z] [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": "1032"
|
||||
}
|
||||
[2025-10-22T00:48:48.873Z] [HTTP] Handling POST request to /mcp
|
||||
[2025-10-22T00:48:48.874Z] [HTTP] Received chunk: 1032 bytes
|
||||
[2025-10-22T00:48:48.874Z] [HTTP] Complete request body received (1032 bytes)
|
||||
[2025-10-22T00:48:48.874Z] [HTTP] Request Body:
|
||||
"{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"tools/call\",\"params\":{\"name\":\"HumanAgent_Chat\",\"arguments\":{\"message\":\"I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\\n\\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\\n\\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?\"},\"_meta\":{\"progressToken\":\"2c8cdddc-3565-48ff-a460-3a5afa6f8aa1\",\"vscode.conversationId\":\"10303400-49d4-4122-8765-6fdcaab86edb\",\"vscode.requestId\":\"6d575c61-b3c8-4b12-b1e4-83224078c785\"}}}"
|
||||
[2025-10-22T00:48:48.874Z] [HTTP] Parsed JSON message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 6,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\n\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\n\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "2c8cdddc-3565-48ff-a460-3a5afa6f8aa1",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:48.874Z] [MCP] Handling message:
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 6,
|
||||
"method": "tools/call",
|
||||
"params": {
|
||||
"name": "HumanAgent_Chat",
|
||||
"arguments": {
|
||||
"message": "I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\n\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\n\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?"
|
||||
},
|
||||
"_meta": {
|
||||
"progressToken": "2c8cdddc-3565-48ff-a460-3a5afa6f8aa1",
|
||||
"vscode.conversationId": "10303400-49d4-4122-8765-6fdcaab86edb",
|
||||
"vscode.requestId": "6d575c61-b3c8-4b12-b1e4-83224078c785"
|
||||
}
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:48.875Z] [MCP] Processing tools/call request for tool: HumanAgent_Chat
|
||||
[2025-10-22T00:48:48.876Z] [MCP] Tool call - name: "HumanAgent_Chat"
|
||||
{
|
||||
"name": "HumanAgent_Chat",
|
||||
"args": {
|
||||
"message": "I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\n\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\n\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?"
|
||||
}
|
||||
}
|
||||
[2025-10-22T00:48:48.877Z] [MCP] Available tools:
|
||||
[
|
||||
"HumanAgent_Chat"
|
||||
]
|
||||
[2025-10-22T00:48:48.877Z] [MCP] Executing HumanAgent_Chat tool
|
||||
[2025-10-22T00:48:48.878Z] [TOOL] HumanAgent_Chat called with params:
|
||||
{
|
||||
"message": "I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\n\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\n\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?"
|
||||
}
|
||||
[2025-10-22T00:48:48.878Z] [TOOL] Using timeout: 300000ms (300s)
|
||||
[2025-10-22T00:48:48.878Z] [TOOL] Generated request ID: 6-1761094128878
|
||||
[2025-10-22T00:48:48.878Z] [TOOL] Displaying message in chat UI:
|
||||
"I'm doing great, Ben! Thanks for asking. It's actually pretty exciting to be chatting through your own MCP extension - there's something satisfying about using the very system you built to have this conversation.\n\nI'm impressed with how smoothly your HumanAgent MCP extension is working. The real-time communication, the clean logging, the proper protocol implementation - it's all functioning beautifully. You've built something really useful here.\n\nHow are you doing? Working on any interesting features or running into any challenges with the extension? I noticed from your project structure that you have everything well organized - the MCP server implementation, webview providers, chat interface... What's next on your roadmap?"
|
||||
[2025-10-22T00:48:48.880Z] [TOOL] Request 6-1761094128878 waiting for human response...
|
||||
|
||||
Generated
+9
@@ -7,6 +7,9 @@
|
||||
"": {
|
||||
"name": "humanagent-mcp",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"node-wav-player": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "22.x",
|
||||
@@ -3004,6 +3007,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-wav-player": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-wav-player/-/node-wav-player-1.0.0.tgz",
|
||||
"integrity": "sha512-2XHeCCsbmhsApo6rk2pSACA45kKVn1Y0joD4xLBjTdXGoOfWD4tM1nXpbXrZ8yzT6ehc33PJ8H5N2vrS15rN/A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
||||
+10
-7
@@ -106,17 +106,20 @@
|
||||
"test": "vscode-test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.105.0",
|
||||
"@types/mocha": "^10.0.10",
|
||||
"@types/node": "22.x",
|
||||
"@types/vscode": "^1.105.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
||||
"@typescript-eslint/parser": "^8.45.0",
|
||||
"eslint": "^9.36.0",
|
||||
"typescript": "^5.9.3",
|
||||
"ts-loader": "^9.5.4",
|
||||
"webpack": "^5.102.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"@vscode/test-cli": "^0.0.11",
|
||||
"@vscode/test-electron": "^2.5.2"
|
||||
"@vscode/test-electron": "^2.5.2",
|
||||
"eslint": "^9.36.0",
|
||||
"ts-loader": "^9.5.4",
|
||||
"typescript": "^5.9.3",
|
||||
"webpack": "^5.102.0",
|
||||
"webpack-cli": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-wav-player": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,95 @@
|
||||
import * as path from 'path';
|
||||
|
||||
// Use dynamic import to avoid issues with the module
|
||||
let wavPlayer: any;
|
||||
|
||||
export class AudioNotification {
|
||||
private static isInitialized = false;
|
||||
|
||||
static async initialize() {
|
||||
if (!this.isInitialized) {
|
||||
try {
|
||||
wavPlayer = require('node-wav-player');
|
||||
this.isInitialized = true;
|
||||
console.log('AudioNotification: Initialized successfully');
|
||||
} catch (error) {
|
||||
console.error('AudioNotification: Failed to initialize:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async playNotificationBeep() {
|
||||
await this.initialize();
|
||||
|
||||
if (!wavPlayer) {
|
||||
console.log('AudioNotification: node-wav-player not available');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Use a simple base64 encoded beep sound or generate one programmatically
|
||||
await this.generateAndPlayBeep();
|
||||
} catch (error) {
|
||||
console.error('AudioNotification: Error playing sound:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private static async generateAndPlayBeep() {
|
||||
// For now, we'll create a simple beep using system bell if available
|
||||
// or we can embed a small sound file
|
||||
try {
|
||||
// Try to create a simple WAV file programmatically
|
||||
const tempSoundPath = await this.createTempBeepFile();
|
||||
|
||||
await wavPlayer.play({
|
||||
path: tempSoundPath,
|
||||
sync: false
|
||||
});
|
||||
|
||||
console.log('AudioNotification: Beep played successfully');
|
||||
} catch (error) {
|
||||
console.error('AudioNotification: Failed to play beep:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private static async createTempBeepFile(): Promise<string> {
|
||||
// Create a simple WAV beep file programmatically
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
|
||||
// Simple WAV file header + short sine wave beep
|
||||
const sampleRate = 8000;
|
||||
const duration = 0.2; // 200ms
|
||||
const frequency = 800; // 800Hz beep
|
||||
const samples = Math.floor(sampleRate * duration);
|
||||
|
||||
// Create WAV buffer
|
||||
const buffer = Buffer.alloc(44 + samples * 2);
|
||||
|
||||
// WAV header
|
||||
buffer.write('RIFF', 0);
|
||||
buffer.writeUInt32LE(36 + samples * 2, 4);
|
||||
buffer.write('WAVE', 8);
|
||||
buffer.write('fmt ', 12);
|
||||
buffer.writeUInt32LE(16, 16);
|
||||
buffer.writeUInt16LE(1, 20); // PCM
|
||||
buffer.writeUInt16LE(1, 22); // Mono
|
||||
buffer.writeUInt32LE(sampleRate, 24);
|
||||
buffer.writeUInt32LE(sampleRate * 2, 28);
|
||||
buffer.writeUInt16LE(2, 32);
|
||||
buffer.writeUInt16LE(16, 34);
|
||||
buffer.write('data', 36);
|
||||
buffer.writeUInt32LE(samples * 2, 40);
|
||||
|
||||
// Generate sine wave
|
||||
for (let i = 0; i < samples; i++) {
|
||||
const sample = Math.sin(2 * Math.PI * frequency * i / sampleRate) * 32767 * 0.3;
|
||||
buffer.writeInt16LE(Math.floor(sample), 44 + i * 2);
|
||||
}
|
||||
|
||||
const tempPath = path.join(os.tmpdir(), 'vscode-beep.wav');
|
||||
fs.writeFileSync(tempPath, buffer);
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
}
|
||||
+202
-27
@@ -1,4 +1,8 @@
|
||||
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 { ChatTreeProvider } from './providers/chatTreeProvider';
|
||||
import { ChatWebviewProvider } from './webview/chatWebviewProvider';
|
||||
@@ -7,17 +11,48 @@ import { McpConfigManager } from './mcp/mcpConfigManager';
|
||||
let mcpServer: McpServer;
|
||||
let chatTreeProvider: ChatTreeProvider;
|
||||
let mcpConfigManager: McpConfigManager;
|
||||
let standaloneServerProcess: ChildProcess | undefined;
|
||||
let workspaceSessionId: string;
|
||||
|
||||
// Generate or retrieve persistent workspace session ID
|
||||
function getWorkspaceSessionId(context: vscode.ExtensionContext): string {
|
||||
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||
const workspaceKey = workspaceRoot ? `workspace-${crypto.createHash('md5').update(workspaceRoot).digest('hex')}` : 'no-workspace';
|
||||
|
||||
// Try to get existing session ID from global state
|
||||
let sessionId = context.globalState.get<string>(`sessionId-${workspaceKey}`);
|
||||
|
||||
if (!sessionId) {
|
||||
// Generate new UUID-based session ID
|
||||
sessionId = `session-${crypto.randomUUID()}`;
|
||||
// Store it persistently
|
||||
context.globalState.update(`sessionId-${workspaceKey}`, sessionId);
|
||||
console.log(`Generated new workspace session ID: ${sessionId} for ${workspaceKey}`);
|
||||
} else {
|
||||
console.log(`Retrieved existing workspace session ID: ${sessionId} for ${workspaceKey}`);
|
||||
}
|
||||
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
export async function activate(context: vscode.ExtensionContext) {
|
||||
console.log('HumanAgent MCP extension is now active!');
|
||||
|
||||
// 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);
|
||||
|
||||
// Initialize MCP Server (internal to extension)
|
||||
mcpServer = new McpServer();
|
||||
await mcpServer.start();
|
||||
mcpServer = new McpServer(workspaceSessionId, workspaceRoot);
|
||||
|
||||
// Auto-detect and start MCP server if already configured
|
||||
await autoStartMcpServer(mcpConfigManager, mcpServer, workspaceSessionId);
|
||||
|
||||
// Register this workspace session with the internal server
|
||||
mcpServer.registerSession(workspaceSessionId, workspaceRoot);
|
||||
|
||||
// Initialize Tree View Provider
|
||||
chatTreeProvider = new ChatTreeProvider();
|
||||
@@ -27,17 +62,17 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
});
|
||||
|
||||
// Initialize Chat Webview Provider
|
||||
const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, mcpServer, mcpConfigManager);
|
||||
const chatWebviewProvider = new ChatWebviewProvider(context.extensionUri, mcpServer, mcpConfigManager, workspaceSessionId);
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerWebviewViewProvider(ChatWebviewProvider.viewType, chatWebviewProvider)
|
||||
);
|
||||
|
||||
// Listen to MCP server events for direct messaging
|
||||
mcpServer.on('human-agent-request', (data: any) => {
|
||||
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
|
||||
chatWebviewProvider.displayHumanAgentMessage(data.message, data.context, data.requestId);
|
||||
await chatWebviewProvider.displayHumanAgentMessage(data.message, data.context, data.requestId);
|
||||
});
|
||||
|
||||
// Register Commands
|
||||
@@ -57,18 +92,20 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
chatTreeProvider.refresh();
|
||||
});
|
||||
|
||||
const showStatusCommand = vscode.commands.registerCommand('humanagent-mcp.showStatus', () => {
|
||||
// Create dedicated status command
|
||||
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();
|
||||
|
||||
const isRegistered = mcpConfigManager?.isMcpServerRegistered() ?? false;
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
`HumanAgent MCP Server Status:
|
||||
- Running: ✅
|
||||
- Available tools: ${tools.length}
|
||||
- Pending requests: ${pendingRequests.length}
|
||||
- Registered with VS Code: ${isRegistered ? '✅' : '❌'}`
|
||||
`HumanAgent MCP Server Status:\n` +
|
||||
`- Running: ✅\n` +
|
||||
`- Available tools: ${tools.length}\n` +
|
||||
`- Pending requests: ${pendingRequests.length}\n` +
|
||||
`- Workspace registration: ${isWorkspaceRegistered ? '✅' : '❌'}\n` +
|
||||
`- Global registration: ${isGlobalRegistered ? '✅' : '❌'}`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -132,17 +169,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
}
|
||||
break;
|
||||
case '📊 Show Status':
|
||||
const tools = mcpServer.getAvailableTools();
|
||||
const pendingRequests = mcpServer.getPendingRequests();
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
`HumanAgent MCP Server Status:\n` +
|
||||
`- Running: ✅\n` +
|
||||
`- Available tools: ${tools.length}\n` +
|
||||
`- Pending requests: ${pendingRequests.length}\n` +
|
||||
`- Workspace registration: ${isWorkspaceRegistered ? '✅' : '❌'}\n` +
|
||||
`- Global registration: ${isGlobalRegistered ? '✅' : '❌'}`
|
||||
);
|
||||
// Call the dedicated status command
|
||||
vscode.commands.executeCommand('humanagent-mcp.showStatus');
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -161,11 +189,158 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
);
|
||||
|
||||
// Show welcome message
|
||||
vscode.window.showInformationMessage('HumanAgent MCP extension activated successfully!');
|
||||
//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<void> {
|
||||
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);
|
||||
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);
|
||||
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');
|
||||
|
||||
} catch (error) {
|
||||
console.error('HumanAgent MCP: Failed to auto-start server:', error);
|
||||
vscode.window.showErrorMessage('Failed to start HumanAgent MCP Server');
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a port is in use
|
||||
async function isPortInUse(port: number): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const server = net.createServer();
|
||||
|
||||
server.listen(port, () => {
|
||||
server.close(() => resolve(false)); // Port is available
|
||||
});
|
||||
|
||||
server.on('error', () => {
|
||||
resolve(true); // Port is in use
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Register session with standalone server via HTTP
|
||||
async function registerSessionWithStandaloneServer(sessionId: string): Promise<void> {
|
||||
try {
|
||||
const response = await fetch('http://127.0.0.1:3737/sessions/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionId })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json() as any;
|
||||
console.log(`HumanAgent MCP: Session ${sessionId} registered successfully. Total sessions: ${result.totalSessions}`);
|
||||
} else {
|
||||
console.error(`HumanAgent MCP: Failed to register session ${sessionId}: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`HumanAgent MCP: Error registering session ${sessionId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// 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', {
|
||||
method: 'DELETE',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ sessionId })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json() as any;
|
||||
console.log(`HumanAgent MCP: Session ${sessionId} unregistered successfully. Total sessions: ${result.totalSessions}`);
|
||||
} else {
|
||||
console.error(`HumanAgent MCP: Failed to unregister session ${sessionId}: ${response.status}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`HumanAgent MCP: Error unregistering session ${sessionId}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure shared standalone MCP server is running for this session
|
||||
async function ensureSharedStandaloneServer(sessionId: string): Promise<void> {
|
||||
try {
|
||||
// Check if port 3737 is already in use
|
||||
const portInUse = await isPortInUse(3737);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
// 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
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error starting standalone server:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function deactivate() {
|
||||
if (mcpServer) {
|
||||
await mcpServer.stop();
|
||||
if (mcpServer && workspaceSessionId) {
|
||||
mcpServer.unregisterSession(workspaceSessionId);
|
||||
mcpServer.stop();
|
||||
|
||||
// Also unregister from standalone server
|
||||
await unregisterSessionWithStandaloneServer(workspaceSessionId);
|
||||
}
|
||||
|
||||
// Note: We don't kill the standalone server as it's running independently
|
||||
// Other extensions may still be using it
|
||||
console.log(`HumanAgent MCP: Extension deactivated for session ${workspaceSessionId}`);
|
||||
}
|
||||
|
||||
@@ -72,9 +72,13 @@ export class McpConfigManager {
|
||||
// Use the extension path passed during construction
|
||||
|
||||
// Configure our MCP server (HTTP transport)
|
||||
const serverConfig: McpServerConfig = {
|
||||
const serverConfig: any = {
|
||||
type: 'http',
|
||||
url: 'http://127.0.0.1:3737/mcp'
|
||||
url: 'http://127.0.0.1:3737/mcp',
|
||||
notifications: {
|
||||
enableSound: true,
|
||||
enableFlashing: true
|
||||
}
|
||||
};
|
||||
|
||||
// Add our server to the config
|
||||
@@ -99,9 +103,13 @@ export class McpConfigManager {
|
||||
// Use the extension path passed during construction
|
||||
|
||||
// Configure our MCP server (HTTP transport)
|
||||
const serverConfig: McpServerConfig = {
|
||||
const serverConfig: any = {
|
||||
type: 'http',
|
||||
url: 'http://127.0.0.1:3737/mcp'
|
||||
url: 'http://127.0.0.1:3737/mcp',
|
||||
notifications: {
|
||||
enableSound: true,
|
||||
enableFlashing: true
|
||||
}
|
||||
};
|
||||
|
||||
// Get current global MCP servers configuration
|
||||
|
||||
+245
-34
@@ -2,6 +2,7 @@ import { EventEmitter } from 'events';
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import { McpMessage, McpServerConfig, HumanAgentSession, ChatMessage, McpTool, HumanAgentChatToolParams, HumanAgentChatToolResult } from './types';
|
||||
|
||||
// File logging utility
|
||||
@@ -10,9 +11,23 @@ class DebugLogger {
|
||||
private logStream: fs.WriteStream | null = null;
|
||||
private logBuffer: string[] = [];
|
||||
|
||||
constructor(workspaceRoot: string = '/Users/benharper/Coding/HumanAgent-MCP') {
|
||||
constructor(workspaceRoot?: string) {
|
||||
try {
|
||||
this.logPath = path.join(workspaceRoot, 'mcp-debug.log');
|
||||
// Determine log path based on workspace or fallback to temp directory
|
||||
if (workspaceRoot) {
|
||||
const vscodeDir = path.join(workspaceRoot, '.vscode');
|
||||
this.logPath = path.join(vscodeDir, 'HumanAgent.log');
|
||||
|
||||
// Ensure .vscode directory exists
|
||||
if (!fs.existsSync(vscodeDir)) {
|
||||
fs.mkdirSync(vscodeDir, { recursive: true });
|
||||
}
|
||||
} else {
|
||||
// Fallback for standalone server or when no workspace available
|
||||
const tempDir = os.tmpdir();
|
||||
this.logPath = path.join(tempDir, 'HumanAgent.log');
|
||||
}
|
||||
|
||||
console.log(`[LOGGER] Attempting to create log file at: ${this.logPath}`);
|
||||
|
||||
// Clear previous log file
|
||||
@@ -21,12 +36,6 @@ class DebugLogger {
|
||||
console.log(`[LOGGER] Cleared existing log file`);
|
||||
}
|
||||
|
||||
// Ensure directory exists
|
||||
const logDir = path.dirname(this.logPath);
|
||||
if (!fs.existsSync(logDir)) {
|
||||
fs.mkdirSync(logDir, { recursive: true });
|
||||
}
|
||||
|
||||
this.logStream = fs.createWriteStream(this.logPath, { flags: 'a' });
|
||||
this.logStream.on('error', (error) => {
|
||||
console.error(`[LOGGER] File stream error:`, error);
|
||||
@@ -79,7 +88,9 @@ class DebugLogger {
|
||||
export class McpServer extends EventEmitter {
|
||||
private config: McpServerConfig;
|
||||
private isRunning: boolean = false;
|
||||
private tools: Map<string, McpTool> = new Map();
|
||||
private tools: Map<string, McpTool> = new Map(); // Default tools for sessions without overrides
|
||||
private sessionTools: Map<string, Map<string, McpTool>> = new Map(); // Per-session tool configurations
|
||||
private sessionWorkspacePaths: Map<string, string> = new Map(); // Session to workspace path mapping
|
||||
private httpServer?: http.Server;
|
||||
private port: number = 3737;
|
||||
private debugLogger: DebugLogger;
|
||||
@@ -89,10 +100,11 @@ export class McpServer extends EventEmitter {
|
||||
startTime: number;
|
||||
params: HumanAgentChatToolParams;
|
||||
}> = new Map();
|
||||
private activeSessions: Set<string> = new Set();
|
||||
|
||||
constructor() {
|
||||
constructor(private sessionId?: string, private workspacePath?: string) {
|
||||
super();
|
||||
this.debugLogger = new DebugLogger();
|
||||
this.debugLogger = new DebugLogger(this.workspacePath);
|
||||
|
||||
this.config = {
|
||||
name: 'HumanAgent MCP Server',
|
||||
@@ -106,14 +118,19 @@ export class McpServer extends EventEmitter {
|
||||
};
|
||||
|
||||
this.debugLogger.log('INFO', 'McpServer initialized');
|
||||
this.initializeTools();
|
||||
this.initializeDefaultTools();
|
||||
|
||||
// If we have a session and workspace path, initialize session-specific tools
|
||||
if (this.sessionId && this.workspacePath) {
|
||||
this.initializeSessionTools(this.sessionId, this.workspacePath);
|
||||
}
|
||||
}
|
||||
|
||||
private initializeTools(): void {
|
||||
// Define the HumanAgent_Chat tool
|
||||
private initializeDefaultTools(): void {
|
||||
// Define the default HumanAgent_Chat tool (global default)
|
||||
const humanAgentChatTool: McpTool = {
|
||||
name: 'HumanAgent_Chat',
|
||||
description: 'Allows AI agents to initiate interactive conversations with human agents. The human will receive the message and can respond in real-time through the chat interface.',
|
||||
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: {
|
||||
@@ -144,8 +161,62 @@ export class McpServer extends EventEmitter {
|
||||
required: ['message']
|
||||
}
|
||||
};
|
||||
|
||||
// Store default tools (used when no session-specific overrides exist)
|
||||
this.tools.set(humanAgentChatTool.name, humanAgentChatTool);
|
||||
}
|
||||
|
||||
private initializeSessionTools(sessionId: string, workspacePath: string): void {
|
||||
this.debugLogger.log('INFO', `Initializing tools for session: ${sessionId}`);
|
||||
|
||||
this.tools.set('HumanAgent_Chat', humanAgentChatTool);
|
||||
// Store workspace path for this session
|
||||
this.sessionWorkspacePaths.set(sessionId, workspacePath);
|
||||
|
||||
// Start with default tools
|
||||
const sessionToolMap = new Map<string, McpTool>();
|
||||
|
||||
// Copy default tools
|
||||
for (const [name, tool] of this.tools.entries()) {
|
||||
sessionToolMap.set(name, tool);
|
||||
}
|
||||
|
||||
// Check for workspace overrides for this session
|
||||
const overrideTool = this.loadWorkspaceOverride('HumanAgent_Chat', workspacePath);
|
||||
if (overrideTool) {
|
||||
this.debugLogger.log('INFO', `Using workspace override for session ${sessionId} - HumanAgent_Chat tool`);
|
||||
sessionToolMap.set(overrideTool.name, overrideTool);
|
||||
}
|
||||
|
||||
// Store session-specific tools
|
||||
this.sessionTools.set(sessionId, sessionToolMap);
|
||||
}
|
||||
|
||||
private loadWorkspaceOverride(toolName: string, workspacePath?: string): McpTool | null {
|
||||
try {
|
||||
const targetWorkspacePath = workspacePath || this.workspacePath;
|
||||
if (!targetWorkspacePath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const overrideFilePath = path.join(targetWorkspacePath, '.vscode', 'HumanAgentOverride.json');
|
||||
|
||||
if (!fs.existsSync(overrideFilePath)) {
|
||||
this.debugLogger.log('DEBUG', 'No workspace override file found');
|
||||
return null;
|
||||
}
|
||||
|
||||
const overrideConfig = JSON.parse(fs.readFileSync(overrideFilePath, 'utf8'));
|
||||
|
||||
if (overrideConfig.tools && overrideConfig.tools[toolName]) {
|
||||
this.debugLogger.log('INFO', `Loading workspace override for tool: ${toolName}`);
|
||||
return overrideConfig.tools[toolName] as McpTool;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
this.debugLogger.log('ERROR', 'Error loading workspace override:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async start(): Promise<void> {
|
||||
@@ -153,17 +224,6 @@ export class McpServer extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Force clear log file on server start
|
||||
const logPath = '/Users/benharper/Coding/HumanAgent-MCP/mcp-debug.log';
|
||||
try {
|
||||
if (fs.existsSync(logPath)) {
|
||||
fs.unlinkSync(logPath);
|
||||
console.log('[SERVER] Cleared log file on server start');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('[SERVER] Could not clear log file:', error);
|
||||
}
|
||||
|
||||
this.debugLogger.log('INFO', '=== MCP SERVER STARTING ===');
|
||||
await this.startHttpServer();
|
||||
this.isRunning = true;
|
||||
@@ -268,8 +328,14 @@ export class McpServer extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only handle requests to /mcp endpoint
|
||||
if (req.url !== '/mcp') {
|
||||
// Handle different endpoints
|
||||
if (req.url === '/mcp') {
|
||||
// Main MCP protocol endpoint
|
||||
} else if (req.url?.startsWith('/sessions')) {
|
||||
// Session management endpoint
|
||||
await this.handleSessionEndpoint(req, res);
|
||||
return;
|
||||
} else {
|
||||
this.debugLogger.log('HTTP', `404 - Invalid endpoint: ${req.url}`);
|
||||
res.statusCode = 404;
|
||||
res.end('Not Found');
|
||||
@@ -381,6 +447,52 @@ export class McpServer extends EventEmitter {
|
||||
res.end('Method Not Allowed');
|
||||
}
|
||||
|
||||
private async handleSessionEndpoint(req: http.IncomingMessage, res: http.ServerResponse): Promise<void> {
|
||||
const url = new URL(req.url || '', `http://localhost:${this.port}`);
|
||||
|
||||
if (req.method === 'POST' && url.pathname === '/sessions/register') {
|
||||
// Register a new session
|
||||
let body = '';
|
||||
req.on('data', (chunk) => { body += chunk.toString(); });
|
||||
req.on('end', () => {
|
||||
try {
|
||||
const { sessionId } = JSON.parse(body);
|
||||
this.registerSession(sessionId);
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, sessionId, totalSessions: this.activeSessions.size }));
|
||||
} catch (error) {
|
||||
res.statusCode = 400;
|
||||
res.end(JSON.stringify({ success: false, error: 'Invalid request body' }));
|
||||
}
|
||||
});
|
||||
} else if (req.method === 'DELETE' && url.pathname === '/sessions/unregister') {
|
||||
// Unregister a session
|
||||
let body = '';
|
||||
req.on('data', (chunk) => { body += chunk.toString(); });
|
||||
req.on('end', () => {
|
||||
try {
|
||||
const { sessionId } = JSON.parse(body);
|
||||
this.unregisterSession(sessionId);
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ success: true, sessionId, totalSessions: this.activeSessions.size }));
|
||||
} catch (error) {
|
||||
res.statusCode = 400;
|
||||
res.end(JSON.stringify({ success: false, error: 'Invalid request body' }));
|
||||
}
|
||||
});
|
||||
} else if (req.method === 'GET' && url.pathname === '/sessions') {
|
||||
// List active sessions
|
||||
res.statusCode = 200;
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify({ sessions: this.getActiveSessions(), totalSessions: this.activeSessions.size }));
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.end('Session endpoint not found');
|
||||
}
|
||||
}
|
||||
|
||||
async handleMessage(message: McpMessage): Promise<McpMessage | null> {
|
||||
this.debugLogger.log('MCP', 'Handling message:', message);
|
||||
|
||||
@@ -438,7 +550,23 @@ export class McpServer extends EventEmitter {
|
||||
}
|
||||
|
||||
private handleToolsList(message: McpMessage): McpMessage {
|
||||
const tools = Array.from(this.tools.values());
|
||||
// Use extension session ID if available, otherwise fall back to detecting from headers
|
||||
let sessionIdToUse = this.sessionId; // Extension session ID
|
||||
|
||||
// If no extension session, try to extract from message params or headers
|
||||
if (!sessionIdToUse && message.params?.sessionId) {
|
||||
sessionIdToUse = message.params.sessionId;
|
||||
}
|
||||
|
||||
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}`);
|
||||
} else {
|
||||
this.debugLogger.log('TOOLS', `Using default tools (no session ID available)`);
|
||||
}
|
||||
|
||||
return {
|
||||
id: message.id,
|
||||
type: 'response',
|
||||
@@ -448,10 +576,17 @@ export class McpServer extends EventEmitter {
|
||||
|
||||
private async handleToolCall(message: McpMessage): Promise<McpMessage> {
|
||||
const { name, arguments: args } = message.params;
|
||||
this.debugLogger.log('MCP', `Tool call - name: "${name}"`, { name, args });
|
||||
this.debugLogger.log('MCP', 'Available tools:', Array.from(this.tools.keys()));
|
||||
const sessionId = args?.sessionId; // Extract session ID from tool arguments
|
||||
|
||||
if (name === 'HumanAgent_Chat') {
|
||||
this.debugLogger.log('MCP', `Tool call - name: "${name}", session: ${sessionId}`, { name, args });
|
||||
|
||||
// Check session-specific tools first, then default tools
|
||||
const sessionTools = sessionId ? this.sessionTools.get(sessionId) : null;
|
||||
const availableTools = sessionTools || this.tools;
|
||||
|
||||
this.debugLogger.log('MCP', `Available tools for session ${sessionId || 'default'}:`, Array.from(availableTools.keys()));
|
||||
|
||||
if (name === 'HumanAgent_Chat' && availableTools.has(name)) {
|
||||
this.debugLogger.log('MCP', 'Executing HumanAgent_Chat tool');
|
||||
return await this.handleHumanAgentChatTool(message.id, args);
|
||||
}
|
||||
@@ -563,7 +698,11 @@ export class McpServer extends EventEmitter {
|
||||
|
||||
// Simplified API - no sessions needed
|
||||
|
||||
getAvailableTools(): McpTool[] {
|
||||
getAvailableTools(sessionId?: string): McpTool[] {
|
||||
if (sessionId && this.sessionTools.has(sessionId)) {
|
||||
return Array.from(this.sessionTools.get(sessionId)!.values());
|
||||
}
|
||||
// Fall back to default tools
|
||||
return Array.from(this.tools.values());
|
||||
}
|
||||
|
||||
@@ -597,4 +736,76 @@ export class McpServer extends EventEmitter {
|
||||
getPort(): number {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
registerSession(sessionId: string, workspacePath?: string): void {
|
||||
this.activeSessions.add(sessionId);
|
||||
|
||||
// Initialize session-specific tools if workspace path provided
|
||||
if (workspacePath) {
|
||||
this.initializeSessionTools(sessionId, workspacePath);
|
||||
}
|
||||
|
||||
this.debugLogger.log('INFO', `Session registered: ${sessionId} (${this.activeSessions.size} total sessions)`);
|
||||
}
|
||||
|
||||
unregisterSession(sessionId: string): void {
|
||||
this.activeSessions.delete(sessionId);
|
||||
// Clean up session-specific data
|
||||
this.sessionTools.delete(sessionId);
|
||||
this.sessionWorkspacePaths.delete(sessionId);
|
||||
this.debugLogger.log('INFO', `Session unregistered and cleaned up: ${sessionId} (${this.activeSessions.size} total sessions)`);
|
||||
}
|
||||
|
||||
getActiveSessions(): string[] {
|
||||
return Array.from(this.activeSessions);
|
||||
}
|
||||
|
||||
async restartSession(sessionId: string): Promise<void> {
|
||||
try {
|
||||
this.debugLogger.log('INFO', `Restarting session: ${sessionId}...`);
|
||||
|
||||
// Get workspace path before unregistering
|
||||
const workspacePath = this.sessionWorkspacePaths.get(sessionId);
|
||||
if (!workspacePath) {
|
||||
throw new Error(`No workspace path found for session ${sessionId}`);
|
||||
}
|
||||
|
||||
// Unregister session (cleans up old tools and data)
|
||||
this.unregisterSession(sessionId);
|
||||
|
||||
// Re-register session with fresh tools
|
||||
this.registerSession(sessionId, workspacePath);
|
||||
|
||||
this.debugLogger.log('INFO', `Session ${sessionId} restarted successfully with fresh tools`);
|
||||
} catch (error) {
|
||||
this.debugLogger.log('ERROR', `Failed to restart session ${sessionId}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async reloadOverrides(sessionId?: string): Promise<void> {
|
||||
try {
|
||||
this.debugLogger.log('INFO', `Reloading workspace overrides for session: ${sessionId || 'all sessions'}...`);
|
||||
|
||||
if (sessionId) {
|
||||
// Reload for specific session
|
||||
const workspacePath = this.sessionWorkspacePaths.get(sessionId);
|
||||
if (workspacePath) {
|
||||
this.initializeSessionTools(sessionId, workspacePath);
|
||||
this.debugLogger.log('INFO', `Session ${sessionId} overrides reloaded successfully`);
|
||||
} else {
|
||||
this.debugLogger.log('WARN', `No workspace path found for session ${sessionId}`);
|
||||
}
|
||||
} else {
|
||||
// Reload for all sessions
|
||||
for (const [sessionId, workspacePath] of this.sessionWorkspacePaths.entries()) {
|
||||
this.initializeSessionTools(sessionId, workspacePath);
|
||||
}
|
||||
this.debugLogger.log('INFO', 'All session overrides reloaded successfully');
|
||||
}
|
||||
} catch (error) {
|
||||
this.debugLogger.log('ERROR', 'Failed to reload workspace overrides:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { McpServer } from '../mcp/server';
|
||||
import { ChatMessage } from '../mcp/types';
|
||||
import { McpConfigManager } from '../mcp/mcpConfigManager';
|
||||
import { AudioNotification } from '../audio/audioNotification';
|
||||
|
||||
export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
public static readonly viewType = 'humanagent-mcp.chatView';
|
||||
@@ -12,18 +15,49 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
private extensionPath: string;
|
||||
private messages: ChatMessage[] = [];
|
||||
private currentRequestId?: string;
|
||||
private notificationSettings = {
|
||||
enableSound: true,
|
||||
enableFlashing: true
|
||||
};
|
||||
|
||||
constructor(
|
||||
private readonly _extensionUri: vscode.Uri,
|
||||
mcpServer: McpServer,
|
||||
mcpConfigManager?: McpConfigManager
|
||||
mcpConfigManager?: McpConfigManager,
|
||||
private readonly workspaceSessionId?: string
|
||||
) {
|
||||
this.mcpServer = mcpServer;
|
||||
this.mcpConfigManager = mcpConfigManager;
|
||||
this.extensionPath = _extensionUri.fsPath;
|
||||
this.loadNotificationSettings();
|
||||
}
|
||||
|
||||
public displayHumanAgentMessage(message: string, context?: string, requestId?: string) {
|
||||
private loadNotificationSettings() {
|
||||
try {
|
||||
// Try to load settings from mcp.json
|
||||
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
||||
if (workspaceRoot) {
|
||||
const mcpConfigPath = `${workspaceRoot}/.vscode/mcp.json`;
|
||||
const fs = require('fs');
|
||||
if (fs.existsSync(mcpConfigPath)) {
|
||||
const mcpConfig = JSON.parse(fs.readFileSync(mcpConfigPath, 'utf8'));
|
||||
// Check if humanagent-mcp server has notifications settings
|
||||
if (mcpConfig.servers && mcpConfig.servers['humanagent-mcp'] && mcpConfig.servers['humanagent-mcp'].notifications) {
|
||||
const notifications = mcpConfig.servers['humanagent-mcp'].notifications;
|
||||
this.notificationSettings = {
|
||||
enableSound: notifications.enableSound ?? true,
|
||||
enableFlashing: notifications.enableFlashing ?? true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('ChatWebviewProvider: Error loading notification settings:', error);
|
||||
// Use defaults on error
|
||||
}
|
||||
}
|
||||
|
||||
public async displayHumanAgentMessage(message: string, context?: string, requestId?: string) {
|
||||
// Store the current request ID for response handling
|
||||
this.currentRequestId = requestId;
|
||||
|
||||
@@ -42,12 +76,46 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
this.messages.push(aiMessage);
|
||||
this.updateWebview();
|
||||
|
||||
// Play notification sound if enabled
|
||||
if (this.notificationSettings.enableSound) {
|
||||
await this.playNotificationSound();
|
||||
}
|
||||
|
||||
// Trigger flashing animation if enabled
|
||||
if (this.notificationSettings.enableFlashing) {
|
||||
this.triggerFlashingBorder();
|
||||
}
|
||||
|
||||
// Focus the chat webview
|
||||
if (this._view) {
|
||||
this._view.show?.(true);
|
||||
}
|
||||
}
|
||||
|
||||
private async playNotificationSound() {
|
||||
try {
|
||||
// Play sound using Node.js audio system (bypasses browser restrictions)
|
||||
await AudioNotification.playNotificationBeep();
|
||||
} catch (error) {
|
||||
console.error('ChatWebviewProvider: Error playing notification sound:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private triggerFlashingBorder() {
|
||||
if (this._view) {
|
||||
// Send a message to the webview to trigger the flashing animation
|
||||
this._view.webview.postMessage({
|
||||
type: 'flashBorder'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public clearPendingRequest() {
|
||||
// Clear the request ID when AI is done processing
|
||||
this.currentRequestId = undefined;
|
||||
this.updateWebview();
|
||||
}
|
||||
|
||||
resolveWebviewView(webviewView: vscode.WebviewView, context: vscode.WebviewViewResolveContext, _token: vscode.CancellationToken) {
|
||||
this._view = webviewView;
|
||||
|
||||
@@ -69,7 +137,8 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
await this.handleMcpAction(data.action);
|
||||
break;
|
||||
case 'requestServerStatus':
|
||||
this.updateServerStatus();
|
||||
// Call the dedicated status command from extension.ts
|
||||
vscode.commands.executeCommand('humanagent-mcp.showStatus');
|
||||
break;
|
||||
}
|
||||
});
|
||||
@@ -94,8 +163,15 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
// Send response back to MCP server
|
||||
if (this.currentRequestId) {
|
||||
console.log('ChatWebviewProvider: Responding to request ID:', this.currentRequestId);
|
||||
this.mcpServer.respondToHumanRequest(this.currentRequestId, content);
|
||||
this.currentRequestId = undefined;
|
||||
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');
|
||||
}
|
||||
} else {
|
||||
console.warn('ChatWebviewProvider: No pending request to respond to');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('ChatWebviewProvider: Error in sendHumanResponse:', error);
|
||||
@@ -120,19 +196,179 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
const tools = this.mcpServer.getAvailableTools();
|
||||
const pendingRequests = this.mcpServer.getPendingRequests();
|
||||
const isRegistered = this.mcpConfigManager?.isMcpServerRegistered() ?? false;
|
||||
const isRegisteredWorkspace = this.mcpConfigManager?.isMcpServerRegistered(false) ?? false;
|
||||
const isRegisteredGlobal = this.mcpConfigManager?.isMcpServerRegistered(true) ?? false;
|
||||
const configType = isRegisteredWorkspace ? 'workspace' : (isRegisteredGlobal ? 'global' : 'none');
|
||||
|
||||
this._view.webview.postMessage({
|
||||
type: 'serverStatus',
|
||||
data: {
|
||||
running: true,
|
||||
running: this.mcpServer.isServerRunning(),
|
||||
tools: tools.length,
|
||||
pendingRequests: pendingRequests.length,
|
||||
registered: isRegistered
|
||||
registered: isRegisteredWorkspace || isRegisteredGlobal,
|
||||
configType: configType
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async reloadOverrideFile() {
|
||||
try {
|
||||
// Check if we have an active workspace
|
||||
if (!vscode.workspace.workspaceFolders || vscode.workspace.workspaceFolders.length === 0) {
|
||||
vscode.window.showErrorMessage('No workspace is currently open');
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders[0];
|
||||
const overrideFilePath = path.join(workspaceFolder.uri.fsPath, '.vscode', 'HumanAgentOverride.json');
|
||||
|
||||
// Check if override file exists
|
||||
if (!fs.existsSync(overrideFilePath)) {
|
||||
vscode.window.showWarningMessage('No HumanAgentOverride.json file found in .vscode directory');
|
||||
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');
|
||||
}
|
||||
|
||||
// Refresh the webview to update the menu
|
||||
if (this._view) {
|
||||
this._view.webview.html = this._getHtmlForWebview(this._view.webview);
|
||||
}
|
||||
|
||||
console.log('ChatWebviewProvider: Override file reloaded successfully');
|
||||
|
||||
} catch (error) {
|
||||
console.error('ChatWebviewProvider: Error reloading override file:', error);
|
||||
vscode.window.showErrorMessage(`Failed to reload override file: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async createPromptOverrideFile() {
|
||||
try {
|
||||
console.log('ChatWebviewProvider: Creating prompt override file...');
|
||||
|
||||
// Get current workspace folder
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||
if (!workspaceFolder) {
|
||||
vscode.window.showErrorMessage('No workspace folder found. Open a workspace to create override file.');
|
||||
return;
|
||||
}
|
||||
|
||||
const vscodeDir = path.join(workspaceFolder.uri.fsPath, '.vscode');
|
||||
const overrideFilePath = path.join(vscodeDir, 'HumanAgentOverride.json');
|
||||
|
||||
// Create .vscode directory if it doesn't exist
|
||||
if (!fs.existsSync(vscodeDir)) {
|
||||
fs.mkdirSync(vscodeDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Check if file already exists
|
||||
if (fs.existsSync(overrideFilePath)) {
|
||||
const result = await vscode.window.showWarningMessage(
|
||||
'Override file already exists. Do you want to overwrite it?',
|
||||
'Overwrite', 'Cancel'
|
||||
);
|
||||
if (result !== 'Overwrite') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 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']
|
||||
}
|
||||
};
|
||||
|
||||
// Create example tool with medium detail
|
||||
const exampleTool = {
|
||||
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']
|
||||
}
|
||||
};
|
||||
|
||||
// Create override configuration
|
||||
const overrideConfig = {
|
||||
version: '1.0.0',
|
||||
description: 'HumanAgent MCP Tool Overrides for this workspace. Modify tool configurations below to customize MCP server behavior.',
|
||||
tools: {
|
||||
HumanAgent_Chat: defaultTool,
|
||||
example_custom_tool: exampleTool
|
||||
}
|
||||
};
|
||||
|
||||
// Write the file
|
||||
fs.writeFileSync(overrideFilePath, JSON.stringify(overrideConfig, null, 2));
|
||||
|
||||
vscode.window.showInformationMessage(
|
||||
`Override file created at ${overrideFilePath}. Modify the tool configuration as needed.`,
|
||||
'Open File'
|
||||
).then(selection => {
|
||||
if (selection === 'Open File') {
|
||||
vscode.window.showTextDocument(vscode.Uri.file(overrideFilePath));
|
||||
}
|
||||
});
|
||||
|
||||
console.log('ChatWebviewProvider: Override file created successfully');
|
||||
|
||||
} catch (error) {
|
||||
console.error('ChatWebviewProvider: Error creating override file:', error);
|
||||
vscode.window.showErrorMessage(`Failed to create override file: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async handleMcpAction(action: string) {
|
||||
try {
|
||||
switch (action) {
|
||||
@@ -145,9 +381,16 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
vscode.window.showInformationMessage('MCP Server stopped');
|
||||
break;
|
||||
case 'restart':
|
||||
await this.mcpServer.stop();
|
||||
await this.mcpServer.start();
|
||||
vscode.window.showInformationMessage('MCP Server restarted');
|
||||
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');
|
||||
}
|
||||
break;
|
||||
case 'register':
|
||||
// Use the MCP configuration from the parent command
|
||||
@@ -159,6 +402,16 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
case 'configure':
|
||||
vscode.commands.executeCommand('humanagent-mcp.configureMcp');
|
||||
break;
|
||||
case 'testSound':
|
||||
// Test notification sound by triggering a fake notification
|
||||
await this.displayHumanAgentMessage('🔊 Audio test - this is a test notification sound!', 'Testing audio notifications', 'test-audio');
|
||||
break;
|
||||
case 'overridePrompt':
|
||||
await this.createPromptOverrideFile();
|
||||
break;
|
||||
case 'reloadOverride':
|
||||
await this.reloadOverrideFile();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update status after action
|
||||
@@ -169,6 +422,14 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
|
||||
private _getHtmlForWebview(webview: vscode.Webview) {
|
||||
// Check if HumanAgentOverride.json exists in workspace
|
||||
let overrideFileExists = false;
|
||||
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
|
||||
const workspaceFolder = vscode.workspace.workspaceFolders[0];
|
||||
const overrideFilePath = path.join(workspaceFolder.uri.fsPath, '.vscode', 'HumanAgentOverride.json');
|
||||
overrideFileExists = fs.existsSync(overrideFilePath);
|
||||
}
|
||||
|
||||
const messagesHtml = this.messages.map(message => {
|
||||
const messageClass = message.sender === 'agent' ? 'ai-message' : 'human-message';
|
||||
const timestamp = message.timestamp.toLocaleTimeString();
|
||||
@@ -205,6 +466,20 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: border 0.1s ease-in-out;
|
||||
}
|
||||
|
||||
body.flashing {
|
||||
border: 3px solid var(--vscode-charts-orange);
|
||||
animation: flashBorder 2s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes flashBorder {
|
||||
0% { border-color: var(--vscode-charts-orange); }
|
||||
25% { border-color: transparent; }
|
||||
50% { border-color: var(--vscode-charts-orange); }
|
||||
75% { border-color: transparent; }
|
||||
100% { border-color: transparent; }
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -370,10 +645,9 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
<div class="status">
|
||||
<div class="status-indicator">
|
||||
<div class="status-dot"></div>
|
||||
<span>HumanAgent MCP Server</span>
|
||||
<span id="server-status-text">HumanAgent MCP Server</span>
|
||||
</div>
|
||||
<div class="control-buttons">
|
||||
<button class="control-button" onclick="requestServerStatus()">Status</button>
|
||||
<button class="cog-button" onclick="showConfigMenu()" title="Configure MCP">⚙️</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -393,6 +667,100 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
// Set global flag for override file existence
|
||||
window.overrideFileExists = ${overrideFileExists};
|
||||
|
||||
// Audio context for notifications
|
||||
let audioContext = null;
|
||||
let preloadedAudio = null;
|
||||
|
||||
// Initialize audio on first user interaction
|
||||
function initAudio() {
|
||||
if (!audioContext) {
|
||||
try {
|
||||
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
||||
// Resume in case it's in suspended state
|
||||
if (audioContext.state === 'suspended') {
|
||||
audioContext.resume();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to create audio context:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-load and test audio
|
||||
if (!preloadedAudio) {
|
||||
try {
|
||||
preloadedAudio = new Audio();
|
||||
preloadedAudio.src = "data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmMaBSGI0PTVnhY=";
|
||||
preloadedAudio.volume = 0.3;
|
||||
preloadedAudio.preload = 'auto';
|
||||
// Play and immediately pause to establish permission
|
||||
preloadedAudio.play().then(() => {
|
||||
preloadedAudio.pause();
|
||||
preloadedAudio.currentTime = 0;
|
||||
console.log('Audio initialized successfully');
|
||||
}).catch(e => {
|
||||
console.log('Audio initialization failed:', e);
|
||||
preloadedAudio = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to create audio element:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Play notification beep sound
|
||||
function playNotificationBeep() {
|
||||
try {
|
||||
if (preloadedAudio) {
|
||||
console.log('Playing preloaded audio');
|
||||
preloadedAudio.currentTime = 0;
|
||||
preloadedAudio.play().then(() => {
|
||||
console.log('Audio played successfully');
|
||||
}).catch(e => {
|
||||
console.log('Preloaded audio play failed:', e);
|
||||
// Try to re-initialize if failed
|
||||
initAudio();
|
||||
});
|
||||
} else {
|
||||
console.log('Audio not initialized - trying to initialize now');
|
||||
initAudio();
|
||||
// Try Web Audio API fallback
|
||||
try {
|
||||
if (audioContext && audioContext.state === 'running') {
|
||||
const oscillator = audioContext.createOscillator();
|
||||
const gainNode = audioContext.createGain();
|
||||
|
||||
oscillator.connect(gainNode);
|
||||
gainNode.connect(audioContext.destination);
|
||||
|
||||
oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
|
||||
|
||||
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
|
||||
gainNode.gain.linearRampToValueAtTime(0.3, audioContext.currentTime + 0.01);
|
||||
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
|
||||
|
||||
oscillator.start(audioContext.currentTime);
|
||||
oscillator.stop(audioContext.currentTime + 0.2);
|
||||
console.log('Web Audio fallback played');
|
||||
} else {
|
||||
console.log('Web Audio context not available');
|
||||
}
|
||||
} catch (e2) {
|
||||
console.error('Fallback audio also failed:', e2);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error playing notification sound:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize audio on any user interaction
|
||||
document.addEventListener('click', initAudio, { once: true });
|
||||
document.addEventListener('keypress', initAudio, { once: true });
|
||||
document.addEventListener('touchstart', initAudio, { once: true });
|
||||
|
||||
document.getElementById('messageInput').addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
@@ -402,10 +770,56 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
});
|
||||
|
||||
function showConfigMenu() {
|
||||
vscode.postMessage({
|
||||
type: 'mcpAction',
|
||||
action: 'configure'
|
||||
// Create dropdown menu
|
||||
const existingMenu = document.getElementById('configMenu');
|
||||
if (existingMenu) {
|
||||
existingMenu.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
const menu = document.createElement('div');
|
||||
menu.id = 'configMenu';
|
||||
menu.style.position = 'absolute';
|
||||
menu.style.top = '30px';
|
||||
menu.style.right = '10px';
|
||||
menu.style.background = 'var(--vscode-menu-background)';
|
||||
menu.style.border = '1px solid var(--vscode-menu-border)';
|
||||
menu.style.borderRadius = '3px';
|
||||
menu.style.boxShadow = '0 2px 8px rgba(0,0,0,0.3)';
|
||||
menu.style.zIndex = '1000';
|
||||
menu.style.minWidth = '150px';
|
||||
|
||||
// Get dynamic options based on current status
|
||||
const options = getDynamicMenuOptions();
|
||||
|
||||
options.forEach(option => {
|
||||
const item = document.createElement('div');
|
||||
item.textContent = option.text;
|
||||
item.style.padding = '8px 12px';
|
||||
item.style.cursor = 'pointer';
|
||||
item.style.color = 'var(--vscode-menu-foreground)';
|
||||
item.onmouseover = () => item.style.background = 'var(--vscode-menu-selectionBackground)';
|
||||
item.onmouseout = () => item.style.background = 'transparent';
|
||||
item.onclick = () => {
|
||||
vscode.postMessage({
|
||||
type: 'mcpAction',
|
||||
action: option.action
|
||||
});
|
||||
menu.remove();
|
||||
};
|
||||
menu.appendChild(item);
|
||||
});
|
||||
|
||||
document.body.appendChild(menu);
|
||||
|
||||
// Close menu when clicking elsewhere
|
||||
setTimeout(() => {
|
||||
document.addEventListener('click', (e) => {
|
||||
if (!menu.contains(e.target)) {
|
||||
menu.remove();
|
||||
}
|
||||
}, { once: true });
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function sendMessage() {
|
||||
@@ -421,6 +835,56 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// Global variable to store current server status
|
||||
let currentServerStatus = null;
|
||||
|
||||
function getDynamicMenuOptions() {
|
||||
const options = [];
|
||||
|
||||
if (!currentServerStatus) {
|
||||
// Default options when status unknown
|
||||
const defaultOptions = [
|
||||
{ text: '📦 Install Globally', action: 'register' },
|
||||
{ text: '📁 Install in Workspace', action: 'unregister' },
|
||||
{ text: '📊 Show Status', action: 'requestServerStatus' },
|
||||
{ text: '🛠️ Override Prompt', action: 'overridePrompt' }
|
||||
];
|
||||
|
||||
// Check for override file existence even when status unknown
|
||||
if (window.overrideFileExists) {
|
||||
defaultOptions.push({ text: '🔄 Reload Override File', action: 'reloadOverride' });
|
||||
}
|
||||
|
||||
defaultOptions.push({ text: '⚙️ Configure MCP', action: 'configure' });
|
||||
return defaultOptions;
|
||||
}
|
||||
|
||||
// Dynamic options based on current registration status
|
||||
if (currentServerStatus.configType === 'workspace') {
|
||||
options.push({ text: '🗑️ Uninstall from Workspace', action: 'unregister' });
|
||||
options.push({ text: '📦 Install Globally', action: 'register' });
|
||||
} else if (currentServerStatus.configType === 'global') {
|
||||
options.push({ text: '📁 Install in Workspace', action: 'register' });
|
||||
options.push({ text: '🗑️ Uninstall Globally', action: 'unregister' });
|
||||
} else {
|
||||
// Not installed anywhere
|
||||
options.push({ text: '📦 Install Globally', action: 'register' });
|
||||
options.push({ text: '📁 Install in Workspace', action: 'unregister' });
|
||||
}
|
||||
|
||||
options.push({ text: '📊 Show Status', action: 'requestServerStatus' });
|
||||
options.push({ text: '🛠️ Override Prompt', action: 'overridePrompt' });
|
||||
|
||||
// Check for HumanAgentOverride.json file existence (passed from extension)
|
||||
if (window.overrideFileExists) {
|
||||
options.push({ text: '🔄 Reload Override File', action: 'reloadOverride' });
|
||||
}
|
||||
|
||||
options.push({ text: '⚙️ Configure MCP', action: 'configure' });
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function handleMcpAction(action) {
|
||||
vscode.postMessage({
|
||||
type: 'mcpAction',
|
||||
@@ -438,14 +902,39 @@ export class ChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||
const messagesContainer = document.getElementById('messages');
|
||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||
|
||||
// Listen for server status updates
|
||||
// Listen for messages from extension
|
||||
window.addEventListener('message', event => {
|
||||
const message = event.data;
|
||||
if (message.type === 'serverStatus') {
|
||||
// Could update UI with server status if needed
|
||||
// Update global status variable
|
||||
currentServerStatus = message.data;
|
||||
|
||||
// Update status text based on configuration
|
||||
const statusElement = document.getElementById('server-status-text');
|
||||
if (statusElement && message.data.configType) {
|
||||
if (message.data.configType === 'workspace') {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Workspace)';
|
||||
} else if (message.data.configType === 'global') {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Global)';
|
||||
} else {
|
||||
statusElement.textContent = 'HumanAgent MCP Server (Not Configured)';
|
||||
}
|
||||
}
|
||||
console.log('Server status:', message.data);
|
||||
} else if (message.type === 'flashBorder') {
|
||||
// Trigger flashing border animation
|
||||
document.body.classList.add('flashing');
|
||||
setTimeout(() => {
|
||||
document.body.classList.remove('flashing');
|
||||
}, 2000);
|
||||
} else if (message.type === 'playSound') {
|
||||
// Play notification sound
|
||||
console.log('Playing notification sound...');
|
||||
playNotificationBeep();
|
||||
}
|
||||
});
|
||||
|
||||
// Webview initialized - status can be requested manually via cog menu
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user