Spaces:
Build error
Build error
File size: 4,570 Bytes
51ff9e5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
import asyncio
import os
import shutil
import sys
import uuid
from dataclasses import dataclass
from pathlib import Path
from typing import Optional
from openhands.core.logger import openhands_logger as logger
from openhands.events.action import Action
from openhands.events.observation import Observation
from openhands.runtime.plugins.requirement import Plugin, PluginRequirement
from openhands.runtime.utils.system import check_port_available
from openhands.utils.shutdown_listener import should_continue
@dataclass
class VSCodeRequirement(PluginRequirement):
name: str = 'vscode'
class VSCodePlugin(Plugin):
name: str = 'vscode'
vscode_port: Optional[int] = None
vscode_connection_token: Optional[str] = None
gateway_process: asyncio.subprocess.Process
async def initialize(self, username: str) -> None:
# Check if we're on Windows - VSCode plugin is not supported on Windows
if os.name == 'nt' or sys.platform == 'win32':
self.vscode_port = None
self.vscode_connection_token = None
logger.warning(
'VSCode plugin is not supported on Windows. Plugin will be disabled.'
)
return
if username not in ['root', 'openhands']:
self.vscode_port = None
self.vscode_connection_token = None
logger.warning(
'VSCodePlugin is only supported for root or openhands user. '
'It is not yet supported for other users (i.e., when running LocalRuntime).'
)
return
# Set up VSCode settings.json
self._setup_vscode_settings()
try:
self.vscode_port = int(os.environ['VSCODE_PORT'])
except (KeyError, ValueError):
logger.warning(
'VSCODE_PORT environment variable not set or invalid. VSCode plugin will be disabled.'
)
return
self.vscode_connection_token = str(uuid.uuid4())
if not check_port_available(self.vscode_port):
logger.warning(
f'Port {self.vscode_port} is not available. VSCode plugin will be disabled.'
)
return
cmd = (
f"su - {username} -s /bin/bash << 'EOF'\n"
f'sudo chown -R {username}:{username} /openhands/.openvscode-server\n'
'cd /workspace\n'
f'exec /openhands/.openvscode-server/bin/openvscode-server --host 0.0.0.0 --connection-token {self.vscode_connection_token} --port {self.vscode_port} --disable-workspace-trust\n'
'EOF'
)
# Using asyncio.create_subprocess_shell instead of subprocess.Popen
# to avoid ASYNC101 linting error
self.gateway_process = await asyncio.create_subprocess_shell(
cmd,
stderr=asyncio.subprocess.STDOUT,
stdout=asyncio.subprocess.PIPE,
)
# read stdout until the kernel gateway is ready
output = ''
while should_continue() and self.gateway_process.stdout is not None:
line_bytes = await self.gateway_process.stdout.readline()
line = line_bytes.decode('utf-8')
print(line)
output += line
if 'at' in line:
break
await asyncio.sleep(1)
logger.debug('Waiting for VSCode server to start...')
logger.debug(
f'VSCode server started at port {self.vscode_port}. Output: {output}'
)
def _setup_vscode_settings(self) -> None:
"""
Set up VSCode settings by creating the .vscode directory in the workspace
and copying the settings.json file there.
"""
# Get the path to the settings.json file in the plugin directory
current_dir = Path(__file__).parent
settings_path = current_dir / 'settings.json'
# Create the .vscode directory in the workspace if it doesn't exist
vscode_dir = Path('/workspace/.vscode')
vscode_dir.mkdir(parents=True, exist_ok=True)
# Copy the settings.json file to the .vscode directory
target_path = vscode_dir / 'settings.json'
shutil.copy(settings_path, target_path)
# Make sure the settings file is readable and writable by all users
os.chmod(target_path, 0o666)
logger.debug(f'VSCode settings copied to {target_path}')
async def run(self, action: Action) -> Observation:
"""Run the plugin for a given action."""
raise NotImplementedError('VSCodePlugin does not support run method')
|