Spaces:
Build error
Build error
File size: 9,276 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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
import asyncio
from pathlib import Path
from prompt_toolkit import print_formatted_text
from prompt_toolkit.shortcuts import clear, print_container
from prompt_toolkit.widgets import Frame, TextArea
from openhands.cli.settings import (
display_settings,
modify_llm_settings_advanced,
modify_llm_settings_basic,
)
from openhands.cli.tui import (
COLOR_GREY,
UsageMetrics,
cli_confirm,
display_help,
display_shutdown_message,
display_status,
)
from openhands.cli.utils import (
add_local_config_trusted_dir,
get_local_config_trusted_dirs,
read_file,
write_to_file,
)
from openhands.core.config import (
OpenHandsConfig,
)
from openhands.core.schema import AgentState
from openhands.events import EventSource
from openhands.events.action import (
ChangeAgentStateAction,
MessageAction,
)
from openhands.events.stream import EventStream
from openhands.storage.settings.file_settings_store import FileSettingsStore
async def handle_commands(
command: str,
event_stream: EventStream,
usage_metrics: UsageMetrics,
sid: str,
config: OpenHandsConfig,
current_dir: str,
settings_store: FileSettingsStore,
) -> tuple[bool, bool, bool]:
close_repl = False
reload_microagents = False
new_session_requested = False
if command == '/exit':
close_repl = handle_exit_command(
event_stream,
usage_metrics,
sid,
)
elif command == '/help':
handle_help_command()
elif command == '/init':
close_repl, reload_microagents = await handle_init_command(
config, event_stream, current_dir
)
elif command == '/status':
handle_status_command(usage_metrics, sid)
elif command == '/new':
close_repl, new_session_requested = handle_new_command(
event_stream, usage_metrics, sid
)
elif command == '/settings':
await handle_settings_command(config, settings_store)
elif command == '/resume':
close_repl, new_session_requested = await handle_resume_command(event_stream)
else:
close_repl = True
action = MessageAction(content=command)
event_stream.add_event(action, EventSource.USER)
return close_repl, reload_microagents, new_session_requested
def handle_exit_command(
event_stream: EventStream, usage_metrics: UsageMetrics, sid: str
) -> bool:
close_repl = False
confirm_exit = (
cli_confirm('\nTerminate session?', ['Yes, proceed', 'No, dismiss']) == 0
)
if confirm_exit:
event_stream.add_event(
ChangeAgentStateAction(AgentState.STOPPED),
EventSource.ENVIRONMENT,
)
display_shutdown_message(usage_metrics, sid)
close_repl = True
return close_repl
def handle_help_command() -> None:
display_help()
async def handle_init_command(
config: OpenHandsConfig, event_stream: EventStream, current_dir: str
) -> tuple[bool, bool]:
REPO_MD_CREATE_PROMPT = """
Please explore this repository. Create the file .openhands/microagents/repo.md with:
- A description of the project
- An overview of the file structure
- Any information on how to run tests or other relevant commands
- Any other information that would be helpful to a brand new developer
Keep it short--just a few paragraphs will do.
"""
close_repl = False
reload_microagents = False
if config.runtime == 'local':
init_repo = await init_repository(current_dir)
if init_repo:
event_stream.add_event(
MessageAction(content=REPO_MD_CREATE_PROMPT),
EventSource.USER,
)
reload_microagents = True
close_repl = True
else:
print_formatted_text(
'\nRepository initialization through the CLI is only supported for local runtime.\n'
)
return close_repl, reload_microagents
def handle_status_command(usage_metrics: UsageMetrics, sid: str) -> None:
display_status(usage_metrics, sid)
def handle_new_command(
event_stream: EventStream, usage_metrics: UsageMetrics, sid: str
) -> tuple[bool, bool]:
close_repl = False
new_session_requested = False
new_session_requested = (
cli_confirm(
'\nCurrent session will be terminated and you will lose the conversation history.\n\nContinue?',
['Yes, proceed', 'No, dismiss'],
)
== 0
)
if new_session_requested:
close_repl = True
new_session_requested = True
event_stream.add_event(
ChangeAgentStateAction(AgentState.STOPPED),
EventSource.ENVIRONMENT,
)
display_shutdown_message(usage_metrics, sid)
return close_repl, new_session_requested
async def handle_settings_command(
config: OpenHandsConfig,
settings_store: FileSettingsStore,
) -> None:
display_settings(config)
modify_settings = cli_confirm(
'\nWhich settings would you like to modify?',
[
'Basic',
'Advanced',
'Go back',
],
)
if modify_settings == 0:
await modify_llm_settings_basic(config, settings_store)
elif modify_settings == 1:
await modify_llm_settings_advanced(config, settings_store)
# FIXME: Currently there's an issue with the actual 'resume' behavior.
# Setting the agent state to RUNNING will currently freeze the agent without continuing with the rest of the task.
# This is a workaround to handle the resume command for the time being. Replace user message with the state change event once the issue is fixed.
async def handle_resume_command(
event_stream: EventStream,
) -> tuple[bool, bool]:
close_repl = True
new_session_requested = False
event_stream.add_event(
MessageAction(content='continue'),
EventSource.USER,
)
# event_stream.add_event(
# ChangeAgentStateAction(AgentState.RUNNING),
# EventSource.ENVIRONMENT,
# )
return close_repl, new_session_requested
async def init_repository(current_dir: str) -> bool:
repo_file_path = Path(current_dir) / '.openhands' / 'microagents' / 'repo.md'
init_repo = False
if repo_file_path.exists():
try:
# Path.exists() ensures repo_file_path is not None, so we can safely pass it to read_file
content = await asyncio.get_event_loop().run_in_executor(
None, read_file, repo_file_path
)
print_formatted_text(
'Repository instructions file (repo.md) already exists.\n'
)
container = Frame(
TextArea(
text=content,
read_only=True,
style=COLOR_GREY,
wrap_lines=True,
),
title='Repository Instructions (repo.md)',
style=f'fg:{COLOR_GREY}',
)
print_container(container)
print_formatted_text('') # Add a newline after the frame
init_repo = (
cli_confirm(
'Do you want to re-initialize?',
['Yes, re-initialize', 'No, dismiss'],
)
== 0
)
if init_repo:
write_to_file(repo_file_path, '')
except Exception:
print_formatted_text('Error reading repository instructions file (repo.md)')
init_repo = False
else:
print_formatted_text(
'\nRepository instructions file will be created by exploring the repository.\n'
)
init_repo = (
cli_confirm(
'Do you want to proceed?',
['Yes, create', 'No, dismiss'],
)
== 0
)
return init_repo
def check_folder_security_agreement(config: OpenHandsConfig, current_dir: str) -> bool:
# Directories trusted by user for the CLI to use as workspace
# Config from ~/.openhands/config.toml overrides the app config
app_config_trusted_dirs = config.sandbox.trusted_dirs
local_config_trusted_dirs = get_local_config_trusted_dirs()
trusted_dirs = local_config_trusted_dirs
if not local_config_trusted_dirs:
trusted_dirs = app_config_trusted_dirs
is_trusted = current_dir in trusted_dirs
if not is_trusted:
security_frame = Frame(
TextArea(
text=(
f' Do you trust the files in this folder?\n\n'
f' {current_dir}\n\n'
' OpenHands may read and execute files in this folder with your permission.'
),
style=COLOR_GREY,
read_only=True,
wrap_lines=True,
),
style=f'fg:{COLOR_GREY}',
)
clear()
print_container(security_frame)
print_formatted_text('')
confirm = (
cli_confirm('Do you wish to continue?', ['Yes, proceed', 'No, exit']) == 0
)
if confirm:
add_local_config_trusted_dir(current_dir)
return confirm
return True
|