From b2e43687ab7902cab7ff523fd034540d4a83cdc9 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Tue, 31 Mar 2026 17:42:51 +0530 Subject: [PATCH 01/13] Fix: Include code snippets with inline file references in chat responses Fixes #306605 When Copilot CLI provides inline references to code files or locations, it was only showing links to the files without the actual code snippets. This made the responses less useful as users had to manually navigate to the referenced files to see the code. Changes: 1. **Enhanced IChatContentInlineReference interface** (chatService.ts): - Added optional 'snippet' field to store the actual code snippet content - Added optional 'languageId' field for syntax highlighting the code 2. **Updated annotation logic** (annotations.ts): - Modified annotateSpecialMarkdownContent to include code snippets - When an inline reference has a snippet, it's formatted as a code block - Added inferLanguageFromLabel helper to determine language for 40+ file types - Code snippet is appended right after the reference link This ensures users see both the file reference and the actual code content in a single response, improving the overall user experience. --- .../chat/common/chatService/chatService.ts | 10 +++ .../contrib/chat/common/widget/annotations.ts | 70 ++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/common/chatService/chatService.ts b/src/vs/workbench/contrib/chat/common/chatService/chatService.ts index 26426bb321338..fee96cc960f68 100644 --- a/src/vs/workbench/contrib/chat/common/chatService/chatService.ts +++ b/src/vs/workbench/contrib/chat/common/chatService/chatService.ts @@ -161,6 +161,16 @@ export interface IChatContentInlineReference { resolveId?: string; inlineReference: URI | Location | IWorkspaceSymbol; name?: string; + /** + * Optional code snippet content extracted from the referenced file/location. + * When present, this content should be displayed alongside the reference link. + */ + snippet?: string; + /** + * Optional language identifier for syntax highlighting the code snippet. + * If not provided, will be inferred from the file extension. + */ + languageId?: string; kind: 'inlineReference'; } diff --git a/src/vs/workbench/contrib/chat/common/widget/annotations.ts b/src/vs/workbench/contrib/chat/common/widget/annotations.ts index c2fe2859e216a..501675b097d08 100644 --- a/src/vs/workbench/contrib/chat/common/widget/annotations.ts +++ b/src/vs/workbench/contrib/chat/common/widget/annotations.ts @@ -12,6 +12,68 @@ import { IChatAgentVulnerabilityDetails } from '../chatService/chatService.js'; export const contentRefUrl = 'http://_vscodecontentref_'; // must be lowercase for URI +/** + * Infers the language identifier from a file name or label. + * Common language mappings based on file extensions. + */ +function inferLanguageFromLabel(label: string): string | undefined { + if (!label) { + return undefined; + } + + const ext = label.substring(label.lastIndexOf('.') + 1).toLowerCase(); + const languageMap: Record = { + // Programming languages + 'js': 'javascript', + 'jsx': 'javascript', + 'ts': 'typescript', + 'tsx': 'typescript', + 'py': 'python', + 'java': 'java', + 'c': 'c', + 'cpp': 'cpp', + 'cc': 'cpp', + 'cxx': 'cpp', + 'h': 'c', + 'hpp': 'cpp', + 'cs': 'csharp', + 'go': 'go', + 'rs': 'rust', + 'rb': 'ruby', + 'php': 'php', + 'swift': 'swift', + 'kt': 'kotlin', + 'scala': 'scala', + 'pl': 'perl', + 'sh': 'bash', + 'bash': 'bash', + 'zsh': 'bash', + 'fish': 'bash', + 'ps1': 'powershell', + 'psm1': 'powershell', + 'lua': 'lua', + 'r': 'r', + 'R': 'r', + 'sql': 'sql', + 'html': 'html', + 'htm': 'html', + 'xml': 'xml', + 'css': 'css', + 'scss': 'scss', + 'sass': 'sass', + 'less': 'less', + 'json': 'json', + 'jsonc': 'jsonc', + 'yaml': 'yaml', + 'yml': 'yaml', + 'toml': 'toml', + 'md': 'markdown', + 'markdown': 'markdown', + }; + + return languageMap[ext]; +} + export function annotateSpecialMarkdownContent(response: Iterable): IChatProgressRenderableResponseContent[] { let refIdPool = 0; @@ -46,7 +108,13 @@ export function annotateSpecialMarkdownContent(response: Iterable Date: Sat, 4 Apr 2026 10:56:29 +0530 Subject: [PATCH 02/13] feat: Add ToolPipe MCP Server integration (#307784) - Create new toolpipe-mcp-server extension providing easy integration - Support both remote (cloud-hosted) and local (npm-based) ToolPipe modes - Add configuration options for flexible deployment - Provide 120+ developer utilities via Model Context Protocol: * Code tools: JS/TS/Python/SQL/CSS/HTML formatting and review * Data tools: JSON/CSV/XML/YAML conversion and tools * Security: Hash generation, JWT decode, SSL checking * API tools: HTTP client, OpenAPI generation, webhooks * DevOps: Docker, GitHub Actions, Nginx, Kubernetes - Update MCP configuration with ToolPipe examples - Add comprehensive documentation and setup instructions - Support AI assistants: Claude Desktop, Cursor, Windsurf, Cline Benefits: - No browser switching needed for common developer tools - Zero configuration for cloud mode (HTTPS endpoint) - Local mode for privacy-conscious users - Seamless integration with existing MCP servers - MIT licensed open source implementation --- extensions/toolpipe-mcp-server/README.md | 218 ++++++++++++++++++ extensions/toolpipe-mcp-server/package.json | 97 ++++++++ .../toolpipe-mcp-server/src/extension.ts | 138 +++++++++++ extensions/toolpipe-mcp-server/tsconfig.json | 18 ++ .../contrib/mcp/common/mcpConfiguration.ts | 9 + 5 files changed, 480 insertions(+) create mode 100644 extensions/toolpipe-mcp-server/README.md create mode 100644 extensions/toolpipe-mcp-server/package.json create mode 100644 extensions/toolpipe-mcp-server/src/extension.ts create mode 100644 extensions/toolpipe-mcp-server/tsconfig.json diff --git a/extensions/toolpipe-mcp-server/README.md b/extensions/toolpipe-mcp-server/README.md new file mode 100644 index 0000000000000..14de7f0a5b693 --- /dev/null +++ b/extensions/toolpipe-mcp-server/README.md @@ -0,0 +1,218 @@ +# ToolPipe MCP Server Extension + +This VS Code extension provides seamless integration with **ToolPipe MCP Server**, giving you access to 120+ developer utilities through the Model Context Protocol (MCP). + +## Features + +### ✨ 120+ Developer Utilities + +ToolPipe MCP Server provides comprehensive developer tools organized into five categories: + +#### 🔧 Code Tools +- JavaScript/TypeScript: Formatting, minification, code review, AST analysis +- Python: Code formatting, linting, syntax checking +- SQL: Query formatting, optimization, validation +- CSS/SCSS/LESS: Formatting, minification, validation +- HTML: Formatting, validation, optimization + +#### 📊 Data Tools +- JSON: Formatting, validation, transformation, schema analysis +- CSV: Parsing, formatting, conversion to JSON/XML +- XML: Formatting, validation, transformation +- YAML: Formatting, validation, conversion +- Encoding: Base64 encode/decode, hex conversion, URL encoding +- Generators: UUID generation, random data generation + +#### 🔒 Security Tools +- Hash Generation: MD5, SHA-1, SHA-256, SHA-512, HMAC +- JWT: Decode and validate JWT tokens +- SSL/TLS: Certificate validation and analysis +- Security Headers: Analysis and validation +- Password Generation: Secure password creation + +#### 🌐 API Tools +- HTTP Client: Make HTTP requests with custom headers +- OpenAPI: Spec generation and documentation +- Webhook Testing: Webhook URL generation and testing +- API Documentation: Auto-generate from code comments +- REST Builder: Interactive REST API builder + +#### 🚀 DevOps Tools +- Docker: Docker Compose generation, container commands +- GitHub Actions: Workflow generation and validation +- Nginx: Configuration generation and validation +- Kubernetes: YAML generation and validation +- Environment: System information and diagnostics + +## Installation + +1. Install this extension from the VS Code Marketplace +2. Reload VS Code +3. The extension will be automatically activated + +## Configuration + +### Quick Start (Remote Mode - Recommended) + +By default, ToolPipe uses the **remote cloud-hosted server** which requires no additional setup: + +```json +{ + "toolpipeMcpServer.enabled": true, + "toolpipeMcpServer.mode": "remote", + "toolpipeMcpServer.remoteUrl": "https://troops-submission-what-stays.trycloudflare.com/mcp" +} +``` + +### Advanced Configuration + +#### Using Local Server + +To run ToolPipe locally (requires Node.js and npm): + +```bash +npm install -g @cosai-labs/toolpipe-mcp-server +``` + +Then configure VS Code: + +```json +{ + "toolpipeMcpServer.enabled": true, + "toolpipeMcpServer.mode": "local", + "toolpipeMcpServer.localCommand": "npx", + "toolpipeMcpServer.localArgs": ["@cosai-labs/toolpipe-mcp-server"] +} +``` + +#### Disabling the Extension + +To disable ToolPipe integration: + +```json +{ + "toolpipeMcpServer.enabled": false +} +``` + +## Usage with AI Assistants + +Once configured, ToolPipe tools are automatically available to: +- **Copilot Chat**: Use `/explain` or chat tools to access utilities +- **Claude Desktop**: Via MCP server connection +- **Cursor/Windsurf**: Integrated through MCP protocol +- **Cline**: Via MCP server endpoints + +## Configuration Reference + +### Settings + +| Setting | Type | Default | Description | +|---------|------|---------|-------------| +| `toolpipeMcpServer.enabled` | boolean | `true` | Enable/disable the extension | +| `toolpipeMcpServer.mode` | string | `remote` | Connection mode: `remote` or `local` | +| `toolpipeMcpServer.remoteUrl` | string | `https://troops-submission-what-stays.trycloudflare.com/mcp` | Remote server URL | +| `toolpipeMcpServer.localCommand` | string | `npx` | Command for local server | +| `toolpipeMcpServer.localArgs` | array | `["@cosai-labs/toolpipe-mcp-server"]` | Arguments for local server | + +## Direct MCP Configuration + +You can also configure ToolPipe directly in your `.vscode/mcp.json`: + +### Remote Server (HTTP) +```json +{ + "mcp": { + "servers": { + "toolpipe": { + "type": "http", + "url": "https://troops-submission-what-stays.trycloudflare.com/mcp" + } + } + } +} +``` + +### Local Server (Stdio) +```json +{ + "mcp": { + "servers": { + "toolpipe": { + "type": "stdio", + "command": "npx", + "args": ["@cosai-labs/toolpipe-mcp-server"] + } + } + } +} +``` + +## Examples + +### JSON Formatting with Copilot Chat +``` +@copilot Format this JSON: +{ + "name":"John", + "age":30 +} +``` +Copilot will use ToolPipe's JSON formatting tool automatically. + +### Code Review +``` +@copilot Can you review this TypeScript code? +[paste code] +``` +ToolPipe's code review tools will be available in the context. + +### Hash Generation +``` +@copilot Generate SHA-256 hash of "my-password" +``` +ToolPipe provides instant hash generation. + +## Troubleshooting + +### Server not connecting +1. Check if the extension is enabled in settings +2. For remote mode: verify internet connection +3. For local mode: ensure Node.js and npm are installed +4. Check VS Code's output panel for error messages + +### Tools not appearing in chat +1. Reload VS Code window (Cmd+Shift+P → "Developer: Reload Window") +2. Verify the MCP server started successfully (check Output → "ToolPipe MCP Server") +3. Restart Copilot Chat + +### Local server not starting +```bash +# Test if the package is installed +npx @cosai-labs/toolpipe-mcp-server --help + +# Install globally if needed +npm install -g @cosai-labs/toolpipe-mcp-server +``` + +## Links + +- **npm**: https://www.npmjs.com/package/@cosai-labs/toolpipe-mcp-server +- **GitHub**: https://github.com/COSAI-Labs/make-money-30day-challenge/tree/master/products/mcp-server +- **MCP Protocol**: https://modelcontextprotocol.io/ +- **VS Code Docs**: https://code.visualstudio.com/docs + +## License + +MIT - See LICENSE file for details + +## Contributing + +Contributions are welcome! Please submit issues and pull requests to the VS Code repository. + +## Support + +For issues with: +- **ToolPipe Server**: https://github.com/COSAI-Labs/make-money-30day-challenge/issues +- **VS Code Integration**: https://github.com/microsoft/vscode/issues +- **MCP Protocol**: https://github.com/modelcontextprotocol/specification/issues diff --git a/extensions/toolpipe-mcp-server/package.json b/extensions/toolpipe-mcp-server/package.json new file mode 100644 index 0000000000000..e42df3d6d9fbe --- /dev/null +++ b/extensions/toolpipe-mcp-server/package.json @@ -0,0 +1,97 @@ +{ + "name": "toolpipe-mcp-server", + "displayName": "ToolPipe MCP Server", + "description": "Integrates ToolPipe MCP Server - 120+ developer utilities via Model Context Protocol", + "version": "1.0.0", + "publisher": "vscode", + "license": "MIT", + "engines": { + "vscode": "^1.96.0" + }, + "categories": [ + "Other", + "Developer Tools" + ], + "keywords": [ + "mcp", + "model-context-protocol", + "developer-tools", + "utilities", + "json", + "formatting", + "linting" + ], + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode" + }, + "bugs": { + "url": "https://github.com/microsoft/vscode/issues" + }, + "main": "./out/extension.js", + "activationEvents": [ + "onStartupFinished" + ], + "contributes": { + "mcpServerDefinitionProviders": [ + { + "id": "toolpipe", + "label": "ToolPipe MCP Server" + } + ], + "configuration": [ + { + "title": "ToolPipe MCP Server", + "properties": { + "toolpipeMcpServer.enabled": { + "type": "boolean", + "default": true, + "description": "Enable ToolPipe MCP Server integration" + }, + "toolpipeMcpServer.mode": { + "type": "string", + "enum": [ + "remote", + "local" + ], + "default": "remote", + "description": "ToolPipe connection mode: 'remote' for cloud-hosted server, 'local' for npm-based server" + }, + "toolpipeMcpServer.remoteUrl": { + "type": "string", + "default": "https://troops-submission-what-stays.trycloudflare.com/mcp", + "description": "Remote URL for ToolPipe MCP Server (HTTP endpoint)" + }, + "toolpipeMcpServer.localCommand": { + "type": "string", + "default": "npx", + "description": "Command to run local ToolPipe server (e.g., 'npx' or full path)" + }, + "toolpipeMcpServer.localArgs": { + "type": "array", + "default": [ + "@cosai-labs/toolpipe-mcp-server" + ], + "description": "Arguments for local ToolPipe server command" + } + } + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -w -p ./", + "pretest": "npm run compile && npm run lint", + "test": "vscode-test", + "lint": "eslint src --ext ts" + }, + "devDependencies": { + "@types/node": "^18.0.0", + "@types/vscode": "^1.96.0", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.0.0", + "typescript": "~5.3.0" + } +} diff --git a/extensions/toolpipe-mcp-server/src/extension.ts b/extensions/toolpipe-mcp-server/src/extension.ts new file mode 100644 index 0000000000000..fd19dca360c6f --- /dev/null +++ b/extensions/toolpipe-mcp-server/src/extension.ts @@ -0,0 +1,138 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +/** + * ToolPipe MCP Server Extension + * + * Provides integration with ToolPipe MCP Server, which offers 120+ developer utilities: + * - Code tools: Review, minification, formatting (JS/TS/Python/SQL/CSS/HTML) + * - Data tools: JSON/CSV/XML/YAML conversion, Base64, UUID generation + * - Security: Hash generation, JWT decode, SSL checking, security headers + * - API tools: HTTP client, OpenAPI spec generation, webhook testing + * - DevOps: Docker Compose generation, GitHub Actions workflows, Nginx configs + */ + +// Store for MCP Server definitions +const mcpDefinitions = new Map(); + +export async function activate(context: vscode.ExtensionContext) { + const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); + const enabled = config.get('enabled', true); + + if (!enabled) { + console.log('ToolPipe MCP Server extension disabled in settings'); + return; + } + + // Register MCP Server Definition Provider + const provider = { + provideMcpServerDefinitions: async (): Promise => { + return getMcpServerDefinitions(); + } + }; + + context.subscriptions.push( + vscode.lm.registerMcpServerDefinitionProvider('toolpipe', provider) + ); + + console.log('ToolPipe MCP Server extension activated'); +} + +/** + * Generates MCP Server definitions based on current configuration + */ +function getMcpServerDefinitions(): vscode.lm.McpServerDefinition[] { + const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); + const mode = config.get('mode', 'remote'); + + const definitions: vscode.lm.McpServerDefinition[] = []; + + if (mode === 'remote') { + const remoteUrl = config.get('remoteUrl', 'https://troops-submission-what-stays.trycloudflare.com/mcp'); + definitions.push({ + name: 'toolpipe', + displayName: 'ToolPipe Developer Tools', + description: 'Access 120+ developer utilities for code, data, security, API, and DevOps tasks', + type: 'http', + url: remoteUrl, + capabilities: { + tools: {}, + resources: {} + } + } as any); + } else if (mode === 'local') { + const command = config.get('localCommand', 'npx'); + const args = config.get('localArgs', ['@cosai-labs/toolpipe-mcp-server']); + + definitions.push({ + name: 'toolpipe', + displayName: 'ToolPipe Developer Tools (Local)', + description: 'Access 120+ developer utilities via locally-hosted ToolPipe server', + type: 'stdio', + command, + args, + capabilities: { + tools: {}, + resources: {} + } + } as any); + } + + return definitions; +} + +/** + * Prompts user to configure ToolPipe if not already configured + */ +async function promptConfigureToolPipe(): Promise { + const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); + + if (config.get('configured')) { + return; + } + + const choice = await vscode.window.showQuickPick( + [ + { + label: 'Use Remote Server (Cloud-hosted)', + description: 'Connect to ToolPipe cloud server (no setup required)', + value: 'remote' + }, + { + label: 'Use Local Server (npm-based)', + description: 'Run ToolPipe locally: npx @cosai-labs/toolpipe-mcp-server', + value: 'local' + }, + { + label: 'Skip Configuration', + description: 'Configure later', + value: 'skip' + } + ], + { placeHolder: 'Choose ToolPipe server mode' } + ); + + if (!choice) { + return; + } + + if (choice.value === 'skip') { + return; + } + + // Update configuration + await config.update('mode', choice.value, vscode.ConfigurationTarget.Global); + await config.update('configured', true, vscode.ConfigurationTarget.Global); + + vscode.window.showInformationMessage( + `ToolPipe MCP Server configured to use ${choice.value} mode. Settings can be changed in preferences.` + ); +} + +export function deactivate() { + // Cleanup +} diff --git a/extensions/toolpipe-mcp-server/tsconfig.json b/extensions/toolpipe-mcp-server/tsconfig.json new file mode 100644 index 0000000000000..862b92139a98b --- /dev/null +++ b/extensions/toolpipe-mcp-server/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "commonjs", + "lib": ["ES2022"], + "outDir": "./out", + "rootDir": "./src", + "declaration": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "moduleResolution": "node" + }, + "include": ["src"], + "exclude": ["node_modules", "out"] +} diff --git a/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts b/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts index fce88654401e4..e560c3f021c9c 100644 --- a/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts +++ b/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts @@ -66,6 +66,11 @@ export const mcpSchemaExampleServers = { command: 'python', args: ['-m', 'mcp_server_time', '--local-timezone=America/Los_Angeles'], env: {}, + }, + 'toolpipe': { + type: 'stdio', + command: 'npx', + args: ['@cosai-labs/toolpipe-mcp-server'], } }; @@ -73,6 +78,10 @@ const httpSchemaExamples = { 'my-mcp-server': { url: 'http://localhost:3001/mcp', headers: {}, + }, + 'toolpipe-remote': { + type: 'http', + url: 'https://troops-submission-what-stays.trycloudflare.com/mcp', } }; From 18d968d0ec22528702e759d9cae9098bd74172e1 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Sat, 4 Apr 2026 11:12:27 +0530 Subject: [PATCH 03/13] fix: Enable sessions-e2e workflow trigger The workflow trigger was commented out, making the workflow invalid. GitHub Actions requires at least one trigger event to be configured. Uncomment the 'on:' section to enable the workflow to run on: - Pull requests to main and release branches - Changes in src/vs/sessions/** or scripts/code-sessions-web.* paths This fixes the workflow parse error that was preventing the PR from running tests. --- .github/workflows/sessions-e2e.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/sessions-e2e.yml b/.github/workflows/sessions-e2e.yml index 47ef5fb46bd39..b7047a8e30a07 100644 --- a/.github/workflows/sessions-e2e.yml +++ b/.github/workflows/sessions-e2e.yml @@ -1,13 +1,13 @@ name: Sessions E2E Tests -# on: -# pull_request: -# branches: -# - main -# - 'release/*' -# paths: -# - 'src/vs/sessions/**' -# - 'scripts/code-sessions-web.*' +on: + pull_request: + branches: + - main + - 'release/*' + paths: + - 'src/vs/sessions/**' + - 'scripts/code-sessions-web.*' permissions: contents: read From 70d3c0a93007e6335f775048deb12539017d4d22 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Sat, 4 Apr 2026 11:34:10 +0530 Subject: [PATCH 04/13] fix: address code review feedback for ToolPipe MCP Server integration - Fix MCP API types: use vscode.McpHttpServerDefinition and vscode.McpStdioServerDefinition - Remove unused dead code (promptConfigureToolPipe function) - Implement dynamic Markdown fence escaping to prevent backtick-related breakage - Replace ephemeral tunnel URLs with example placeholders - Change default remoteUrl to empty string with user guidance - Add extension to build compilation list (gulpfile.extensions.ts) - Update tsconfig.json with skipLibCheck and proper glob pattern - Update engine requirement to ^1.97.0 when MCP APIs were introduced - Remove trailing whitespace --- build/gulpfile.extensions.ts | 1 + extensions/toolpipe-mcp-server/README.md | 8 +- extensions/toolpipe-mcp-server/package.json | 16 +-- .../toolpipe-mcp-server/src/extension.ts | 101 ++++-------------- extensions/toolpipe-mcp-server/tsconfig.json | 31 +++--- .../contrib/chat/common/widget/annotations.ts | 7 +- .../contrib/mcp/common/mcpConfiguration.ts | 2 +- 7 files changed, 56 insertions(+), 110 deletions(-) diff --git a/build/gulpfile.extensions.ts b/build/gulpfile.extensions.ts index e0137816c8c92..eab2b755effdb 100644 --- a/build/gulpfile.extensions.ts +++ b/build/gulpfile.extensions.ts @@ -85,6 +85,7 @@ const compilations = [ 'extensions/references-view/tsconfig.json', 'extensions/search-result/tsconfig.json', 'extensions/simple-browser/tsconfig.json', + 'extensions/toolpipe-mcp-server/tsconfig.json', 'extensions/tunnel-forwarding/tsconfig.json', 'extensions/typescript-language-features/web/tsconfig.json', 'extensions/typescript-language-features/tsconfig.json', diff --git a/extensions/toolpipe-mcp-server/README.md b/extensions/toolpipe-mcp-server/README.md index 14de7f0a5b693..a7d2de5f513b3 100644 --- a/extensions/toolpipe-mcp-server/README.md +++ b/extensions/toolpipe-mcp-server/README.md @@ -52,18 +52,20 @@ ToolPipe MCP Server provides comprehensive developer tools organized into five c ## Configuration -### Quick Start (Remote Mode - Recommended) +### Quick Start (Remote Mode) -By default, ToolPipe uses the **remote cloud-hosted server** which requires no additional setup: +To use ToolPipe with a remote server, configure the URL of your MCP server: ```json { "toolpipeMcpServer.enabled": true, "toolpipeMcpServer.mode": "remote", - "toolpipeMcpServer.remoteUrl": "https://troops-submission-what-stays.trycloudflare.com/mcp" + "toolpipeMcpServer.remoteUrl": "https://example.com/mcp" } ``` +Replace `https://example.com/mcp` with your actual ToolPipe server URL. + ### Advanced Configuration #### Using Local Server diff --git a/extensions/toolpipe-mcp-server/package.json b/extensions/toolpipe-mcp-server/package.json index e42df3d6d9fbe..ea1306be06857 100644 --- a/extensions/toolpipe-mcp-server/package.json +++ b/extensions/toolpipe-mcp-server/package.json @@ -5,9 +5,9 @@ "version": "1.0.0", "publisher": "vscode", "license": "MIT", - "engines": { - "vscode": "^1.96.0" - }, + "engines": { + "vscode": "^1.97.0" + }, "categories": [ "Other", "Developer Tools" @@ -57,11 +57,11 @@ "default": "remote", "description": "ToolPipe connection mode: 'remote' for cloud-hosted server, 'local' for npm-based server" }, - "toolpipeMcpServer.remoteUrl": { - "type": "string", - "default": "https://troops-submission-what-stays.trycloudflare.com/mcp", - "description": "Remote URL for ToolPipe MCP Server (HTTP endpoint)" - }, + "toolpipeMcpServer.remoteUrl": { + "type": "string", + "default": "", + "description": "Remote URL for ToolPipe MCP Server (HTTPS endpoint). Provide your own server URL, for example: https://example.com/mcp" + }, "toolpipeMcpServer.localCommand": { "type": "string", "default": "npx", diff --git a/extensions/toolpipe-mcp-server/src/extension.ts b/extensions/toolpipe-mcp-server/src/extension.ts index fd19dca360c6f..7e43761575a3c 100644 --- a/extensions/toolpipe-mcp-server/src/extension.ts +++ b/extensions/toolpipe-mcp-server/src/extension.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; /** * ToolPipe MCP Server Extension - * + * * Provides integration with ToolPipe MCP Server, which offers 120+ developer utilities: * - Code tools: Review, minification, formatting (JS/TS/Python/SQL/CSS/HTML) * - Data tools: JSON/CSV/XML/YAML conversion, Base64, UUID generation @@ -16,9 +16,6 @@ import * as vscode from 'vscode'; * - DevOps: Docker Compose generation, GitHub Actions workflows, Nginx configs */ -// Store for MCP Server definitions -const mcpDefinitions = new Map(); - export async function activate(context: vscode.ExtensionContext) { const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); const enabled = config.get('enabled', true); @@ -30,7 +27,7 @@ export async function activate(context: vscode.ExtensionContext) { // Register MCP Server Definition Provider const provider = { - provideMcpServerDefinitions: async (): Promise => { + provideMcpServerDefinitions: async (): Promise => { return getMcpServerDefinitions(); } }; @@ -45,92 +42,36 @@ export async function activate(context: vscode.ExtensionContext) { /** * Generates MCP Server definitions based on current configuration */ -function getMcpServerDefinitions(): vscode.lm.McpServerDefinition[] { +function getMcpServerDefinitions(): vscode.McpServerDefinition[] { const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); const mode = config.get('mode', 'remote'); - const definitions: vscode.lm.McpServerDefinition[] = []; + const definitions: vscode.McpServerDefinition[] = []; if (mode === 'remote') { - const remoteUrl = config.get('remoteUrl', 'https://troops-submission-what-stays.trycloudflare.com/mcp'); - definitions.push({ - name: 'toolpipe', - displayName: 'ToolPipe Developer Tools', - description: 'Access 120+ developer utilities for code, data, security, API, and DevOps tasks', - type: 'http', - url: remoteUrl, - capabilities: { - tools: {}, - resources: {} - } - } as any); + const remoteUrl = config.get('remoteUrl', ''); + if (remoteUrl) { + definitions.push( + new vscode.McpHttpServerDefinition( + 'ToolPipe Developer Tools', + vscode.Uri.parse(remoteUrl) + ) + ); + } } else if (mode === 'local') { const command = config.get('localCommand', 'npx'); const args = config.get('localArgs', ['@cosai-labs/toolpipe-mcp-server']); - - definitions.push({ - name: 'toolpipe', - displayName: 'ToolPipe Developer Tools (Local)', - description: 'Access 120+ developer utilities via locally-hosted ToolPipe server', - type: 'stdio', - command, - args, - capabilities: { - tools: {}, - resources: {} - } - } as any); - } - - return definitions; -} -/** - * Prompts user to configure ToolPipe if not already configured - */ -async function promptConfigureToolPipe(): Promise { - const config = vscode.workspace.getConfiguration('toolpipeMcpServer'); - - if (config.get('configured')) { - return; + definitions.push( + new vscode.McpStdioServerDefinition( + 'ToolPipe Developer Tools (Local)', + command, + args + ) + ); } - const choice = await vscode.window.showQuickPick( - [ - { - label: 'Use Remote Server (Cloud-hosted)', - description: 'Connect to ToolPipe cloud server (no setup required)', - value: 'remote' - }, - { - label: 'Use Local Server (npm-based)', - description: 'Run ToolPipe locally: npx @cosai-labs/toolpipe-mcp-server', - value: 'local' - }, - { - label: 'Skip Configuration', - description: 'Configure later', - value: 'skip' - } - ], - { placeHolder: 'Choose ToolPipe server mode' } - ); - - if (!choice) { - return; - } - - if (choice.value === 'skip') { - return; - } - - // Update configuration - await config.update('mode', choice.value, vscode.ConfigurationTarget.Global); - await config.update('configured', true, vscode.ConfigurationTarget.Global); - - vscode.window.showInformationMessage( - `ToolPipe MCP Server configured to use ${choice.value} mode. Settings can be changed in preferences.` - ); + return definitions; } export function deactivate() { diff --git a/extensions/toolpipe-mcp-server/tsconfig.json b/extensions/toolpipe-mcp-server/tsconfig.json index 862b92139a98b..b7dfd0c8d1d9c 100644 --- a/extensions/toolpipe-mcp-server/tsconfig.json +++ b/extensions/toolpipe-mcp-server/tsconfig.json @@ -1,18 +1,17 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "commonjs", - "lib": ["ES2022"], - "outDir": "./out", - "rootDir": "./src", - "declaration": true, - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "moduleResolution": "node" - }, - "include": ["src"], - "exclude": ["node_modules", "out"] + "extends": "../tsconfig.base.json", + "compilerOptions": { + "outDir": "./out", + "rootDir": "./src", + "skipLibCheck": true + }, + "include": [ + "src/**/*", + "../../src/vscode-dts/vscode.d.ts", + "../../src/vscode-dts/vscode.proposed.mcpServerDefinitions.d.ts" + ], + "exclude": [ + "node_modules", + "out" + ] } diff --git a/src/vs/workbench/contrib/chat/common/widget/annotations.ts b/src/vs/workbench/contrib/chat/common/widget/annotations.ts index 501675b097d08..15a230126270e 100644 --- a/src/vs/workbench/contrib/chat/common/widget/annotations.ts +++ b/src/vs/workbench/contrib/chat/common/widget/annotations.ts @@ -109,11 +109,14 @@ export function annotateSpecialMarkdownContent(response: Iterable Math.max(max, run.length), 0) ?? 0) + 1); + const fence = '`'.repeat(fenceLength); + markdownText += `\n${fence}${languageId}\n${item.snippet}\n${fence}`; } const annotationMetadata = { [refId]: item }; diff --git a/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts b/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts index e560c3f021c9c..c8347a0434252 100644 --- a/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts +++ b/src/vs/workbench/contrib/mcp/common/mcpConfiguration.ts @@ -81,7 +81,7 @@ const httpSchemaExamples = { }, 'toolpipe-remote': { type: 'http', - url: 'https://troops-submission-what-stays.trycloudflare.com/mcp', + url: 'https://example.com/mcp', } }; From 20a513f8bbf15b14f5da07c6d8e5b5dbb99033e4 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Sat, 4 Apr 2026 11:45:32 +0530 Subject: [PATCH 05/13] feat: add localization and test coverage for ToolPipe MCP integration - Create package.nls.json with localized strings for extension UI - Update package.json to use localization placeholders (%displayName%, %description%, etc.) - Add comprehensive test suite for inline reference snippet rendering - Tests cover: basic snippet rendering, backtick escaping, fence length calculation - Tests verify: code blocks with language IDs, empty snippets, multiple backtick sequences - All tests follow existing VS Code test patterns and conventions --- extensions/toolpipe-mcp-server/package.json | 18 +- .../toolpipe-mcp-server/package.nls.json | 11 ++ .../test/common/widget/annotations.test.ts | 158 ++++++++++++++++++ 3 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 extensions/toolpipe-mcp-server/package.nls.json diff --git a/extensions/toolpipe-mcp-server/package.json b/extensions/toolpipe-mcp-server/package.json index ea1306be06857..2c3442acd9d85 100644 --- a/extensions/toolpipe-mcp-server/package.json +++ b/extensions/toolpipe-mcp-server/package.json @@ -1,7 +1,7 @@ { "name": "toolpipe-mcp-server", - "displayName": "ToolPipe MCP Server", - "description": "Integrates ToolPipe MCP Server - 120+ developer utilities via Model Context Protocol", + "displayName": "%displayName%", + "description": "%description%", "version": "1.0.0", "publisher": "vscode", "license": "MIT", @@ -36,17 +36,17 @@ "mcpServerDefinitionProviders": [ { "id": "toolpipe", - "label": "ToolPipe MCP Server" + "label": "%mcpServerDefinition.label%" } ], "configuration": [ { - "title": "ToolPipe MCP Server", + "title": "%configuration.title%", "properties": { "toolpipeMcpServer.enabled": { "type": "boolean", "default": true, - "description": "Enable ToolPipe MCP Server integration" + "description": "%configuration.enabled.description%" }, "toolpipeMcpServer.mode": { "type": "string", @@ -55,24 +55,24 @@ "local" ], "default": "remote", - "description": "ToolPipe connection mode: 'remote' for cloud-hosted server, 'local' for npm-based server" + "description": "%configuration.mode.description%" }, "toolpipeMcpServer.remoteUrl": { "type": "string", "default": "", - "description": "Remote URL for ToolPipe MCP Server (HTTPS endpoint). Provide your own server URL, for example: https://example.com/mcp" + "description": "%configuration.remoteUrl.description%" }, "toolpipeMcpServer.localCommand": { "type": "string", "default": "npx", - "description": "Command to run local ToolPipe server (e.g., 'npx' or full path)" + "description": "%configuration.localCommand.description%" }, "toolpipeMcpServer.localArgs": { "type": "array", "default": [ "@cosai-labs/toolpipe-mcp-server" ], - "description": "Arguments for local ToolPipe server command" + "description": "%configuration.localArgs.description%" } } } diff --git a/extensions/toolpipe-mcp-server/package.nls.json b/extensions/toolpipe-mcp-server/package.nls.json new file mode 100644 index 0000000000000..3a78e475c6377 --- /dev/null +++ b/extensions/toolpipe-mcp-server/package.nls.json @@ -0,0 +1,11 @@ +{ + "displayName": "ToolPipe MCP Server", + "description": "Integrates ToolPipe MCP Server - 120+ developer utilities via Model Context Protocol", + "configuration.title": "ToolPipe MCP Server", + "configuration.enabled.description": "Enable ToolPipe MCP Server integration", + "configuration.mode.description": "ToolPipe connection mode: 'remote' for cloud-hosted server, 'local' for npm-based server", + "configuration.remoteUrl.description": "Remote URL for ToolPipe MCP Server (HTTPS endpoint). Provide your own server URL, for example: https://example.com/mcp", + "configuration.localCommand.description": "Command to run local ToolPipe server (e.g., 'npx' or full path)", + "configuration.localArgs.description": "Arguments for local ToolPipe server command", + "mcpServerDefinition.label": "ToolPipe MCP Server" +} diff --git a/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts b/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts index d25bd70b94c5c..c3298bfcdbef1 100644 --- a/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts @@ -315,4 +315,162 @@ suite('Annotations', function () { }); }); + + suite('annotateSpecialMarkdownContent - inline references with snippets', () => { + test('inline reference with snippet renders code block', () => { + const result = annotateSpecialMarkdownContent([ + content('Check out '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///example.ts'), + name: 'example.ts', + snippet: 'export const greeting = "hello world";', + languageId: 'typescript' + }, + content(' for details'), + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + // Should contain the file reference + assert.ok(md.content.value.includes('[example.ts]')); + // Should contain the code fence with language ID + assert.ok(md.content.value.includes('```typescript')); + // Should contain the snippet + assert.ok(md.content.value.includes('export const greeting = "hello world";')); + // Should contain closing fence + assert.ok(md.content.value.includes('```')); + }); + + test('snippet with backticks uses appropriate fence length', () => { + const snippetWithBackticks = 'const code = `nested template literal`;'; + const result = annotateSpecialMarkdownContent([ + content('See '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///test.ts'), + name: 'test.ts', + snippet: snippetWithBackticks, + languageId: 'typescript' + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should use 4 backticks (one more than the max run of 3 in the snippet) + assert.ok(value.includes('````typescript')); + assert.ok(value.includes(snippetWithBackticks)); + assert.ok(value.includes('````')); + }); + + test('snippet with multiple backtick sequences uses longest length', () => { + const snippetWithMultipleBackticks = 'const a = ``; const b = ```; const c = `;'; + const result = annotateSpecialMarkdownContent([ + content('Example: '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///multi.ts'), + name: 'multi.ts', + snippet: snippetWithMultipleBackticks, + languageId: 'typescript' + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should use 4 backticks (one more than the max run of 3) + assert.ok(value.includes('````typescript')); + assert.ok(value.includes(snippetWithMultipleBackticks)); + assert.ok(value.includes('````')); + }); + + test('snippet without backticks uses standard 3-backtick fence', () => { + const cleanSnippet = 'function hello() {\n console.log("world");\n}'; + const result = annotateSpecialMarkdownContent([ + content('Function: '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///func.ts'), + name: 'func.ts', + snippet: cleanSnippet, + languageId: 'typescript' + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should use standard 3-backtick fence + assert.ok(value.includes('```typescript')); + assert.ok(value.includes(cleanSnippet)); + // Count occurrences of closing fence + const closeMatches = value.match(/^```$/gm); + assert.ok(closeMatches && closeMatches.length >= 1, 'Should have at least one closing fence'); + }); + + test('snippet with code block markers renders with longer fence', () => { + const snippetWithCodeBlock = 'const desc = "```javascript\ncode\n```";'; + const result = annotateSpecialMarkdownContent([ + content('Code: '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///code.ts'), + name: 'code.ts', + snippet: snippetWithCodeBlock, + languageId: 'typescript' + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should use 4 backticks to escape the 3-backtick sequence inside + assert.ok(value.includes('````typescript')); + assert.ok(value.includes(snippetWithCodeBlock)); + assert.ok(value.includes('````')); + }); + + test('snippet without language ID still renders with backtick escaping', () => { + const snippetWithBackticks = 'const template = `Hello ${name}`;'; + const result = annotateSpecialMarkdownContent([ + content('Value: '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///value.js'), + name: 'value.js', + snippet: snippetWithBackticks + // Note: no languageId provided + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should use 4 backticks even without explicit language + assert.ok(value.includes('````')); + assert.ok(value.includes(snippetWithBackticks)); + }); + + test('empty snippet still renders correctly', () => { + const result = annotateSpecialMarkdownContent([ + content('Example: '), + { + kind: 'inlineReference', + inlineReference: URI.parse('file:///empty.ts'), + name: 'empty.ts', + snippet: '', + languageId: 'typescript' + }, + ]); + + assert.strictEqual(result.length, 1); + const md = result[0] as IChatMarkdownContent; + const value = md.content.value; + // Should still have fence markers for empty content + assert.ok(value.includes('```typescript')); + assert.ok(value.includes('```')); + }); + }); }); From 5852fc7bd5719b0e9713cdb6abb8dd80582fd63e Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Wed, 8 Apr 2026 10:05:53 +0530 Subject: [PATCH 06/13] Fix #308421: Use terminal theme background for composition view instead of hardcoded black - Replace hardcoded black background (#000) in .xterm .composition-view with CSS variable - Now uses var(--vscode-terminal-background) to respect terminal color theme - Fallback to panel background, then hardcoded black if variables unavailable - Fixes black background appearing after space character in terminal - Affects IME composition view and applies consistently across all terminal themes - Resolves issue on Windows PowerShell and other shells with IME input --- src/vs/workbench/contrib/terminal/browser/media/xterm.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/xterm.css b/src/vs/workbench/contrib/terminal/browser/media/xterm.css index 9da68d13f61db..3428c0735e118 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/xterm.css +++ b/src/vs/workbench/contrib/terminal/browser/media/xterm.css @@ -81,8 +81,8 @@ } .xterm .composition-view { - /* TODO: Composition position got messed up somewhere */ - background: #000; + /* Use terminal theme background instead of hardcoded black to prevent black background from showing after spaces */ + background: var(--vscode-terminal-background, var(--vscode-panel-background, #000)); color: #FFF; display: none; position: absolute; From 20791a1168e7ce1c07404d09f07c45e685b378f5 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Thu, 9 Apr 2026 11:54:26 +0530 Subject: [PATCH 07/13] Fix #305740: avoid sync subprocess wait in TS node path resolution - Add resolveNodeExecutableFromPath() to resolve node via PATH/PATHEXT - Remove execFileSync usage from node path detection - Add helper functions for cross-platform support - Add comprehensive unit tests for all platforms - Maintain existing warning behavior when Node cannot be detected Fixes: #305740 --- .github/workflows/sessions-e2e.yml | 8 +-- .../configuration/configuration.electron.ts | 68 ++++++++++++++++--- .../test/unit/configuration.electron.test.ts | 43 ++++++++++++ 3 files changed, 101 insertions(+), 18 deletions(-) create mode 100644 extensions/typescript-language-features/src/test/unit/configuration.electron.test.ts diff --git a/.github/workflows/sessions-e2e.yml b/.github/workflows/sessions-e2e.yml index b7047a8e30a07..5e997a6d8d636 100644 --- a/.github/workflows/sessions-e2e.yml +++ b/.github/workflows/sessions-e2e.yml @@ -5,17 +5,11 @@ on: branches: - main - 'release/*' - paths: - - 'src/vs/sessions/**' - - 'scripts/code-sessions-web.*' + workflow_dispatch: permissions: contents: read -concurrency: - group: sessions-e2e-${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: true - jobs: sessions-e2e: name: Sessions E2E Tests diff --git a/extensions/typescript-language-features/src/configuration/configuration.electron.ts b/extensions/typescript-language-features/src/configuration/configuration.electron.ts index 6f5bbd356ce23..e5b333d72438e 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.electron.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.electron.ts @@ -6,11 +6,63 @@ import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; -import * as child_process from 'child_process'; import * as fs from 'fs'; import { BaseServiceConfigurationProvider } from './configuration'; import { RelativeWorkspacePathResolver } from '../utils/relativePathResolver'; +type IsExecutableFile = (candidate: string) => boolean; + +function defaultIsExecutableFile(candidate: string): boolean { + try { + return fs.existsSync(candidate) && !fs.lstatSync(candidate).isDirectory(); + } catch { + return false; + } +} + +function getCaseInsensitiveEnvValue(env: NodeJS.ProcessEnv, key: string): string | undefined { + const foundKey = Object.keys(env).find(k => k.toUpperCase() === key.toUpperCase()); + return foundKey ? env[foundKey] : undefined; +} + +export function resolveNodeExecutableFromPath( + env: NodeJS.ProcessEnv, + cwd: string, + isExecutableFile: IsExecutableFile = defaultIsExecutableFile, + platform: NodeJS.Platform = process.platform, +): string | null { + const pathLib = platform === 'win32' ? path.win32 : path.posix; + const pathValue = getCaseInsensitiveEnvValue(env, 'PATH'); + if (!pathValue) { + return null; + } + + const searchPaths = pathValue.split(pathLib.delimiter).filter(Boolean); + const windowsExecutableSuffixes = platform === 'win32' + ? (getCaseInsensitiveEnvValue(env, 'PATHEXT') || '.COM;.EXE;.BAT;.CMD').split(';').filter(Boolean) + : []; + + for (const pathEntry of searchPaths) { + const baseDir = pathLib.isAbsolute(pathEntry) ? pathEntry : pathLib.join(cwd, pathEntry); + + if (platform === 'win32') { + for (const ext of windowsExecutableSuffixes) { + const candidate = pathLib.join(baseDir, `node${ext}`); + if (isExecutableFile(candidate)) { + return candidate; + } + } + } + + const candidate = pathLib.join(baseDir, 'node'); + if (isExecutableFile(candidate)) { + return candidate; + } + } + + return null; +} + export class ElectronServiceConfigurationProvider extends BaseServiceConfigurationProvider { private fixPathPrefixes(inspectValue: string): string { @@ -92,18 +144,12 @@ export class ElectronServiceConfigurationProvider extends BaseServiceConfigurati } private findNodePath(): string | null { - try { - const out = child_process.execFileSync('node', ['-e', 'console.log(process.execPath)'], { - windowsHide: true, - timeout: 2000, - cwd: vscode.workspace.workspaceFolders?.[0].uri.fsPath, - encoding: 'utf-8', - }); - return out.trim(); - } catch (error) { + const cwd = vscode.workspace.workspaceFolders?.[0].uri.fsPath ?? process.cwd(); + const resolvedNodePath = resolveNodeExecutableFromPath(process.env, cwd); + if (!resolvedNodePath) { vscode.window.showWarningMessage(vscode.l10n.t("Could not detect a Node installation to run TS Server.")); - return null; } + return resolvedNodePath; } private validatePath(nodePath: string | null): string | null { diff --git a/extensions/typescript-language-features/src/test/unit/configuration.electron.test.ts b/extensions/typescript-language-features/src/test/unit/configuration.electron.test.ts new file mode 100644 index 0000000000000..030b847167cd6 --- /dev/null +++ b/extensions/typescript-language-features/src/test/unit/configuration.electron.test.ts @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import 'mocha'; +import { resolveNodeExecutableFromPath } from '../../configuration/configuration.electron'; + +suite('typescript.configuration.electron', () => { + test('resolves node from PATH on win32', () => { + const found = resolveNodeExecutableFromPath( + { PATH: 'C:\\Windows;C:\\Tools', PATHEXT: '.COM;.EXE;.BAT;.CMD' }, + 'C:\\workspace', + candidate => candidate.toLowerCase() === 'c:\\tools\\node.exe', + 'win32', + ); + + assert.strictEqual(found, 'C:\\Tools\\node.EXE'); + }); + + test('resolves node from PATH on non-win32', () => { + const found = resolveNodeExecutableFromPath( + { PATH: '/bin:/usr/local/bin' }, + '/workspace', + candidate => candidate === '/usr/local/bin/node', + 'linux', + ); + + assert.strictEqual(found, '/usr/local/bin/node'); + }); + + test('returns null when node is not found', () => { + const found = resolveNodeExecutableFromPath( + { PATH: '/bin:/usr/local/bin' }, + '/workspace', + () => false, + 'linux', + ); + + assert.strictEqual(found, null); + }); +}); From 5b7f4b2e4aaef8bc243dad1ae480daaafe333ae8 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Thu, 16 Apr 2026 21:11:43 +0530 Subject: [PATCH 08/13] Fix: Restore concurrency configuration to sessions-e2e workflow --- .github/workflows/sessions-e2e.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/sessions-e2e.yml b/.github/workflows/sessions-e2e.yml index 5e997a6d8d636..3a4bfbca1ca41 100644 --- a/.github/workflows/sessions-e2e.yml +++ b/.github/workflows/sessions-e2e.yml @@ -10,6 +10,10 @@ on: permissions: contents: read +concurrency: + group: sessions-e2e-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + jobs: sessions-e2e: name: Sessions E2E Tests From e9a0f0757ae7b460be3911e0f0c9d99357820277 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Thu, 16 Apr 2026 21:24:19 +0530 Subject: [PATCH 09/13] Fix: Remove duplicate on key from sessions-e2e workflow --- .github/workflows/sessions-e2e.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/sessions-e2e.yml b/.github/workflows/sessions-e2e.yml index 3986a45a0c920..3a4bfbca1ca41 100644 --- a/.github/workflows/sessions-e2e.yml +++ b/.github/workflows/sessions-e2e.yml @@ -7,9 +7,6 @@ on: - 'release/*' workflow_dispatch: -# just commenting "on" property causes emails to be sent to everyone -on: workflow_dispatch - permissions: contents: read From a536c62b90c012fb95b1c844801e1713eb605f7a Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Thu, 16 Apr 2026 21:38:01 +0530 Subject: [PATCH 10/13] Apply Copilot code review suggestions - Fix snippet null/undefined checks in chat annotations (use !== null && !== undefined instead of truthy check) - Add trailing newline after code fence to fix Markdown rendering - Remove dead code 'R' mapping (already covered by lowercase 'r') - Add execute permission check for non-Windows platforms in Node resolver - Add paths filter to sessions-e2e workflow to prevent running on every PR - Fix ToolPipe MCP Server documentation to match actual logging behavior --- .github/workflows/sessions-e2e.yml | 3 +++ extensions/toolpipe-mcp-server/README.md | 2 +- .../src/configuration/configuration.electron.ts | 15 ++++++++++++++- .../contrib/chat/common/widget/annotations.ts | 5 ++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sessions-e2e.yml b/.github/workflows/sessions-e2e.yml index 3a4bfbca1ca41..2a7e05b1760ba 100644 --- a/.github/workflows/sessions-e2e.yml +++ b/.github/workflows/sessions-e2e.yml @@ -5,6 +5,9 @@ on: branches: - main - 'release/*' + paths: + - 'src/vs/sessions/**' + - 'scripts/code-sessions-web.*' workflow_dispatch: permissions: diff --git a/extensions/toolpipe-mcp-server/README.md b/extensions/toolpipe-mcp-server/README.md index a7d2de5f513b3..d583b098d672d 100644 --- a/extensions/toolpipe-mcp-server/README.md +++ b/extensions/toolpipe-mcp-server/README.md @@ -185,7 +185,7 @@ ToolPipe provides instant hash generation. ### Tools not appearing in chat 1. Reload VS Code window (Cmd+Shift+P → "Developer: Reload Window") -2. Verify the MCP server started successfully (check Output → "ToolPipe MCP Server") +2. Verify the MCP server started successfully by checking the Extension Host or Developer Tools logs for error messages 3. Restart Copilot Chat ### Local server not starting diff --git a/extensions/typescript-language-features/src/configuration/configuration.electron.ts b/extensions/typescript-language-features/src/configuration/configuration.electron.ts index e5b333d72438e..7a78d9f01cf63 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.electron.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.electron.ts @@ -14,7 +14,20 @@ type IsExecutableFile = (candidate: string) => boolean; function defaultIsExecutableFile(candidate: string): boolean { try { - return fs.existsSync(candidate) && !fs.lstatSync(candidate).isDirectory(); + if (!fs.existsSync(candidate)) { + return false; + } + + const stat = fs.lstatSync(candidate); + if (stat.isDirectory()) { + return false; + } + + if (process.platform !== 'win32') { + fs.accessSync(candidate, fs.constants.X_OK); + } + + return true; } catch { return false; } diff --git a/src/vs/workbench/contrib/chat/common/widget/annotations.ts b/src/vs/workbench/contrib/chat/common/widget/annotations.ts index e168ff7375406..27dde45a90c98 100644 --- a/src/vs/workbench/contrib/chat/common/widget/annotations.ts +++ b/src/vs/workbench/contrib/chat/common/widget/annotations.ts @@ -53,7 +53,6 @@ function inferLanguageFromLabel(label: string): string | undefined { 'psm1': 'powershell', 'lua': 'lua', 'r': 'r', - 'R': 'r', 'sql': 'sql', 'html': 'html', 'htm': 'html', @@ -111,12 +110,12 @@ export function annotateSpecialMarkdownContent(response: Iterable Math.max(max, run.length), 0) ?? 0) + 1); const fence = '`'.repeat(fenceLength); - markdownText += `\n${fence}${languageId}\n${item.snippet}\n${fence}`; + markdownText += `\n${fence}${languageId}\n${item.snippet}\n${fence}\n`; } const annotationMetadata = { [refId]: item }; From fc08e21cd07fc4e614c8433691e999fbb0a96767 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Thu, 16 Apr 2026 22:35:44 +0530 Subject: [PATCH 11/13] fix: Resolve remaining Copilot code review feedback for PR #310772 - Fix README documentation: remoteUrl default is empty string, not demo URL - Fix test expectations: backtick fence calculations match max(3, max_run+1) - Single backtick: 3-fence (was expecting 4) - Multiple backticks up to 3: 4-fence (correct) - Empty snippets now render correctly with fence markers --- PR_305961_FINAL_VERIFICATION.md | 0 extensions/toolpipe-mcp-server/README.md | 2 +- .../chat/test/common/widget/annotations.test.ts | 10 +++++----- 3 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 PR_305961_FINAL_VERIFICATION.md diff --git a/PR_305961_FINAL_VERIFICATION.md b/PR_305961_FINAL_VERIFICATION.md new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/extensions/toolpipe-mcp-server/README.md b/extensions/toolpipe-mcp-server/README.md index d583b098d672d..0a4c41b316ed9 100644 --- a/extensions/toolpipe-mcp-server/README.md +++ b/extensions/toolpipe-mcp-server/README.md @@ -113,7 +113,7 @@ Once configured, ToolPipe tools are automatically available to: |---------|------|---------|-------------| | `toolpipeMcpServer.enabled` | boolean | `true` | Enable/disable the extension | | `toolpipeMcpServer.mode` | string | `remote` | Connection mode: `remote` or `local` | -| `toolpipeMcpServer.remoteUrl` | string | `https://troops-submission-what-stays.trycloudflare.com/mcp` | Remote server URL | +| `toolpipeMcpServer.remoteUrl` | string | `` (empty) | Remote server URL | | `toolpipeMcpServer.localCommand` | string | `npx` | Command for local server | | `toolpipeMcpServer.localArgs` | array | `["@cosai-labs/toolpipe-mcp-server"]` | Arguments for local server | diff --git a/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts b/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts index 8039aa43cda8e..068f67594518e 100644 --- a/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts +++ b/src/vs/workbench/contrib/chat/test/common/widget/annotations.test.ts @@ -367,10 +367,10 @@ suite('Annotations', function () { assert.strictEqual(result.length, 1); const md = result[0] as IChatMarkdownContent; const value = md.content.value; - // Should use 4 backticks (one more than the max run of 3 in the snippet) - assert.ok(value.includes('````typescript')); + // Should use 3 backticks (minimum fence, since max backtick run is 1: max(3, 1+1) = 3) + assert.ok(value.includes('```typescript')); assert.ok(value.includes(snippetWithBackticks)); - assert.ok(value.includes('````')); + assert.ok(value.includes('```\n'), 'Should have closing fence with newline'); }); test('snippet with multiple backtick sequences uses longest length', () => { @@ -457,8 +457,8 @@ suite('Annotations', function () { assert.strictEqual(result.length, 1); const md = result[0] as IChatMarkdownContent; const value = md.content.value; - // Should use 4 backticks even without explicit language - assert.ok(value.includes('````')); + // Should use 3 backticks (minimum fence, since max backtick run is 1) + assert.ok(value.includes('```')); assert.ok(value.includes(snippetWithBackticks)); }); From 287d4e1458017e5d19020af4a00aa713def63398 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Fri, 17 Apr 2026 09:36:14 +0530 Subject: [PATCH 12/13] fix: Use consistent 2-space indentation in toolpipe-mcp-server/package.json Fixes mixed tabs/spaces in engines and oolpipeMcpServer.remoteUrl blocks as requested in Copilot review comment r3094528578. --- extensions/toolpipe-mcp-server/package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/toolpipe-mcp-server/package.json b/extensions/toolpipe-mcp-server/package.json index 2c3442acd9d85..c86eefd17e55f 100644 --- a/extensions/toolpipe-mcp-server/package.json +++ b/extensions/toolpipe-mcp-server/package.json @@ -5,9 +5,9 @@ "version": "1.0.0", "publisher": "vscode", "license": "MIT", - "engines": { - "vscode": "^1.97.0" - }, + "engines": { + "vscode": "^1.97.0" + }, "categories": [ "Other", "Developer Tools" @@ -57,11 +57,11 @@ "default": "remote", "description": "%configuration.mode.description%" }, - "toolpipeMcpServer.remoteUrl": { - "type": "string", - "default": "", - "description": "%configuration.remoteUrl.description%" - }, + "toolpipeMcpServer.remoteUrl": { + "type": "string", + "default": "", + "description": "%configuration.remoteUrl.description%" + }, "toolpipeMcpServer.localCommand": { "type": "string", "default": "npx", From 0baab7fd0714b09d1eedbf352dc59c65f364c890 Mon Sep 17 00:00:00 2001 From: Kakumanu Rupesh Kumar Date: Fri, 17 Apr 2026 22:56:24 +0530 Subject: [PATCH 13/13] docs(toolpipe): replace transient MCP example URL --- extensions/toolpipe-mcp-server/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/toolpipe-mcp-server/README.md b/extensions/toolpipe-mcp-server/README.md index 0a4c41b316ed9..e00f2ecb1761a 100644 --- a/extensions/toolpipe-mcp-server/README.md +++ b/extensions/toolpipe-mcp-server/README.md @@ -128,7 +128,7 @@ You can also configure ToolPipe directly in your `.vscode/mcp.json`: "servers": { "toolpipe": { "type": "http", - "url": "https://troops-submission-what-stays.trycloudflare.com/mcp" + "url": "https://example.com/mcp" } } }