mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
Merge branch 'main' of github.com:OpenDevin/OpenDevin into enyst/memories-condenser
This commit is contained in:
@@ -8,8 +8,8 @@ const config: Config = {
|
||||
favicon: "img/logo.png",
|
||||
|
||||
// Set the production url of your site here
|
||||
url: "https://OpenDevin.github.io",
|
||||
baseUrl: "/OpenDevin/",
|
||||
url: "https://docs.all-hands.dev",
|
||||
baseUrl: "/",
|
||||
|
||||
// GitHub pages deployment config.
|
||||
organizationName: "OpenDevin",
|
||||
|
||||
@@ -134,9 +134,9 @@ le point de terminaison API avec lequel vous essayez de vous connecter. Cela arr
|
||||
* Si vous êtes en cours d'exécution dans l'interface utilisateur, assurez-vous de définir le `model` dans le modal des paramètres
|
||||
* Si vous êtes en cours d'exécution sans interface (via main.py), assurez-vous de définir `LLM_MODEL` dans votre env/config
|
||||
* Assurez-vous de suivre les instructions spéciales de votre fournisseur de LLM
|
||||
* [ollama](/OpenDevin/fr/modules/usage/llms/localLLMs)
|
||||
* [Azure](/OpenDevin/fr/modules/usage/llms/azureLLMs)
|
||||
* [Google](/OpenDevin/fr/modules/usage/llms/googleLLMs)
|
||||
* [ollama](/fr/modules/usage/llms/localLLMs)
|
||||
* [Azure](/fr/modules/usage/llms/azureLLMs)
|
||||
* [Google](/fr/modules/usage/llms/googleLLMs)
|
||||
* Assurez-vous que votre clé API est correcte
|
||||
* Voyez si vous pouvez vous connecter au LLM en utilisant `curl`
|
||||
* Essayez de [vous connecter via LiteLLM directement](https://github.com/BerriAI/litellm) pour tester votre configuration
|
||||
|
||||
@@ -129,9 +129,9 @@ openai.NotFoundError: Error code: 404 - {'error': {'code': '404', 'message': 'Re
|
||||
* 如果您在 UI 中运行,请确保在设置模式中设置 `model`
|
||||
* 如果您通过 main.py 运行,请确保在环境变量/配置中设置 `LLM_MODEL`
|
||||
* 确保遵循了您的 LLM 提供商的任何特殊说明
|
||||
* [Ollama](/OpenDevin/zh-Hans/modules/usage/llms/localLLMs)
|
||||
* [Azure](/OpenDevin/zh-Hans/modules/usage/llms/azureLLMs)
|
||||
* [Google](/OpenDevin/zh-Hans/modules/usage/llms/googleLLMs)
|
||||
* [Ollama](/zh-Hans/modules/usage/llms/localLLMs)
|
||||
* [Azure](/zh-Hans/modules/usage/llms/azureLLMs)
|
||||
* [Google](/zh-Hans/modules/usage/llms/googleLLMs)
|
||||
* 确保您的 API 密钥正确无误
|
||||
* 尝试使用 `curl` 连接到 LLM
|
||||
* 尝试[直接通过 LiteLLM 连接](https://github.com/BerriAI/litellm)来测试您的设置
|
||||
|
||||
112
docs/modules/usage/custom_sandbox_guide.md
Normal file
112
docs/modules/usage/custom_sandbox_guide.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# 💿 How to Create a Custom Docker Sandbox
|
||||
|
||||
The default OpenDevin sandbox comes with a [minimal ubuntu configuration](https://github.com/OpenDevin/OpenDevin/blob/main/containers/sandbox/Dockerfile). Your use case may need additional software installed by default. This guide will teach you how to accomplish this by utilizing a custom docker image.
|
||||
|
||||
## Setup
|
||||
|
||||
To get started running with your own Docker Sandbox image you need to ensure you can build OpenDevin locally via the following:
|
||||
1. Clone the OpenDevin github repository to your local machine
|
||||
2. In the root (OpenDevin/) directory, run ```make build```
|
||||
3. Then run ```make run```
|
||||
4. Finally navigate your browser to ```localhost:3001``` to ensure that your local build of OpenDevin is functional
|
||||
|
||||
|
||||
Please refer to [Development.md](https://github.com/OpenDevin/OpenDevin/blob/main/Development.md) for more installation details.
|
||||
|
||||
> Note that the above steps will take some time to run and will require that your have python3.11, poetry (a python package manager), and Docker installed
|
||||
|
||||
|
||||
## Create Your Docker Image
|
||||
|
||||
Next you must create your custom docker image, which should be debian/ubuntu based. For example if we want want OpenDevin to have access to the "node" binary, we would use the following Dockerfile:
|
||||
```bash
|
||||
# Start with latest ubuntu image
|
||||
FROM ubuntu:latest
|
||||
|
||||
# Run needed updates
|
||||
RUN apt-get update && apt-get install
|
||||
|
||||
# Install node
|
||||
RUN apt-get install -y nodejs
|
||||
```
|
||||
Next build your docker image with the name of your choice, for example "custom_image". To do this you can create a directory and put your file inside it with the name "Dockerfile", and inside the directory run the following command:
|
||||
```docker build -t custom_image .```
|
||||
|
||||
This will produce a new image called ```custom_image``` that will be available in Docker Engine.
|
||||
|
||||
> Note that in the configuration described in this document, OpenDevin will run as user "opendevin" inside the sandbox and thus all packages installed via the docker file should be available to all users on the system, not just root
|
||||
>
|
||||
> Installing with apt-get above installs node for all users
|
||||
|
||||
|
||||
## Specify your custom image in config.toml file
|
||||
|
||||
OpenDevin configuration occurs via the top level ```config.toml``` file.
|
||||
Create a ```config.toml``` file in the OpenDevin directory and enter these contents:
|
||||
```
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
persist_sandbox=false
|
||||
run_as_devin=true
|
||||
sandbox_container_image="custom_image"
|
||||
```
|
||||
> Ensure that sandbox_container_image is set to the name of your custom image from the previous step
|
||||
|
||||
## Run
|
||||
Run OpenDevin by running ```make run``` in the top level directory.
|
||||
A lot of things will happen but ultimately the OpenDevin server and frontend should be running.
|
||||
|
||||
Navigate to ```localhost:3001``` and check if your desired dependencies are available.
|
||||
|
||||
In the case of the example above, running ```node -v``` in the terminal produces ```v18.19.1```
|
||||
|
||||
Congratulations!
|
||||
|
||||
## Technical Explanation
|
||||
|
||||
The relevant code is defined in [ssh_box.py](https://github.com/OpenDevin/OpenDevin/blob/main/opendevin/runtime/docker/ssh_box.py) and [image_agnostic_util.py](https://github.com/OpenDevin/OpenDevin/blob/main/opendevin/runtime/docker/image_agnostic_util.py).
|
||||
|
||||
In particular, ssh_box.py checks the config object for ```config.sandbox_container_image``` and then attempts to retrieve the image using [get_od_sandbox_image](https://github.com/OpenDevin/OpenDevin/blob/main/opendevin/runtime/docker/image_agnostic_util.py#L72) which is defined in image_agnostic_util.py.
|
||||
|
||||
When first using a custom image, it will not be found and thus it will be built (on subsequent runs the built image will be found and returned).
|
||||
|
||||
The custom image is built using [_build_sandbox_image()](https://github.com/OpenDevin/OpenDevin/blob/main/opendevin/runtime/docker/image_agnostic_util.py#L29), which creates a docker file using your custom_image as a base and then configures the environment for OpenDevin, like this:
|
||||
```
|
||||
dockerfile_content = (
|
||||
f'FROM {base_image}\n'
|
||||
'RUN apt update && apt install -y openssh-server wget sudo\n'
|
||||
'RUN mkdir -p -m0755 /var/run/sshd\n'
|
||||
'RUN mkdir -p /opendevin && mkdir -p /opendevin/logs && chmod 777 /opendevin/logs\n'
|
||||
'RUN wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"\n'
|
||||
'RUN bash Miniforge3-$(uname)-$(uname -m).sh -b -p /opendevin/miniforge3\n'
|
||||
'RUN bash -c ". /opendevin/miniforge3/etc/profile.d/conda.sh && conda config --set changeps1 False && conda config --append channels conda-forge"\n'
|
||||
'RUN echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> ~/.bashrc\n'
|
||||
'RUN echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> /opendevin/bash.bashrc\n'
|
||||
).strip()
|
||||
```
|
||||
|
||||
> Note: the name of the image is modified via [_get_new_image_name()](https://github.com/OpenDevin/OpenDevin/blob/main/opendevin/runtime/docker/image_agnostic_util.py#L63) and it is the modified name that is searched for on subsequent runs
|
||||
|
||||
|
||||
|
||||
|
||||
## Troubleshooting / Errors
|
||||
|
||||
### Error: ```useradd: UID 1000 is not unique```
|
||||
If you see this error in the console output it is because OpenDevin is trying to create the opendevin user in the sandbox with a UID of 1000, however this UID is already being used in the image (for some reason). To fix this change the sandbox_user_id field in the config.toml file to a different value:
|
||||
```
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
persist_sandbox=false
|
||||
run_as_devin=true
|
||||
sandbox_container_image="custom_image"
|
||||
sandbox_user_id="1001"
|
||||
```
|
||||
|
||||
### Port use errors
|
||||
|
||||
If you see an error about a port being in use or unavailable, try deleting all running Docker Containers (run `docker ps` and `docker rm` relevant containers) and then re-running ```make run```
|
||||
|
||||
## Discuss
|
||||
|
||||
For other issues or questions join the [Slack](https://join.slack.com/t/opendevin/shared_invite/zt-2jsrl32uf-fTeeFjNyNYxqSZt5NPY3fA) or [Discord](https://discord.gg/ESHStjSjD4) and ask!
|
||||
@@ -135,9 +135,9 @@ the API endpoint you're trying to connect to. Most often this happens for Azure
|
||||
* If you're running inside the UI, be sure to set the `model` in the settings modal
|
||||
* If you're running headless (via main.py) be sure to set `LLM_MODEL` in your env/config
|
||||
* Make sure you've followed any special instructions for your LLM provider
|
||||
* [ollama](/OpenDevin/modules/usage/llms/localLLMs)
|
||||
* [Azure](/OpenDevin/modules/usage/llms/azureLLMs)
|
||||
* [Google](/OpenDevin/modules/usage/llms/googleLLMs)
|
||||
* [ollama](/modules/usage/llms/localLLMs)
|
||||
* [Azure](/modules/usage/llms/azureLLMs)
|
||||
* [Google](/modules/usage/llms/googleLLMs)
|
||||
* Make sure your API key is correct
|
||||
* See if you can connect to the LLM using `curl`
|
||||
* Try [connecting via LiteLLM directly](https://github.com/BerriAI/litellm) to test your setup
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM ghcr.io/opendevin/eval-swe-bench:builder
|
||||
|
||||
# This Dockefile is used to build the Docker image for the evaluation of the SWE-Bench.
|
||||
# This Dockerfile is used to build the Docker image for the evaluation of the SWE-Bench.
|
||||
# YOU SHOULD ENSURE ./eval_workspace CONTAINS THE EVALUATION WORKSPACE (testbed, conda)
|
||||
# Check BUILD_TESTBED_AND_ENV.md for more details.
|
||||
|
||||
|
||||
141
frontend/package-lock.json
generated
141
frontend/package-lock.json
generated
@@ -17,11 +17,11 @@
|
||||
"@xterm/xterm": "^5.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint-config-airbnb-typescript": "^18.0.0",
|
||||
"framer-motion": "^11.2.11",
|
||||
"framer-motion": "^11.2.12",
|
||||
"i18next": "^23.11.5",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"i18next-http-backend": "^2.5.2",
|
||||
"jose": "^5.4.1",
|
||||
"jose": "^5.5.0",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@@ -31,7 +31,7 @@
|
||||
"react-icons": "^5.2.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-router-dom": "^6.24.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"vite": "^5.3.1",
|
||||
@@ -42,13 +42,13 @@
|
||||
"@testing-library/jest-dom": "^6.4.6",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-highlight": "^0.12.8",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.14.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
@@ -4502,10 +4502,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@remix-run/router": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
|
||||
"integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
|
||||
"license": "MIT",
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.0.tgz",
|
||||
"integrity": "sha512-2D6XaHEVvkCn682XBnipbJjgZUU7xjLtA4dGJRBVUKpEaDYOZMENZoZjAOSb7qirxt5RupjzZxz4fK2FO+EFPw==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
@@ -5075,9 +5074,9 @@
|
||||
"integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.14.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.8.tgz",
|
||||
"integrity": "sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==",
|
||||
"version": "20.14.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz",
|
||||
"integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==",
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
@@ -5162,16 +5161,16 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz",
|
||||
"integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz",
|
||||
"integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "7.13.1",
|
||||
"@typescript-eslint/type-utils": "7.13.1",
|
||||
"@typescript-eslint/utils": "7.13.1",
|
||||
"@typescript-eslint/visitor-keys": "7.13.1",
|
||||
"@typescript-eslint/scope-manager": "7.14.1",
|
||||
"@typescript-eslint/type-utils": "7.14.1",
|
||||
"@typescript-eslint/utils": "7.14.1",
|
||||
"@typescript-eslint/visitor-keys": "7.14.1",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
@@ -5195,15 +5194,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz",
|
||||
"integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz",
|
||||
"integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "7.13.1",
|
||||
"@typescript-eslint/types": "7.13.1",
|
||||
"@typescript-eslint/typescript-estree": "7.13.1",
|
||||
"@typescript-eslint/visitor-keys": "7.13.1",
|
||||
"@typescript-eslint/scope-manager": "7.14.1",
|
||||
"@typescript-eslint/types": "7.14.1",
|
||||
"@typescript-eslint/typescript-estree": "7.14.1",
|
||||
"@typescript-eslint/visitor-keys": "7.14.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -5223,13 +5222,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz",
|
||||
"integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz",
|
||||
"integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.13.1",
|
||||
"@typescript-eslint/visitor-keys": "7.13.1"
|
||||
"@typescript-eslint/types": "7.14.1",
|
||||
"@typescript-eslint/visitor-keys": "7.14.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@@ -5240,13 +5239,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz",
|
||||
"integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz",
|
||||
"integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "7.13.1",
|
||||
"@typescript-eslint/utils": "7.13.1",
|
||||
"@typescript-eslint/typescript-estree": "7.14.1",
|
||||
"@typescript-eslint/utils": "7.14.1",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
@@ -5267,9 +5266,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz",
|
||||
"integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz",
|
||||
"integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@@ -5280,13 +5279,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz",
|
||||
"integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz",
|
||||
"integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.13.1",
|
||||
"@typescript-eslint/visitor-keys": "7.13.1",
|
||||
"@typescript-eslint/types": "7.14.1",
|
||||
"@typescript-eslint/visitor-keys": "7.14.1",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -5308,15 +5307,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz",
|
||||
"integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz",
|
||||
"integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "7.13.1",
|
||||
"@typescript-eslint/types": "7.13.1",
|
||||
"@typescript-eslint/typescript-estree": "7.13.1"
|
||||
"@typescript-eslint/scope-manager": "7.14.1",
|
||||
"@typescript-eslint/types": "7.14.1",
|
||||
"@typescript-eslint/typescript-estree": "7.14.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@@ -5330,12 +5329,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "7.13.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz",
|
||||
"integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==",
|
||||
"version": "7.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz",
|
||||
"integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.13.1",
|
||||
"@typescript-eslint/types": "7.14.1",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
@@ -8216,9 +8215,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "11.2.11",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.11.tgz",
|
||||
"integrity": "sha512-n+ozoEzgJu/2h9NoQMokF+CwNqIRVyuRC4RwMPwklfrrTjbVV32k9uBIgqYAwn7Jfpt5LuDVCtT57MWz1FbaLw==",
|
||||
"version": "11.2.12",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.12.tgz",
|
||||
"integrity": "sha512-lCjkV4nA9rWOy2bhR4RZzkp2xpB++kFmUZ6D44V9VQaxk+JDmbDd5lq+u58DjJIIllE8AZEXp9OG/TyDN4FB/w==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
@@ -10553,9 +10552,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jose": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.4.1.tgz",
|
||||
"integrity": "sha512-U6QajmpV/nhL9SyfAewo000fkiRQ+Yd2H0lBxJJ9apjpOgkOcBQJWOrMo917lxLptdS/n/o/xPzMkXhF46K8hQ==",
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jose/-/jose-5.5.0.tgz",
|
||||
"integrity": "sha512-DUPr/1kYXbuqYpkCj9r66+B4SGCKXCLQ5ZbKCgmn4sJveJqcwNqWtAR56u4KPmpXjrmBO2uNuLdEAEiqIhFNBg==",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/panva"
|
||||
}
|
||||
@@ -13188,12 +13187,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.23.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
|
||||
"integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
|
||||
"license": "MIT",
|
||||
"version": "6.24.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.0.tgz",
|
||||
"integrity": "sha512-sQrgJ5bXk7vbcC4BxQxeNa5UmboFm35we1AFK0VvQaz9g0LzxEIuLOhHIoZ8rnu9BO21ishGeL9no1WB76W/eg==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.16.1"
|
||||
"@remix-run/router": "1.17.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
@@ -13203,13 +13201,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.23.1",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
|
||||
"integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
|
||||
"license": "MIT",
|
||||
"version": "6.24.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.0.tgz",
|
||||
"integrity": "sha512-960sKuau6/yEwS8e+NVEidYQb1hNjAYM327gjEyXlc6r3Skf2vtwuJ2l7lssdegD2YjoKG5l8MsVyeTDlVeY8g==",
|
||||
"dependencies": {
|
||||
"@remix-run/router": "1.16.1",
|
||||
"react-router": "6.23.1"
|
||||
"@remix-run/router": "1.17.0",
|
||||
"react-router": "6.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"@xterm/xterm": "^5.4.0",
|
||||
"clsx": "^2.1.1",
|
||||
"eslint-config-airbnb-typescript": "^18.0.0",
|
||||
"framer-motion": "^11.2.11",
|
||||
"framer-motion": "^11.2.12",
|
||||
"i18next": "^23.11.5",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"i18next-http-backend": "^2.5.2",
|
||||
"jose": "^5.4.1",
|
||||
"jose": "^5.5.0",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
@@ -30,7 +30,7 @@
|
||||
"react-icons": "^5.2.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-router-dom": "^6.24.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"vite": "^5.3.1",
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "npm run make-i18n && vite",
|
||||
"build": "tsc && vite build",
|
||||
"build": "npm run make-i18n && tsc && vite build",
|
||||
"test": "vitest run",
|
||||
"dev_wsl": "VITE_WATCH_USE_POLLING=true vite",
|
||||
"preview": "vite preview",
|
||||
@@ -64,13 +64,13 @@
|
||||
"@testing-library/jest-dom": "^6.4.6",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/node": "^20.14.9",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-highlight": "^0.12.8",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.14.1",
|
||||
"@typescript-eslint/parser": "^7.14.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
|
||||
BIN
frontend/public/beep.wav
Normal file
BIN
frontend/public/beep.wav
Normal file
Binary file not shown.
@@ -11,6 +11,7 @@ import SettingsModal from "#/components/modals/settings/SettingsModal";
|
||||
import "./App.css";
|
||||
import AgentControlBar from "./components/AgentControlBar";
|
||||
import AgentStatusBar from "./components/AgentStatusBar";
|
||||
import VolumeIcon from "./components/VolumeIcon";
|
||||
import Terminal from "./components/terminal/Terminal";
|
||||
import Session from "#/services/session";
|
||||
import { getToken } from "#/services/auth";
|
||||
@@ -27,11 +28,17 @@ function Controls({ setSettingOpen }: Props): JSX.Element {
|
||||
<AgentControlBar />
|
||||
</div>
|
||||
<AgentStatusBar />
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-all"
|
||||
onClick={() => setSettingOpen(true)}
|
||||
>
|
||||
<CogTooth />
|
||||
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<div style={{ marginRight: "8px" }}>
|
||||
<VolumeIcon />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-all"
|
||||
onClick={() => setSettingOpen(true)}
|
||||
>
|
||||
<CogTooth />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,6 +15,7 @@ const IgnoreTaskStateMap: { [k: string]: AgentState[] } = {
|
||||
AgentState.PAUSED,
|
||||
AgentState.STOPPED,
|
||||
AgentState.FINISHED,
|
||||
AgentState.REJECTED,
|
||||
AgentState.AWAITING_USER_INPUT,
|
||||
],
|
||||
[AgentState.RUNNING]: [
|
||||
@@ -22,6 +23,7 @@ const IgnoreTaskStateMap: { [k: string]: AgentState[] } = {
|
||||
AgentState.RUNNING,
|
||||
AgentState.STOPPED,
|
||||
AgentState.FINISHED,
|
||||
AgentState.REJECTED,
|
||||
AgentState.AWAITING_USER_INPUT,
|
||||
],
|
||||
[AgentState.STOPPED]: [AgentState.INIT, AgentState.STOPPED],
|
||||
@@ -48,10 +50,18 @@ function ActionButton({
|
||||
<button
|
||||
onClick={() => handleAction(action)}
|
||||
disabled={isDisabled}
|
||||
className={`${large ? "rounded-full bg-neutral-800 p-3" : ""} hover:opacity-80 transition-all`}
|
||||
className={`
|
||||
relative overflow-visible cursor-default hover:cursor-pointer group
|
||||
disabled:cursor-not-allowed disabled:opacity-60
|
||||
${large ? "rounded-full bg-neutral-800 p-3" : ""}
|
||||
transition-all duration-300 ease-in-out
|
||||
`}
|
||||
type="button"
|
||||
>
|
||||
{children}
|
||||
<span className="relative z-10 group-hover:filter group-hover:drop-shadow-[0_0_5px_rgba(255,64,0,0.4)]">
|
||||
{children}
|
||||
</span>
|
||||
<span className="absolute -inset-[5px] border-2 border-red-400/40 rounded-full opacity-0 group-hover:opacity-100 transition-opacity duration-300 ease-in-out" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSelector } from "react-redux";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
import { RootState } from "#/store";
|
||||
import AgentState from "#/types/AgentState";
|
||||
import beep from "#/utils/beep";
|
||||
|
||||
enum IndicatorColor {
|
||||
BLUE = "bg-blue-500",
|
||||
@@ -49,6 +50,10 @@ function AgentStatusBar() {
|
||||
message: t(I18nKey.CHAT_INTERFACE$AGENT_FINISHED_MESSAGE),
|
||||
indicator: IndicatorColor.GREEN,
|
||||
},
|
||||
[AgentState.REJECTED]: {
|
||||
message: t(I18nKey.CHAT_INTERFACE$AGENT_REJECTED_MESSAGE),
|
||||
indicator: IndicatorColor.YELLOW,
|
||||
},
|
||||
[AgentState.ERROR]: {
|
||||
message: t(I18nKey.CHAT_INTERFACE$AGENT_ERROR_MESSAGE),
|
||||
indicator: IndicatorColor.RED,
|
||||
@@ -61,6 +66,16 @@ function AgentStatusBar() {
|
||||
// - Agent is thinking
|
||||
// - Agent is ready
|
||||
// - Agent is not available
|
||||
useEffect(() => {
|
||||
if (
|
||||
curAgentState === AgentState.AWAITING_USER_INPUT ||
|
||||
curAgentState === AgentState.ERROR ||
|
||||
curAgentState === AgentState.INIT
|
||||
) {
|
||||
if (document.cookie.indexOf("audio") !== -1) beep();
|
||||
}
|
||||
}, [curAgentState]);
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<div
|
||||
|
||||
29
frontend/src/components/VolumeIcon.tsx
Normal file
29
frontend/src/components/VolumeIcon.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import React, { useState } from "react";
|
||||
import { IoMdVolumeHigh, IoMdVolumeOff } from "react-icons/io";
|
||||
import beep from "#/utils/beep";
|
||||
|
||||
function VolumeIcon(): JSX.Element {
|
||||
const [isMuted, setIsMuted] = useState(true);
|
||||
|
||||
const toggleMute = () => {
|
||||
const cookieName = "audio";
|
||||
setIsMuted(!isMuted);
|
||||
if (!isMuted) {
|
||||
document.cookie = `${cookieName}=;`;
|
||||
} else {
|
||||
document.cookie = `${cookieName}=on;`;
|
||||
beep();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="cursor-pointer hover:opacity-80 transition-all"
|
||||
onClick={toggleMute}
|
||||
>
|
||||
{isMuted ? <IoMdVolumeOff size={23} /> : <IoMdVolumeHigh size={23} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default VolumeIcon;
|
||||
@@ -62,7 +62,7 @@ function ChatInput({ disabled = false, onSendMessage }: ChatInputProps) {
|
||||
? "cursor-not-allowed border-neutral-400 text-neutral-400"
|
||||
: "hover:bg-neutral-500 ",
|
||||
)}
|
||||
aria-label="Send message"
|
||||
aria-label={t(I18nKey.CHAT_INTERFACE$TOOLTIP_SEND_MESSAGE)}
|
||||
>
|
||||
<VscArrowUp />
|
||||
</button>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// frontend/src/components/chat/ChatInterface.tsx
|
||||
import React, { useRef } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { IoMdChatbubbles } from "react-icons/io";
|
||||
@@ -8,6 +9,7 @@ import { FaRegThumbsDown, FaRegThumbsUp } from "react-icons/fa";
|
||||
import { useDisclosure } from "@nextui-org/react";
|
||||
import ChatInput from "./ChatInput";
|
||||
import Chat from "./Chat";
|
||||
import TypingIndicator from "./TypingIndicator";
|
||||
import { RootState } from "#/store";
|
||||
import AgentState from "#/types/AgentState";
|
||||
import { sendChatMessage } from "#/services/chatService";
|
||||
@@ -127,19 +129,27 @@ function ChatInterface() {
|
||||
|
||||
<div className="relative">
|
||||
<div className="absolute bottom-2 left-0 right-0 flex items-center justify-center">
|
||||
{!hitBottom &&
|
||||
ScrollButton({
|
||||
onClick: scrollDomToBottom,
|
||||
icon: <VscArrowDown className="inline mr-2 w-3 h-3" />,
|
||||
label: t(I18nKey.CHAT_INTERFACE$TO_BOTTOM),
|
||||
})}
|
||||
{curAgentState === AgentState.AWAITING_USER_INPUT &&
|
||||
hitBottom &&
|
||||
ScrollButton({
|
||||
onClick: handleSendContinueMsg,
|
||||
icon: <RiArrowRightDoubleLine className="inline mr-2 w-3 h-3" />,
|
||||
label: t(I18nKey.CHAT_INTERFACE$INPUT_CONTINUE_MESSAGE),
|
||||
})}
|
||||
{!hitBottom && (
|
||||
<ScrollButton
|
||||
onClick={scrollDomToBottom}
|
||||
icon={<VscArrowDown className="inline mr-2 w-3 h-3" />}
|
||||
label={t(I18nKey.CHAT_INTERFACE$TO_BOTTOM)}
|
||||
/>
|
||||
)}
|
||||
{hitBottom && (
|
||||
<>
|
||||
{curAgentState === AgentState.AWAITING_USER_INPUT && (
|
||||
<ScrollButton
|
||||
onClick={handleSendContinueMsg}
|
||||
icon={
|
||||
<RiArrowRightDoubleLine className="inline mr-2 w-3 h-3" />
|
||||
}
|
||||
label={t(I18nKey.CHAT_INTERFACE$INPUT_CONTINUE_MESSAGE)}
|
||||
/>
|
||||
)}
|
||||
{curAgentState === AgentState.RUNNING && <TypingIndicator />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{feedbackShared !== messages.length && messages.length > 3 && (
|
||||
|
||||
@@ -2,8 +2,10 @@ import React, { useState } from "react";
|
||||
import Markdown from "react-markdown";
|
||||
import { FaClipboard } from "react-icons/fa";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { code } from "../markdown/code";
|
||||
import toast from "#/utils/toast";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
|
||||
interface MessageProps {
|
||||
message: Message;
|
||||
@@ -18,14 +20,18 @@ function ChatMessage({ message }: MessageProps) {
|
||||
message.sender === "user" ? "bg-neutral-700 self-end" : "bg-neutral-500",
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const copyToClipboard = () => {
|
||||
navigator.clipboard
|
||||
.writeText(message.content)
|
||||
.then(() => {
|
||||
toast.info("Message copied to clipboard!");
|
||||
toast.info(t(I18nKey.CHAT_INTERFACE$CHAT_MESSAGE_COPIED));
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error("copy-error", `Failed to copy message: ${error}`);
|
||||
.catch(() => {
|
||||
toast.error(
|
||||
"copy-error",
|
||||
t(I18nKey.CHAT_INTERFACE$CHAT_MESSAGE_COPY_FAILED),
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -40,7 +46,7 @@ function ChatMessage({ message }: MessageProps) {
|
||||
<button
|
||||
onClick={copyToClipboard}
|
||||
className="absolute top-1 right-1 p-1 bg-neutral-600 rounded hover:bg-neutral-500 transition-opacity opacity-75 hover:opacity-100"
|
||||
aria-label="Copy message"
|
||||
aria-label={t(I18nKey.CHAT_INTERFACE$TOOLTIP_COPY_MESSAGE)}
|
||||
type="button"
|
||||
>
|
||||
<FaClipboard />
|
||||
|
||||
22
frontend/src/components/chat/TypingIndicator.tsx
Normal file
22
frontend/src/components/chat/TypingIndicator.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
|
||||
function TypingIndicator(): React.ReactElement {
|
||||
return (
|
||||
<div className="flex items-center space-x-1.5 bg-neutral-700 px-3 py-1.5 rounded-full">
|
||||
<span
|
||||
className="w-1.5 h-1.5 bg-gray-400 rounded-full animate-[bounce_0.5s_infinite] translate-y-[-2px]"
|
||||
style={{ animationDelay: "0ms" }}
|
||||
/>
|
||||
<span
|
||||
className="w-1.5 h-1.5 bg-gray-400 rounded-full animate-[bounce_0.5s_infinite] translate-y-[-2px]"
|
||||
style={{ animationDelay: "75ms" }}
|
||||
/>
|
||||
<span
|
||||
className="w-1.5 h-1.5 bg-gray-400 rounded-full animate-[bounce_0.5s_infinite] translate-y-[-2px]"
|
||||
style={{ animationDelay: "150ms" }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default TypingIndicator;
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
} from "react-icons/io";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { IoFileTray } from "react-icons/io5";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import AgentState from "#/types/AgentState";
|
||||
import { setRefreshID } from "#/state/codeSlice";
|
||||
@@ -15,6 +16,7 @@ import IconButton from "../IconButton";
|
||||
import ExplorerTree from "./ExplorerTree";
|
||||
import toast from "#/utils/toast";
|
||||
import { RootState } from "#/store";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
|
||||
interface ExplorerActionsProps {
|
||||
onRefresh: () => void;
|
||||
@@ -92,7 +94,7 @@ function FileExplorer() {
|
||||
const { curAgentState } = useSelector((state: RootState) => state.agent);
|
||||
const fileInputRef = React.useRef<HTMLInputElement | null>(null);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { t } = useTranslation();
|
||||
const selectFileInput = () => {
|
||||
fileInputRef.current?.click(); // Trigger the file browser
|
||||
};
|
||||
@@ -113,7 +115,7 @@ function FileExplorer() {
|
||||
await uploadFiles(toAdd);
|
||||
await refreshWorkspace();
|
||||
} catch (error) {
|
||||
toast.error("ws", "Error uploading file");
|
||||
toast.error("ws", t(I18nKey.EXPLORER$UPLOAD_ERROR_MESSAGE));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,7 +160,9 @@ function FileExplorer() {
|
||||
className="z-10 absolute flex flex-col justify-center items-center bg-black top-0 bottom-0 left-0 right-0 opacity-65"
|
||||
>
|
||||
<IoFileTray size={32} />
|
||||
<p className="font-bold text-xl">Drop Files Here</p>
|
||||
<p className="font-bold text-xl">
|
||||
{t(I18nKey.EXPLORER$LABEL_DROP_FILES)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
@@ -176,7 +180,7 @@ function FileExplorer() {
|
||||
>
|
||||
{!isHidden && (
|
||||
<div className="ml-1 text-neutral-300 font-bold text-sm">
|
||||
Workspace
|
||||
{t(I18nKey.EXPLORER$LABEL_WORKSPACE)}
|
||||
</div>
|
||||
)}
|
||||
<ExplorerActions
|
||||
|
||||
@@ -58,7 +58,7 @@ function SettingsModal({ isOpen, onOpenChange }: SettingsProps) {
|
||||
setModels(await fetchModels());
|
||||
setAgents(await fetchAgents());
|
||||
} catch (error) {
|
||||
toast.error("settings", "Failed to fetch models and agents");
|
||||
toast.error("settings", t(I18nKey.CONFIGURATION$ERROR_FETCH_MODELS));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -268,6 +268,46 @@
|
||||
"en": "Please stop the agent before editing these settings.",
|
||||
"de": "Bitte beenden Sie den Agenten vor der Bearbeitung der Einstellungen."
|
||||
},
|
||||
"CONFIGURATION$ERROR_FETCH_MODELS": {
|
||||
"en": "Failed to fetch models and agents",
|
||||
"zh-CN": "获取模型和智能体失败",
|
||||
"de": "Fehler beim Abrufen der Modelle und Agenten"
|
||||
},
|
||||
"SESSION$SERVER_CONNECTED_MESSAGE": {
|
||||
"en": "Connected to server",
|
||||
"zh-CN": "已连接到服务器",
|
||||
"de": "Verbindung zum Server hergestellt"
|
||||
},
|
||||
"SESSION$SESSION_HANDLING_ERROR_MESSAGE": {
|
||||
"en": "Error handling message",
|
||||
"zh-CN": "处理消息时发生错误",
|
||||
"de": "Fehler beim Verarbeiten der Nachricht"
|
||||
},
|
||||
"SESSION$SESSION_CONNECTION_ERROR_MESSAGE": {
|
||||
"en": "Error connecting to session",
|
||||
"zh-CN": "连接到会话时发生错误",
|
||||
"de": "Verbindung zur Sitzung fehlgeschlagen"
|
||||
},
|
||||
"SESSION$SOCKET_NOT_INITIALIZED_ERROR_MESSAGE": {
|
||||
"en": "Socket not initialized",
|
||||
"zh-CN": "Socket 未初始化",
|
||||
"de": "Socket nicht initialisiert"
|
||||
},
|
||||
"EXPLORER$UPLOAD_ERROR_MESSAGE": {
|
||||
"en": "Error uploading file",
|
||||
"zh-CN": "上传文件时发生错误",
|
||||
"de": "Fehler beim Hochladen der Datei"
|
||||
},
|
||||
"EXPLORER$LABEL_DROP_FILES": {
|
||||
"en": "Drop files here",
|
||||
"zh-CN": "将文件拖到这里",
|
||||
"de": "Dateien hier ablegen"
|
||||
},
|
||||
"EXPLORER$LABEL_WORKSPACE": {
|
||||
"en": "Workspace",
|
||||
"zh-CN": "工作区",
|
||||
"de": "Arbeitsbereich"
|
||||
},
|
||||
"LOAD_SESSION$MODAL_TITLE": {
|
||||
"en": "Return to existing session?",
|
||||
"de": "Zurück zu vorhandener Sitzung?",
|
||||
@@ -357,6 +397,11 @@
|
||||
"de": "Agent hat die Aufgabe erledigt.",
|
||||
"zh-CN": "智能体已完成任务"
|
||||
},
|
||||
"CHAT_INTERFACE$AGENT_REJECTED_MESSAGE": {
|
||||
"en": "Agent has rejected the task.",
|
||||
"de": "Agent hat die Aufgabe abgelehnt.",
|
||||
"zh-CN": "智能体拒绝任务"
|
||||
},
|
||||
"CHAT_INTERFACE$AGENT_ERROR_MESSAGE": {
|
||||
"en": "Agent encountered an error.",
|
||||
"de": "Agent ist auf einen Fehler gelaufen.",
|
||||
@@ -394,6 +439,26 @@
|
||||
"ar": "إرسال",
|
||||
"fr": "Envoyer"
|
||||
},
|
||||
"CHAT_INTERFACE$CHAT_MESSAGE_COPIED": {
|
||||
"en": "Message copied to clipboard",
|
||||
"zh-CN": "消息已复制到剪贴板",
|
||||
"de": "Nachricht in die Zwischenablage kopiert"
|
||||
},
|
||||
"CHAT_INTERFACE$CHAT_MESSAGE_COPY_FAILED": {
|
||||
"en": "Failed to copy message to clipboard",
|
||||
"zh-CN": "复制消息到剪贴板失败",
|
||||
"de": "Nachricht konnte nicht in die Zwischenablage kopiert werden"
|
||||
},
|
||||
"CHAT_INTERFACE$TOOLTIP_COPY_MESSAGE": {
|
||||
"en": "Copy message",
|
||||
"zh-CN": "复制消息",
|
||||
"de": "Nachricht kopieren"
|
||||
},
|
||||
"CHAT_INTERFACE$TOOLTIP_SEND_MESSAGE": {
|
||||
"en": "Send message",
|
||||
"zh-CN": "发送消息",
|
||||
"de": "Nachricht senden"
|
||||
},
|
||||
"CHAT_INTERFACE$INITIAL_MESSAGE": {
|
||||
"en": "Hi! I'm OpenDevin, an AI Software Engineer. What would you like to build with me today?",
|
||||
"zh-CN": "你好!我是 OpenDevin,一名 AI 软件工程师。今天想和我一起编写什么程序呢?",
|
||||
|
||||
@@ -36,6 +36,12 @@ const messageActions = {
|
||||
[ActionType.FINISH]: (message: ActionMessage) => {
|
||||
store.dispatch(addAssistantMessage(message.message));
|
||||
},
|
||||
[ActionType.REJECT]: (message: ActionMessage) => {
|
||||
store.dispatch(addAssistantMessage(message.message));
|
||||
},
|
||||
[ActionType.DELEGATE]: (message: ActionMessage) => {
|
||||
store.dispatch(addAssistantMessage(message.message));
|
||||
},
|
||||
[ActionType.RUN]: (message: ActionMessage) => {
|
||||
if (message.args.thought) {
|
||||
store.dispatch(addAssistantMessage(message.args.thought));
|
||||
|
||||
@@ -27,6 +27,12 @@ export function handleObservationMessage(message: ObservationMessage) {
|
||||
case ObservationType.AGENT_STATE_CHANGED:
|
||||
store.dispatch(changeAgentState(message.extras.agent_state));
|
||||
break;
|
||||
case ObservationType.DELEGATE:
|
||||
// TODO: better UI for delegation result (#2309)
|
||||
if (message.content) {
|
||||
store.dispatch(addAssistantMessage(message.content));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
store.dispatch(addAssistantMessage(message.message));
|
||||
break;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import i18next from "i18next";
|
||||
import toast from "#/utils/toast";
|
||||
import { handleAssistantMessage } from "./actions";
|
||||
import { getToken, setToken, clearToken } from "./auth";
|
||||
import ActionType from "#/types/ActionType";
|
||||
import { getSettings } from "./settings";
|
||||
import { I18nKey } from "#/i18n/declaration";
|
||||
|
||||
const translate = (key: I18nKey) => i18next.t(key);
|
||||
|
||||
class Session {
|
||||
private static _socket: WebSocket | null = null;
|
||||
@@ -66,10 +70,12 @@ class Session {
|
||||
|
||||
private static _setupSocket(): void {
|
||||
if (!Session._socket) {
|
||||
throw new Error("Socket is not initialized.");
|
||||
throw new Error(
|
||||
translate(I18nKey.SESSION$SOCKET_NOT_INITIALIZED_ERROR_MESSAGE),
|
||||
);
|
||||
}
|
||||
Session._socket.onopen = (e) => {
|
||||
toast.success("ws", "Connected to server.");
|
||||
toast.success("ws", translate(I18nKey.SESSION$SERVER_CONNECTED_MESSAGE));
|
||||
Session._connecting = false;
|
||||
Session._initializeAgent();
|
||||
Session.callbacks.open?.forEach((callback) => {
|
||||
@@ -84,7 +90,10 @@ class Session {
|
||||
Session._history.push(data);
|
||||
} catch (err) {
|
||||
// TODO: report the error
|
||||
toast.error("ws", "Error handing message.");
|
||||
toast.error(
|
||||
"ws",
|
||||
translate(I18nKey.SESSION$SESSION_HANDLING_ERROR_MESSAGE),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (data.error && data.error_code === 401) {
|
||||
@@ -101,8 +110,10 @@ class Session {
|
||||
};
|
||||
|
||||
Session._socket.onerror = () => {
|
||||
const msg = "Connection failed. Retry...";
|
||||
toast.error("ws", msg);
|
||||
toast.error(
|
||||
"ws",
|
||||
translate(I18nKey.SESSION$SESSION_CONNECTION_ERROR_MESSAGE),
|
||||
);
|
||||
};
|
||||
|
||||
Session._socket.onclose = () => {
|
||||
@@ -135,15 +146,19 @@ class Session {
|
||||
return;
|
||||
}
|
||||
if (!Session.isConnected()) {
|
||||
throw new Error("Not connected to server.");
|
||||
throw new Error(
|
||||
translate(I18nKey.SESSION$SESSION_CONNECTION_ERROR_MESSAGE),
|
||||
);
|
||||
}
|
||||
|
||||
if (Session.isConnected()) {
|
||||
Session._socket?.send(message);
|
||||
Session._history.push(JSON.parse(message));
|
||||
} else {
|
||||
const msg = "Connection failed. Retry...";
|
||||
toast.error("ws", msg);
|
||||
toast.error(
|
||||
"ws",
|
||||
translate(I18nKey.SESSION$SESSION_CONNECTION_ERROR_MESSAGE),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ enum ActionType {
|
||||
// Interact with the browser instance.
|
||||
BROWSE_INTERACTIVE = "browse_interactive",
|
||||
|
||||
// Delegate a (sub)task to another agent.
|
||||
DELEGATE = "delegate",
|
||||
|
||||
// Searches long-term memory.
|
||||
RECALL = "recall",
|
||||
|
||||
@@ -33,6 +36,9 @@ enum ActionType {
|
||||
// use the finish action to stop working.
|
||||
FINISH = "finish",
|
||||
|
||||
// Reject a request from user or another agent.
|
||||
REJECT = "reject",
|
||||
|
||||
// Adds a task to the plan.
|
||||
ADD_TASK = "add_task",
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ enum AgentState {
|
||||
PAUSED = "paused",
|
||||
STOPPED = "stopped",
|
||||
FINISHED = "finished",
|
||||
REJECTED = "rejected",
|
||||
ERROR = "error",
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ enum ObservationType {
|
||||
|
||||
// Agent state has changed
|
||||
AGENT_STATE_CHANGED = "agent_state_changed",
|
||||
|
||||
// Delegate result
|
||||
DELEGATE = "delegate",
|
||||
}
|
||||
|
||||
export default ObservationType;
|
||||
|
||||
9
frontend/src/utils/beep.tsx
Normal file
9
frontend/src/utils/beep.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
const beep = () => {
|
||||
const snd = new Audio("/beep.wav");
|
||||
snd.addEventListener("canplaythrough", () => snd.play());
|
||||
snd.addEventListener("error", (e) =>
|
||||
console.error("Audio file could not be loaded", e),
|
||||
);
|
||||
};
|
||||
|
||||
export default beep;
|
||||
@@ -281,7 +281,14 @@ class AgentController:
|
||||
self.delegateAction = None
|
||||
|
||||
# update delegate result observation
|
||||
obs: Observation = AgentDelegateObservation(outputs=outputs, content='')
|
||||
# TODO: replace this with AI-generated summary (#2395)
|
||||
formatted_output = ', '.join(
|
||||
f'{key}: {value}' for key, value in outputs.items()
|
||||
)
|
||||
content = f'Delegate agent finishes task with {formatted_output}'
|
||||
obs: Observation = AgentDelegateObservation(
|
||||
outputs=outputs, content=content
|
||||
)
|
||||
self.event_stream.add_event(obs, EventSource.AGENT)
|
||||
return
|
||||
|
||||
|
||||
@@ -78,7 +78,10 @@ class AgentRejectAction(Action):
|
||||
|
||||
@property
|
||||
def message(self) -> str:
|
||||
return 'Task is rejected by the agent.'
|
||||
msg: str = 'Task is rejected by the agent.'
|
||||
if 'reason' in self.outputs:
|
||||
msg += ' Reason: ' + self.outputs['reason']
|
||||
return msg
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -17,11 +17,12 @@ def generate_dockerfile_content(base_image: str) -> str:
|
||||
'RUN apt update && apt install -y openssh-server wget sudo net-tools iproute2\n'
|
||||
'RUN mkdir -p -m0755 /var/run/sshd\n'
|
||||
'RUN mkdir -p /opendevin && mkdir -p /opendevin/logs && chmod 777 /opendevin/logs\n'
|
||||
'RUN wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"\n'
|
||||
'RUN bash Miniforge3-$(uname)-$(uname -m).sh -b -p /opendevin/miniforge3\n'
|
||||
'RUN bash -c ". /opendevin/miniforge3/etc/profile.d/conda.sh && conda config --set changeps1 False && conda config --append channels conda-forge"\n'
|
||||
'RUN echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> ~/.bashrc\n'
|
||||
'RUN echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> /opendevin/bash.bashrc\n'
|
||||
'RUN { test -d /opendevin/miniforge3 && echo "/opendevin/miniforge3 already in base image"; } || { \\\n'
|
||||
' wget "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" && \\\n'
|
||||
' bash Miniforge3-$(uname)-$(uname -m).sh -b -p /opendevin/miniforge3 && \\\n'
|
||||
' bash -c ". /opendevin/miniforge3/etc/profile.d/conda.sh && conda config --set changeps1 False && conda config --append channels conda-forge" && \\\n'
|
||||
' echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> ~/.bashrc && \\\n'
|
||||
' echo "export PATH=/opendevin/miniforge3/bin:$PATH" >> /opendevin/bash.bashrc; }\n'
|
||||
).strip()
|
||||
return dockerfile_content
|
||||
|
||||
|
||||
96
poetry.lock
generated
96
poetry.lock
generated
@@ -416,17 +416,17 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "boto3"
|
||||
version = "1.34.131"
|
||||
version = "1.34.133"
|
||||
description = "The AWS SDK for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "boto3-1.34.131-py3-none-any.whl", hash = "sha256:05e388cb937e82be70bfd7eb0c84cf8011ff35cf582a593873ac21675268683b"},
|
||||
{file = "boto3-1.34.131.tar.gz", hash = "sha256:dab8f72a6c4e62b4fd70da09e08a6b2a65ea2115b27dd63737142005776ef216"},
|
||||
{file = "boto3-1.34.133-py3-none-any.whl", hash = "sha256:da7e78c03270be872ad78301892396ffea56647efcb2c3a8621ef46a905541ab"},
|
||||
{file = "boto3-1.34.133.tar.gz", hash = "sha256:7071f8ce1f09113ca5630860fd590464e6325a4df55faae83c956225941016fc"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.34.131,<1.35.0"
|
||||
botocore = ">=1.34.133,<1.35.0"
|
||||
jmespath = ">=0.7.1,<2.0.0"
|
||||
s3transfer = ">=0.10.0,<0.11.0"
|
||||
|
||||
@@ -435,13 +435,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
|
||||
|
||||
[[package]]
|
||||
name = "botocore"
|
||||
version = "1.34.131"
|
||||
version = "1.34.133"
|
||||
description = "Low-level, data-driven core of boto 3."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "botocore-1.34.131-py3-none-any.whl", hash = "sha256:13b011d7b206ce00727dcee26548fa3b550db9046d5a0e90ac25a6e6c8fde6ef"},
|
||||
{file = "botocore-1.34.131.tar.gz", hash = "sha256:502ddafe1d627fcf1e4c007c86454e5dd011dba7c58bd8e8a5368a79f3e387dc"},
|
||||
{file = "botocore-1.34.133-py3-none-any.whl", hash = "sha256:f269dad8e17432d2527b97ed9f1fd30ec8dc705f8b818957170d1af484680ef2"},
|
||||
{file = "botocore-1.34.133.tar.gz", hash = "sha256:5ea609aa4831a6589e32eef052a359ad8d7311733b4d86a9d35dab4bd3ec80ff"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2771,13 +2771,13 @@ types-tqdm = "*"
|
||||
|
||||
[[package]]
|
||||
name = "litellm"
|
||||
version = "1.40.25"
|
||||
version = "1.40.27"
|
||||
description = "Library to easily interface with LLM API providers"
|
||||
optional = false
|
||||
python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8"
|
||||
files = [
|
||||
{file = "litellm-1.40.25-py3-none-any.whl", hash = "sha256:94bff834ca92338223bed474fe614ab30a706681a596e1e38ea60fe8a574a7a8"},
|
||||
{file = "litellm-1.40.25.tar.gz", hash = "sha256:437d515274b8cc901d527fbf14ce46599700225f4e1dae2d19b46b446e402b08"},
|
||||
{file = "litellm-1.40.27-py3-none-any.whl", hash = "sha256:f6906e5260d784e7e31d579f5b28545e87517268cb96dd0dcaf31e4c5d34073f"},
|
||||
{file = "litellm-1.40.27.tar.gz", hash = "sha256:a13a04168be5a8e52d43c34c2e657ca2521da61039ac39a17abc233a1875923f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -3823,38 +3823,38 @@ dill = ">=0.3.8"
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
version = "1.10.0"
|
||||
version = "1.10.1"
|
||||
description = "Optional static typing for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"},
|
||||
{file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"},
|
||||
{file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"},
|
||||
{file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"},
|
||||
{file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"},
|
||||
{file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"},
|
||||
{file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"},
|
||||
{file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"},
|
||||
{file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"},
|
||||
{file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"},
|
||||
{file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"},
|
||||
{file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"},
|
||||
{file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"},
|
||||
{file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"},
|
||||
{file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"},
|
||||
{file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"},
|
||||
{file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"},
|
||||
{file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"},
|
||||
{file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"},
|
||||
{file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"},
|
||||
{file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"},
|
||||
{file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"},
|
||||
{file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"},
|
||||
{file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"},
|
||||
{file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"},
|
||||
{file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"},
|
||||
{file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"},
|
||||
{file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"},
|
||||
{file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"},
|
||||
{file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"},
|
||||
{file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"},
|
||||
{file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"},
|
||||
{file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"},
|
||||
{file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"},
|
||||
{file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"},
|
||||
{file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"},
|
||||
{file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"},
|
||||
{file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"},
|
||||
{file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"},
|
||||
{file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"},
|
||||
{file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"},
|
||||
{file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"},
|
||||
{file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"},
|
||||
{file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"},
|
||||
{file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"},
|
||||
{file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"},
|
||||
{file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"},
|
||||
{file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"},
|
||||
{file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"},
|
||||
{file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"},
|
||||
{file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"},
|
||||
{file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"},
|
||||
{file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"},
|
||||
{file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -4190,13 +4190,13 @@ sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.35.3"
|
||||
version = "1.35.4"
|
||||
description = "The official Python library for the openai API"
|
||||
optional = false
|
||||
python-versions = ">=3.7.1"
|
||||
files = [
|
||||
{file = "openai-1.35.3-py3-none-any.whl", hash = "sha256:7b26544cef80f125431c073ffab3811d2421fbb9e30d3bd5c2436aba00b042d5"},
|
||||
{file = "openai-1.35.3.tar.gz", hash = "sha256:d6177087f150b381d49499be782d764213fdf638d391b29ca692b84dd675a389"},
|
||||
{file = "openai-1.35.4-py3-none-any.whl", hash = "sha256:894b79c485fae2df3a6b68ceb570730e5a480c08bccc32a412cf3be2d4eb1384"},
|
||||
{file = "openai-1.35.4.tar.gz", hash = "sha256:b58a0d6257c5c86e85b9b2f43e6eed04ada616560df9da0dca6697d06845e7c8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -5598,13 +5598,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "reportlab"
|
||||
version = "4.2.0"
|
||||
version = "4.2.2"
|
||||
description = "The Reportlab Toolkit"
|
||||
optional = false
|
||||
python-versions = "<4,>=3.7"
|
||||
files = [
|
||||
{file = "reportlab-4.2.0-py3-none-any.whl", hash = "sha256:53630f9d25a7938def3e6a93d723b72a7a5921d34d23cf7a0930adeb2cb0e6c1"},
|
||||
{file = "reportlab-4.2.0.tar.gz", hash = "sha256:474fb28d63431a5d47d75c90d580393050df7d491a09c7877df3291a2e9f6d0a"},
|
||||
{file = "reportlab-4.2.2-py3-none-any.whl", hash = "sha256:927616931637e2f13e2ee3b3b6316d7a07803170e258621cff7d138bde17fbb5"},
|
||||
{file = "reportlab-4.2.2.tar.gz", hash = "sha256:765eecbdd68491c56947e29c38b8b69b834ee5dbbdd2fb7409f08ebdebf04428"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -6370,13 +6370,13 @@ mpmath = ">=1.1.0,<1.4.0"
|
||||
|
||||
[[package]]
|
||||
name = "tenacity"
|
||||
version = "8.4.1"
|
||||
version = "8.4.2"
|
||||
description = "Retry code until it succeeds"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tenacity-8.4.1-py3-none-any.whl", hash = "sha256:28522e692eda3e1b8f5e99c51464efcc0b9fc86933da92415168bc1c4e2308fa"},
|
||||
{file = "tenacity-8.4.1.tar.gz", hash = "sha256:54b1412b878ddf7e1f1577cd49527bad8cdef32421bd599beac0c6c3f10582fd"},
|
||||
{file = "tenacity-8.4.2-py3-none-any.whl", hash = "sha256:9e6f7cf7da729125c7437222f8a522279751cdfbe6b67bfe64f75d3a348661b2"},
|
||||
{file = "tenacity-8.4.2.tar.gz", hash = "sha256:cd80a53a79336edba8489e767f729e4f391c896956b57140b5d7511a64bbd3ef"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -7737,4 +7737,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "34a62a0dedfa4ccee243811f066f45d4c6633e510e101e27b4fd31f91fb379bd"
|
||||
content-hash = "dba3c8c3812d657e413a57e3bd87ad6f80adadc08857948ff1fd6e1c62692ca7"
|
||||
|
||||
@@ -32,7 +32,7 @@ boto3 = "*"
|
||||
minio = "^7.2.7"
|
||||
gevent = "^24.2.1"
|
||||
pyarrow = "16.1.0" # transitive dependency, pinned here to avoid conflicts
|
||||
tenacity = "^8.4.1"
|
||||
tenacity = "^8.4.2"
|
||||
zope-interface = "6.4.post2"
|
||||
|
||||
[tool.poetry.group.llama-index.dependencies]
|
||||
@@ -46,7 +46,7 @@ llama-index-embeddings-ollama = "*"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
ruff = "0.4.10"
|
||||
mypy = "1.10.0"
|
||||
mypy = "1.10.1"
|
||||
pre-commit = "3.7.1"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
|
||||
@@ -70,7 +70,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[{"source": "user", "action": "message", "args": {"content": "Fix typos in bad.txt. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"source": "agent", "action": "delegate", "args": {"agent": "TypoFixerAgent", "inputs": {"task": "Fix typos in bad.txt"}, "thought": ""}}, {"source": "agent", "observation": "delegate", "content": "", "extras": {"outputs": {"summary": {"file": "bad.txt", "typos_fixed": [{"original": "typoo", "corrected": "typo"}, {"original": "mor", "corrected": "more"}]}}}}]
|
||||
[[{"source": "user", "action": "message", "args": {"content": "Fix typos in bad.txt. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "TypoFixerAgent", "inputs": {"task": "Fix typos in bad.txt"}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "Delegate agent finishes task with summary: {'file': 'bad.txt', 'typos_fixed': [{'original': 'typoo', 'corrected': 'typo'}, {'original': 'mor', 'corrected': 'more'}]}", "extras": {"outputs": {"summary": {"file": "bad.txt", "typos_fixed": [{"original": "typoo", "corrected": "typo"}, {"original": "mor", "corrected": "more"}]}}}}]]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it. If you
|
||||
cannot fix it, call the `reject` action.
|
||||
|
||||
@@ -70,7 +70,7 @@ as well as observations you've made. This only includes the MOST RECENT
|
||||
actions and observations--more may have happened before that.
|
||||
They are time-ordered, with your most recent action at the bottom.
|
||||
|
||||
[[{"source": "user", "action": "message", "args": {"content": "Write a git commit message for the current staging area. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "CommitWriterAgent", "inputs": {}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "", "extras": {"outputs": {"reason": "Not a valid git repository."}}}]]
|
||||
[[{"source": "user", "action": "message", "args": {"content": "Write a git commit message for the current staging area. Do not ask me for confirmation at any point.", "wait_for_response": false}}, {"observation": "null", "content": "", "extras": {}}], [{"source": "agent", "action": "delegate", "args": {"agent": "CommitWriterAgent", "inputs": {}, "thought": ""}}, {"observation": "null", "content": "", "extras": {}}], [{"action": "null", "args": {}}, {"source": "agent", "observation": "delegate", "content": "Delegate agent finishes task with reason: Not a valid git repository.", "extras": {"outputs": {"reason": "Not a valid git repository."}}}]]
|
||||
|
||||
If the last item in the history is an error, you should try to fix it. If you
|
||||
cannot fix it, call the `reject` action.
|
||||
|
||||
Reference in New Issue
Block a user