Skip to content

fix: hide special paths; sort models #2325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions opendevin/runtime/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ def get_folder_structure(workdir: Path) -> WorkspaceFile:
root = WorkspaceFile(name=workdir.name, children=[])
for item in workdir.iterdir():
if item.is_dir():
# Ignore special folders
if item.parts[-1] in (
'.git',
'.DS_Store',
'.svn',
'.hg',
'.idea',
'.vscode',
'.settings',
'.pytest_cache',
'__pycache__',
'node_modules',
'vendor',
'build',
'dist',
'bin',
'logs',
'log',
'tmp',
'temp',
'coverage',
'venv',
'env',
):
continue
dir = get_folder_structure(item)
if dir.children:
root.children.append(dir)
Expand Down
29 changes: 29 additions & 0 deletions opendevin/runtime/server/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ def resolve_path(file_path, working_directory):
# Get path relative to host
path_in_host_workspace = Path(config.workspace_base) / path_in_workspace

# Prevent special folders
if path_in_host_workspace:
path_obj = Path(path_in_host_workspace)
if path_obj:
if path_obj.parts[-1] in (
'.git',
'.DS_Store',
'.svn',
'.hg',
'.idea',
'.vscode',
'.settings',
'.pytest_cache',
'__pycache__',
'node_modules',
'vendor',
'build',
'dist',
'bin',
'logs',
'log',
'tmp',
'temp',
'coverage',
'venv',
'env',
):
raise PermissionError('Invalid path.')

return path_in_host_workspace


Expand Down
15 changes: 12 additions & 3 deletions opendevin/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This is a WebSocket server that executes tasks using an agent.

## Install

Follow the instructions in the base README.md to install dependencies and set up.

## Start the Server
Expand All @@ -13,7 +14,7 @@ uvicorn opendevin.server.listen:app --reload --port 3000

## Test the Server

You can use `websocat` to test the server: https://github.com/vi/websocat
You can use [`websocat`](https://github.com/vi/websocat) to test the server.

```sh
websocat ws://127.0.0.1:3000/ws
Expand All @@ -24,23 +25,28 @@ websocat ws://127.0.0.1:3000/ws

```sh
LLM_API_KEY=sk-... # Your OpenAI API Key
LLM_MODEL=gpt-4o # Default model for the agent to use
WORKSPACE_BASE=/path/to/your/workspace # Default path to model's workspace
LLM_MODEL=gpt-4o # Default model for the agent to use
WORKSPACE_BASE=/path/to/your/workspace # Default absolute path to workspace
```

## API Schema

There are two types of messages that can be sent to, or received from, the server:

* Actions
* Observations

### Actions

An action has three parts:

* `action`: The action to be taken
* `args`: The arguments for the action
* `message`: A friendly message that can be put in the chat log

There are several kinds of actions. Their arguments are listed below.
This list may grow over time.

* `initialize` - initializes the agent. Only sent by client.
* `model` - the name of the model to use
* `directory` - the path to the workspace
Expand All @@ -66,14 +72,17 @@ This list may grow over time.
* `finish` - agent signals that the task is completed

### Observations

An observation has four parts:

* `observation`: The observation type
* `content`: A string representing the observed data
* `extras`: additional structured data
* `message`: A friendly message that can be put in the chat log

There are several kinds of observations. Their extras are listed below.
This list may grow over time.

* `read` - the content of a file
* `path` - the path of the file read
* `browse` - the HTML content of a url
Expand Down
41 changes: 38 additions & 3 deletions opendevin/server/listen.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
with warnings.catch_warnings():
warnings.simplefilter('ignore')
import litellm
from pathlib import Path

from fastapi import FastAPI, Request, Response, UploadFile, WebSocket, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
Expand Down Expand Up @@ -190,7 +192,7 @@ async def get_litellm_models():
bedrock_model_list = bedrock.list_foundation_models()
model_list = litellm_model_list_without_bedrock + bedrock_model_list

return list(set(model_list))
return list(sorted(set(model_list)))


@app.get('/api/options/agents')
Expand All @@ -203,7 +205,7 @@ async def get_agents():
curl http://localhost:3000/api/agents
```
"""
agents = Agent.list_agents()
agents = sorted(Agent.list_agents())
return agents


Expand All @@ -223,8 +225,41 @@ def list_files(request: Request, path: str = '/'):
content={'error': 'Runtime not yet initialized'},
)

exclude_list = (
'.git',
'.DS_Store',
'.svn',
'.hg',
'.idea',
'.vscode',
'.settings',
'.pytest_cache',
'__pycache__',
'node_modules',
'vendor',
'build',
'dist',
'bin',
'logs',
'log',
'tmp',
'temp',
'coverage',
'venv',
'env',
)

try:
return request.state.session.agent_session.runtime.file_store.list(path)
entries = request.state.session.agent_session.runtime.file_store.list(path)

# Filter entries, excluding special folders
if entries:
return [
entry
for entry in entries
if Path(entry).parts and Path(entry).parts[-1] not in exclude_list
]
return []
except Exception as e:
logger.error(f'Error refreshing files: {e}', exc_info=False)
error_msg = f'Error refreshing files: {e}'
Expand Down