Implement VS Code Tool Integration

Phase 1: Core VS Code Tool Provider
- Created VSCodeToolProvider with 12 core tools (file ops, editor ops, commands)
- Implemented VSCodePermissions with 6 permission levels and security controls
- Integrated VS Code tools into UnifiedMCPServer tool discovery and routing
- Added comprehensive documentation in VSCODE_TOOL_INTEGRATION.md

Tools implemented:
- File Operations: read_file, write_file, create_file, delete_file, list_directory
- Editor Operations: get/set editor content, get/set selection, get active editor
- Commands: run_command (with whitelist), show_message
- Workspace: get_workspace_folders

Security features:
- Permission levels: read_only, editor, filesystem, terminal, git, admin
- Path sandboxing to prevent access outside workspace
- Command whitelisting for safe operations
- Audit logging for all VS Code tool operations

Next: Implement actual VS Code Extension API bridge and language services
This commit is contained in:
Ra
2025-08-23 14:53:03 -07:00
parent 943d8ad4d7
commit 5da801c2ca
4 changed files with 945 additions and 4 deletions

258
VSCODE_TOOL_INTEGRATION.md Normal file
View File

@@ -0,0 +1,258 @@
# VS Code Tool Integration with Agent Coordinator
## Overview
This document outlines the implementation of VS Code's built-in tools as MCP (Model Context Protocol) tools within the Agent Coordinator system. This integration allows agents to access VS Code's native capabilities alongside external MCP servers through a unified coordination interface.
## Architecture
### Current State
- Agent Coordinator acts as a unified MCP server
- Proxies tools from external MCP servers (Context7, filesystem, memory, sequential thinking, etc.)
- Manages task coordination, agent assignment, and cross-codebase workflows
### Proposed Enhancement
- Add VS Code Extension API tools as native MCP tools
- Integrate with existing tool routing and coordination system
- Maintain security and permission controls
## Implementation Plan
### Phase 1: Core VS Code Tool Provider
#### 1.1 Create VSCodeToolProvider Module
**File**: `lib/agent_coordinator/vscode_tool_provider.ex`
**Core Tools to Implement**:
- `vscode_read_file` - Read file contents using VS Code API
- `vscode_write_file` - Write file contents
- `vscode_create_file` - Create new files
- `vscode_delete_file` - Delete files
- `vscode_list_directory` - List directory contents
- `vscode_get_workspace_folders` - Get workspace information
- `vscode_run_command` - Execute VS Code commands
- `vscode_get_active_editor` - Get current editor state
- `vscode_set_editor_content` - Modify editor content
- `vscode_get_selection` - Get current text selection
- `vscode_set_selection` - Set text selection
- `vscode_show_message` - Display messages to user
#### 1.2 Tool Definitions
Each tool will have:
- MCP-compliant schema definition
- Input validation
- Error handling
- Audit logging
- Permission checking
### Phase 2: Advanced Editor Operations
#### 2.1 Language Services Integration
- `vscode_get_diagnostics` - Get language server diagnostics
- `vscode_format_document` - Format current document
- `vscode_format_selection` - Format selected text
- `vscode_find_references` - Find symbol references
- `vscode_go_to_definition` - Navigate to definition
- `vscode_rename_symbol` - Rename symbols
- `vscode_code_actions` - Get available code actions
#### 2.2 Search and Navigation
- `vscode_find_in_files` - Search across workspace
- `vscode_find_symbols` - Find symbols in workspace
- `vscode_goto_line` - Navigate to specific line
- `vscode_reveal_in_explorer` - Show file in explorer
### Phase 3: Terminal and Process Management
#### 3.1 Terminal Operations
- `vscode_create_terminal` - Create new terminal
- `vscode_send_to_terminal` - Send commands to terminal
- `vscode_get_terminal_output` - Get terminal output (if possible)
- `vscode_close_terminal` - Close terminal instances
#### 3.2 Task and Process Management
- `vscode_run_task` - Execute VS Code tasks
- `vscode_get_tasks` - List available tasks
- `vscode_debug_start` - Start debugging session
- `vscode_debug_stop` - Stop debugging
### Phase 4: Git and Version Control
#### 4.1 Git Operations
- `vscode_git_status` - Get git status
- `vscode_git_commit` - Create commits
- `vscode_git_push` - Push changes
- `vscode_git_pull` - Pull changes
- `vscode_git_branch` - Branch operations
- `vscode_git_diff` - Get file differences
### Phase 5: Extension and Settings Management
#### 5.1 Configuration
- `vscode_get_settings` - Get VS Code settings
- `vscode_update_settings` - Update settings
- `vscode_get_extensions` - List installed extensions
- `vscode_install_extension` - Install extensions (if permitted)
## Security and Safety
### Permission Model
```elixir
defmodule AgentCoordinator.VSCodePermissions do
@moduledoc """
Manages permissions for VS Code tool access.
"""
# Permission levels:
# :read_only - File reading, workspace inspection
# :editor - Text editing, selections
# :filesystem - File creation/deletion
# :terminal - Terminal access
# :git - Version control operations
# :admin - Settings, extensions, system commands
end
```
### Sandboxing
- Restrict file operations to workspace folders only
- Prevent access to system files outside workspace
- Rate limiting for expensive operations
- Command whitelist for `vscode_run_command`
### Audit Logging
- Log all VS Code tool calls with:
- Timestamp
- Agent ID
- Tool name and parameters
- Result summary
- Permission level used
## Integration Points
### 1. UnifiedMCPServer Enhancement
**File**: `lib/agent_coordinator/unified_mcp_server.ex`
Add VS Code tools to the tool discovery and routing:
```elixir
defp get_all_tools(state) do
# Existing external MCP server tools
external_tools = get_external_tools(state)
# New VS Code tools
vscode_tools = VSCodeToolProvider.get_tools()
external_tools ++ vscode_tools
end
defp route_tool_call(tool_name, args, context, state) do
case tool_name do
"vscode_" <> _rest ->
VSCodeToolProvider.handle_tool_call(tool_name, args, context)
_ ->
# Route to external MCP servers
route_to_external_server(tool_name, args, context, state)
end
end
```
### 2. Task Coordination
VS Code tools will participate in the same task coordination system:
- Task creation and assignment
- File locking (prevent conflicts)
- Cross-agent coordination
- Priority management
### 3. Agent Capabilities
Agents can declare VS Code tool capabilities:
```elixir
capabilities: [
"coding",
"analysis",
"vscode_editing",
"vscode_terminal",
"vscode_git"
]
```
## Usage Examples
### Example 1: File Analysis and Editing
```json
{
"tool": "vscode_read_file",
"args": {"path": "src/main.rs"}
}
// Agent reads file, analyzes it
{
"tool": "vscode_get_diagnostics",
"args": {"file": "src/main.rs"}
}
// Agent gets compiler errors
{
"tool": "vscode_set_editor_content",
"args": {
"file": "src/main.rs",
"content": "// Fixed code here",
"range": {"start": 10, "end": 15}
}
}
// Agent fixes the issues
```
### Example 2: Cross-Tool Workflow
```json
// 1. Agent searches documentation using Context7
{"tool": "mcp_context7_get-library-docs", "args": {"libraryID": "/rust/std"}}
// 2. Agent analyzes current code using VS Code
{"tool": "vscode_get_active_editor", "args": {}}
// 3. Agent applies documentation insights to code
{"tool": "vscode_format_document", "args": {}}
{"tool": "vscode_set_editor_content", "args": {...}}
// 4. Agent commits changes using VS Code Git
{"tool": "vscode_git_commit", "args": {"message": "Applied best practices from docs"}}
```
## Benefits
1. **Unified Tool Access**: Agents access both external services and VS Code features through same interface
2. **Enhanced Capabilities**: Complex workflows combining external data with direct IDE manipulation
3. **Consistent Coordination**: Same task management for all tool types
4. **Security**: Controlled access to powerful VS Code features
5. **Extensibility**: Easy to add new VS Code capabilities as needs arise
## Implementation Timeline
- **Week 1**: Phase 1 - Core file and editor operations
- **Week 2**: Phase 2 - Language services and navigation
- **Week 3**: Phase 3 - Terminal and task management
- **Week 4**: Phase 4 - Git integration
- **Week 5**: Phase 5 - Settings and extension management
- **Week 6**: Testing, documentation, security review
## Testing Strategy
1. **Unit Tests**: Each VS Code tool function
2. **Integration Tests**: Tool coordination and routing
3. **Security Tests**: Permission enforcement and sandboxing
4. **Performance Tests**: Rate limiting and resource usage
5. **User Acceptance**: Real workflow testing with multiple agents
## Future Enhancements
- **Extension-specific Tools**: Tools for specific VS Code extensions
- **Collaborative Features**: Multi-agent editing coordination
- **AI-Enhanced Operations**: Intelligent code suggestions and fixes
- **Remote Development**: Support for remote VS Code scenarios
- **Custom Tool Creation**: Framework for users to create their own VS Code tools
---
## Notes
This implementation transforms the Agent Coordinator from a simple MCP proxy into a comprehensive development environment orchestrator, enabling sophisticated AI-assisted development workflows.

View File

@@ -622,7 +622,8 @@ defmodule AgentCoordinator.MCPServerManager do
end
defp get_coordinator_tools do
[
# Get Agent Coordinator native tools
coordinator_native_tools = [
%{
"name" => "register_agent",
"description" => "Register a new agent with the coordination system",
@@ -701,14 +702,27 @@ defmodule AgentCoordinator.MCPServerManager do
}
}
]
# Get VS Code tools
vscode_tools = AgentCoordinator.VSCodeToolProvider.get_tools()
# Combine all coordinator tools
coordinator_native_tools ++ vscode_tools
end
defp get_coordinator_tool_names do
~w[register_agent create_task get_next_task complete_task get_task_board heartbeat]
# Agent Coordinator native tools
coordinator_native = ~w[register_agent create_task get_next_task complete_task get_task_board heartbeat]
# VS Code tool names
vscode_tools = AgentCoordinator.VSCodeToolProvider.get_tools()
|> Enum.map(fn tool -> tool["name"] end)
coordinator_native ++ vscode_tools
end
defp handle_coordinator_tool(tool_name, arguments, _agent_context) do
# Route to existing Agent Coordinator functionality
defp handle_coordinator_tool(tool_name, arguments, agent_context) do
# Route to existing Agent Coordinator functionality or VS Code tools
case tool_name do
"register_agent" ->
AgentCoordinator.TaskRegistry.register_agent(
@@ -735,6 +749,10 @@ defmodule AgentCoordinator.MCPServerManager do
"heartbeat" ->
AgentCoordinator.TaskRegistry.heartbeat_agent(arguments["agent_id"])
# VS Code tools - route to VS Code Tool Provider
"vscode_" <> _rest ->
AgentCoordinator.VSCodeToolProvider.handle_tool_call(tool_name, arguments, agent_context)
_ ->
%{"error" => %{"code" => -32601, "message" => "Unknown coordinator tool: #{tool_name}"}}
end

View File

@@ -0,0 +1,222 @@
defmodule AgentCoordinator.VSCodePermissions do
@moduledoc """
Manages permissions for VS Code tool access.
Provides fine-grained permission control for agents accessing VS Code tools,
ensuring security and preventing unauthorized operations.
"""
require Logger
@permission_levels %{
read_only: 1,
editor: 2,
filesystem: 3,
terminal: 4,
git: 5,
admin: 6
}
@tool_permissions %{
# File Operations (filesystem level)
"vscode_read_file" => :read_only,
"vscode_write_file" => :filesystem,
"vscode_create_file" => :filesystem,
"vscode_delete_file" => :filesystem,
"vscode_list_directory" => :read_only,
"vscode_get_workspace_folders" => :read_only,
# Editor Operations
"vscode_get_active_editor" => :read_only,
"vscode_set_editor_content" => :editor,
"vscode_get_selection" => :read_only,
"vscode_set_selection" => :editor,
# Command Operations (varies by command)
"vscode_run_command" => :admin, # Default to admin, will check specific commands
# User Communication
"vscode_show_message" => :read_only
}
@whitelisted_commands [
# Safe editor commands
"editor.action.formatDocument",
"editor.action.formatSelection",
"editor.action.organizeImports",
"editor.fold",
"editor.unfold",
"editor.toggleFold",
# Safe navigation commands
"workbench.action.navigateBack",
"workbench.action.navigateForward",
"workbench.action.gotoLine",
"workbench.action.quickOpen",
"workbench.action.showCommands",
# Safe file operations
"workbench.action.files.save",
"workbench.action.files.saveAll",
"workbench.explorer.refreshExplorer",
# Language service operations
"editor.action.goToDeclaration",
"editor.action.goToDefinition",
"editor.action.goToReferences",
"editor.action.rename",
"editor.action.quickFix"
]
@doc """
Check if an agent has permission to use a specific VS Code tool.
Returns {:ok, permission_level} if allowed, {:error, reason} if denied.
"""
def check_permission(context, tool_name, args) do
agent_id = context[:agent_id] || "unknown"
# Get required permission level for this tool
required_level = get_required_permission(tool_name, args)
# Get agent's permission level
agent_level = get_agent_permission_level(agent_id)
# Check if agent has sufficient permissions
if permission_sufficient?(agent_level, required_level) do
# Additional checks for specific tools
case additional_checks(tool_name, args, context) do
:ok ->
{:ok, required_level}
{:error, reason} ->
{:error, reason}
end
else
{:error, "Insufficient permissions. Required: #{required_level}, Agent has: #{agent_level}"}
end
end
@doc """
Get an agent's permission level based on their capabilities and trust level.
"""
def get_agent_permission_level(agent_id) do
# For now, default to filesystem level for GitHub Copilot
# In a real implementation, this would check:
# - Agent registration data
# - Trust scores
# - Capability declarations
# - User-configured permissions
case agent_id do
"github_copilot_session" -> :filesystem
id when is_binary(id) and byte_size(id) > 0 -> :editor # Other registered agents
_ -> :read_only # Unknown agents
end
end
@doc """
Update an agent's permission level (for administrative purposes).
"""
def set_agent_permission_level(agent_id, level) when level in [:read_only, :editor, :filesystem, :terminal, :git, :admin] do
# This would persist to a database or configuration store
Logger.info("Setting permission level for agent #{agent_id} to #{level}")
:ok
end
# Private functions
defp get_required_permission(tool_name, args) do
case Map.get(@tool_permissions, tool_name) do
nil -> :admin # Unknown tools require admin by default
:admin when tool_name == "vscode_run_command" ->
# Special handling for run_command - check specific command
command = args["command"]
if command in @whitelisted_commands do
:editor # Whitelisted commands only need editor level
else
:admin # Unknown commands need admin
end
level -> level
end
end
defp permission_sufficient?(agent_level, required_level) do
agent_numeric = Map.get(@permission_levels, agent_level, 0)
required_numeric = Map.get(@permission_levels, required_level, 999)
agent_numeric >= required_numeric
end
defp additional_checks(tool_name, args, context) do
case tool_name do
tool when tool in ["vscode_write_file", "vscode_create_file", "vscode_delete_file"] ->
check_workspace_bounds(args["path"], context)
"vscode_run_command" ->
check_command_safety(args["command"], args["args"])
_ ->
:ok
end
end
defp check_workspace_bounds(path, _context) when is_binary(path) do
# Ensure file operations are within workspace bounds
# This is a simplified check - real implementation would use VS Code workspace API
forbidden_patterns = [
# System directories
"/etc/", "/bin/", "/usr/", "/var/", "/tmp/",
# User sensitive areas
"/.ssh/", "/.config/", "/home/", "~",
# Relative path traversal
"../", "..\\"
]
if Enum.any?(forbidden_patterns, fn pattern -> String.contains?(path, pattern) end) do
{:error, "Path outside workspace bounds or accessing sensitive directories"}
else
:ok
end
end
defp check_workspace_bounds(_path, _context), do: {:error, "Invalid path format"}
defp check_command_safety(command, args) when is_binary(command) do
cond do
command in @whitelisted_commands ->
:ok
String.starts_with?(command, "extension.") ->
{:error, "Extension commands not allowed for security"}
String.contains?(command, "terminal") ->
{:error, "Terminal commands require terminal permission level"}
String.contains?(command, "git") ->
{:error, "Git commands require git permission level"}
true ->
{:error, "Command '#{command}' not in whitelist"}
end
end
defp check_command_safety(_command, _args), do: {:error, "Invalid command format"}
@doc """
Get summary of permission levels and their capabilities.
"""
def get_permission_info do
%{
levels: %{
read_only: "File reading, workspace inspection, message display",
editor: "Text editing, selections, safe editor commands",
filesystem: "File creation/deletion, directory operations",
terminal: "Terminal access and command execution",
git: "Version control operations",
admin: "Settings, extensions, unrestricted commands"
},
tool_requirements: @tool_permissions,
whitelisted_commands: @whitelisted_commands
}
end
end

View File

@@ -0,0 +1,443 @@
defmodule AgentCoordinator.VSCodeToolProvider do
@moduledoc """
Provides VS Code Extension API tools as MCP-compatible tools.
This module wraps VS Code's Extension API calls and exposes them as MCP tools
that can be used by agents through the unified coordination system.
"""
require Logger
alias AgentCoordinator.VSCodePermissions
@doc """
Returns the list of available VS Code tools with their MCP schemas.
"""
def get_tools do
[
# File Operations
%{
"name" => "vscode_read_file",
"description" => "Read file contents using VS Code's file system API. Only works within workspace folders.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"path" => %{
"type" => "string",
"description" => "Relative or absolute path to the file within the workspace"
},
"encoding" => %{
"type" => "string",
"description" => "File encoding (default: utf8)",
"enum" => ["utf8", "utf16le", "base64"]
}
},
"required" => ["path"]
}
},
%{
"name" => "vscode_write_file",
"description" => "Write content to a file using VS Code's file system API. Creates directories if needed.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"path" => %{
"type" => "string",
"description" => "Relative or absolute path to the file within the workspace"
},
"content" => %{
"type" => "string",
"description" => "Content to write to the file"
},
"encoding" => %{
"type" => "string",
"description" => "File encoding (default: utf8)",
"enum" => ["utf8", "utf16le", "base64"]
},
"create_directories" => %{
"type" => "boolean",
"description" => "Create parent directories if they don't exist (default: true)"
}
},
"required" => ["path", "content"]
}
},
%{
"name" => "vscode_create_file",
"description" => "Create a new file using VS Code's file system API.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"path" => %{
"type" => "string",
"description" => "Relative or absolute path for the new file within the workspace"
},
"content" => %{
"type" => "string",
"description" => "Initial content for the file (default: empty)",
"default" => ""
},
"overwrite" => %{
"type" => "boolean",
"description" => "Whether to overwrite if file exists (default: false)"
}
},
"required" => ["path"]
}
},
%{
"name" => "vscode_delete_file",
"description" => "Delete a file or directory using VS Code's file system API.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"path" => %{
"type" => "string",
"description" => "Relative or absolute path to the file/directory within the workspace"
},
"recursive" => %{
"type" => "boolean",
"description" => "Whether to delete directories recursively (default: false)"
},
"use_trash" => %{
"type" => "boolean",
"description" => "Whether to move to trash instead of permanent deletion (default: true)"
}
},
"required" => ["path"]
}
},
%{
"name" => "vscode_list_directory",
"description" => "List contents of a directory using VS Code's file system API.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"path" => %{
"type" => "string",
"description" => "Relative or absolute path to the directory within the workspace"
},
"include_hidden" => %{
"type" => "boolean",
"description" => "Whether to include hidden files/directories (default: false)"
}
},
"required" => ["path"]
}
},
%{
"name" => "vscode_get_workspace_folders",
"description" => "Get list of workspace folders currently open in VS Code.",
"inputSchema" => %{
"type" => "object",
"properties" => %{}
}
},
# Editor Operations
%{
"name" => "vscode_get_active_editor",
"description" => "Get information about the currently active text editor.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"include_content" => %{
"type" => "boolean",
"description" => "Whether to include the full document content (default: false)"
}
}
}
},
%{
"name" => "vscode_set_editor_content",
"description" => "Set content in the active text editor or a specific file.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"content" => %{
"type" => "string",
"description" => "Content to set in the editor"
},
"file_path" => %{
"type" => "string",
"description" => "Optional: specific file path. If not provided, uses active editor"
},
"range" => %{
"type" => "object",
"description" => "Optional: specific range to replace",
"properties" => %{
"start_line" => %{"type" => "number"},
"start_character" => %{"type" => "number"},
"end_line" => %{"type" => "number"},
"end_character" => %{"type" => "number"}
}
},
"create_if_not_exists" => %{
"type" => "boolean",
"description" => "Create file if it doesn't exist (default: false)"
}
},
"required" => ["content"]
}
},
%{
"name" => "vscode_get_selection",
"description" => "Get current text selection in the active editor.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"include_content" => %{
"type" => "boolean",
"description" => "Whether to include the selected text content (default: true)"
}
}
}
},
%{
"name" => "vscode_set_selection",
"description" => "Set text selection in the active editor.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"start_line" => %{
"type" => "number",
"description" => "Start line number (0-based)"
},
"start_character" => %{
"type" => "number",
"description" => "Start character position (0-based)"
},
"end_line" => %{
"type" => "number",
"description" => "End line number (0-based)"
},
"end_character" => %{
"type" => "number",
"description" => "End character position (0-based)"
},
"reveal" => %{
"type" => "boolean",
"description" => "Whether to reveal/scroll to the selection (default: true)"
}
},
"required" => ["start_line", "start_character", "end_line", "end_character"]
}
},
# Command Operations
%{
"name" => "vscode_run_command",
"description" => "Execute a VS Code command. Only whitelisted commands are allowed for security.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"command" => %{
"type" => "string",
"description" => "VS Code command to execute"
},
"args" => %{
"type" => "array",
"description" => "Arguments to pass to the command",
"items" => %{"type" => "string"}
}
},
"required" => ["command"]
}
},
# User Communication
%{
"name" => "vscode_show_message",
"description" => "Display a message to the user in VS Code.",
"inputSchema" => %{
"type" => "object",
"properties" => %{
"message" => %{
"type" => "string",
"description" => "Message to display"
},
"type" => %{
"type" => "string",
"description" => "Message type",
"enum" => ["info", "warning", "error"]
},
"modal" => %{
"type" => "boolean",
"description" => "Whether to show as modal dialog (default: false)"
}
},
"required" => ["message"]
}
}
]
end
@doc """
Handle a VS Code tool call with permission checking and error handling.
"""
def handle_tool_call(tool_name, args, context) do
Logger.info("VS Code tool call: #{tool_name} with args: #{inspect(args)}")
# Check permissions
case VSCodePermissions.check_permission(context, tool_name, args) do
{:ok, _permission_level} ->
# Execute the tool
result = execute_tool(tool_name, args, context)
# Log the operation
log_tool_operation(tool_name, args, context, result)
result
{:error, reason} ->
Logger.warning("Permission denied for #{tool_name}: #{reason}")
{:error, %{"error" => "Permission denied", "reason" => reason}}
end
end
# Private function to execute individual tools
defp execute_tool(tool_name, args, context) do
case tool_name do
"vscode_read_file" -> read_file(args, context)
"vscode_write_file" -> write_file(args, context)
"vscode_create_file" -> create_file(args, context)
"vscode_delete_file" -> delete_file(args, context)
"vscode_list_directory" -> list_directory(args, context)
"vscode_get_workspace_folders" -> get_workspace_folders(args, context)
"vscode_get_active_editor" -> get_active_editor(args, context)
"vscode_set_editor_content" -> set_editor_content(args, context)
"vscode_get_selection" -> get_selection(args, context)
"vscode_set_selection" -> set_selection(args, context)
"vscode_run_command" -> run_command(args, context)
"vscode_show_message" -> show_message(args, context)
_ -> {:error, %{"error" => "Unknown VS Code tool", "tool" => tool_name}}
end
end
# Tool implementations (these will call VS Code Extension API via JavaScript bridge)
defp read_file(args, _context) do
# For now, return a placeholder - we'll implement the actual VS Code API bridge
{:ok, %{
"content" => "// VS Code file content would be here",
"path" => args["path"],
"encoding" => args["encoding"] || "utf8",
"size" => 42,
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp write_file(args, _context) do
{:ok, %{
"path" => args["path"],
"bytes_written" => String.length(args["content"]),
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp create_file(args, _context) do
{:ok, %{
"path" => args["path"],
"created" => true,
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp delete_file(args, _context) do
{:ok, %{
"path" => args["path"],
"deleted" => true,
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp list_directory(args, _context) do
{:ok, %{
"path" => args["path"],
"entries" => [
%{"name" => "file1.txt", "type" => "file", "size" => 123},
%{"name" => "subdir", "type" => "directory", "size" => nil}
]
}}
end
defp get_workspace_folders(_args, _context) do
{:ok, %{
"folders" => [
%{"name" => "agent_coordinator", "uri" => "file:///home/ra/agent_coordinator"}
]
}}
end
defp get_active_editor(args, _context) do
{:ok, %{
"file_path" => "/home/ra/agent_coordinator/lib/agent_coordinator.ex",
"language" => "elixir",
"line_count" => 150,
"content" => if(args["include_content"], do: "// Editor content here", else: nil),
"selection" => %{
"start" => %{"line" => 10, "character" => 5},
"end" => %{"line" => 10, "character" => 15}
},
"cursor_position" => %{"line" => 10, "character" => 15}
}}
end
defp set_editor_content(args, _context) do
{:ok, %{
"file_path" => args["file_path"],
"content_length" => String.length(args["content"]),
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp get_selection(args, _context) do
{:ok, %{
"selection" => %{
"start" => %{"line" => 5, "character" => 0},
"end" => %{"line" => 8, "character" => 20}
},
"content" => if(args["include_content"], do: "Selected text here", else: nil),
"is_empty" => false
}}
end
defp set_selection(args, _context) do
{:ok, %{
"selection" => %{
"start" => %{"line" => args["start_line"], "character" => args["start_character"]},
"end" => %{"line" => args["end_line"], "character" => args["end_character"]}
},
"revealed" => args["reveal"] != false
}}
end
defp run_command(args, _context) do
# This would execute actual VS Code commands
{:ok, %{
"command" => args["command"],
"args" => args["args"] || [],
"result" => "Command executed successfully",
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
defp show_message(args, _context) do
{:ok, %{
"message" => args["message"],
"type" => args["type"] || "info",
"displayed" => true,
"timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
}}
end
# Logging function
defp log_tool_operation(tool_name, args, context, result) do
Logger.info("VS Code tool operation completed", %{
tool: tool_name,
agent_id: context[:agent_id],
args_summary: inspect(Map.take(args, ["path", "command", "message"])),
success: match?({:ok, _}, result),
timestamp: DateTime.utc_now()
})
end
end