From 2b40a9294384fa8c5ed8d0513e6738ae73861d28 Mon Sep 17 00:00:00 2001 From: tofarr Date: Mon, 10 Feb 2025 18:07:40 +0000 Subject: [PATCH 1/9] Fix for issue where temp file is empty (#6669) --- .../impl/action_execution/action_execution_client.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openhands/runtime/impl/action_execution/action_execution_client.py b/openhands/runtime/impl/action_execution/action_execution_client.py index 7da8c21ff60d..7f1282447461 100644 --- a/openhands/runtime/impl/action_execution/action_execution_client.py +++ b/openhands/runtime/impl/action_execution/action_execution_client.py @@ -142,11 +142,13 @@ def copy_from(self, path: str) -> Path: stream=True, timeout=30, ) as response: - temp_file = tempfile.NamedTemporaryFile(delete=False) - for chunk in response.iter_content(chunk_size=8192): - if chunk: # filter out keep-alive new chunks - temp_file.write(chunk) - return Path(temp_file.name) + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + total_length = 0 + for chunk in response.iter_content(chunk_size=8192): + if chunk: # filter out keep-alive new chunks + total_length += len(chunk) + temp_file.write(chunk) + return Path(temp_file.name) except requests.Timeout: raise TimeoutError('Copy operation timed out') From 7860055f8cbf26e93c4bf9d971e175fa184bcaee Mon Sep 17 00:00:00 2001 From: Graham Neubig Date: Mon, 10 Feb 2025 13:53:39 -0500 Subject: [PATCH 2/9] fix: Normalize whitespace when comparing patch context lines (#6541) Co-authored-by: openhands --- openhands/resolver/patching/apply.py | 17 +++--- tests/unit/test_patch_whitespace.py | 79 ++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 tests/unit/test_patch_whitespace.py diff --git a/openhands/resolver/patching/apply.py b/openhands/resolver/patching/apply.py index 24f2266f56cf..aedc521a1cd6 100644 --- a/openhands/resolver/patching/apply.py +++ b/openhands/resolver/patching/apply.py @@ -94,12 +94,17 @@ def apply_diff(diff, text, reverse=False, use_patch=False): hunk=hunk, ) if lines[old - 1] != line: - raise HunkApplyException( - 'context line {n}, "{line}" does not match "{sl}"'.format( - n=old, line=line, sl=lines[old - 1] - ), - hunk=hunk, - ) + # Try to normalize whitespace by replacing multiple spaces with a single space + # This helps with patches that have different indentation levels + normalized_line = ' '.join(line.split()) + normalized_source = ' '.join(lines[old - 1].split()) + if normalized_line != normalized_source: + raise HunkApplyException( + 'context line {n}, "{line}" does not match "{sl}"'.format( + n=old, line=line, sl=lines[old - 1] + ), + hunk=hunk, + ) # for calculating the old line r = 0 diff --git a/tests/unit/test_patch_whitespace.py b/tests/unit/test_patch_whitespace.py new file mode 100644 index 000000000000..197584f4e723 --- /dev/null +++ b/tests/unit/test_patch_whitespace.py @@ -0,0 +1,79 @@ +from openhands.resolver.patching.apply import apply_diff +from openhands.resolver.patching.patch import parse_patch + + +def test_patch_whitespace_mismatch(): + """Test that the patch application succeeds even when whitespace doesn't match.""" + # Original content has a line with spaces + original_content = """class Example: + def method(self): + pass + + def another(self): + pass""" + + # Patch expects an empty line (no spaces) + patch_text = """diff --git a/example.py b/example.py +index 1234567..89abcdef 100644 +--- a/example.py ++++ b/example.py +@@ -2,6 +2,10 @@ class Example: + def method(self): + pass + ++ new_field: str = "value" ++ + def another(self): + pass""" + + patch = next(parse_patch(patch_text)) + # The patch should still work because we normalize whitespace + new_content = apply_diff(patch, original_content) + assert new_content == [ + 'class Example:', + ' def method(self):', + ' pass', + '', + ' new_field: str = "value"', + '', + ' def another(self):', + ' pass', + ] + + +def test_patch_whitespace_match(): + """Test that the patch application succeeds when whitespace matches.""" + # Original content has an empty line (no spaces) + original_content = """class Example: + def method(self): + pass + + def another(self): + pass""" + + # Patch expects an empty line (no spaces) + patch_text = """diff --git a/example.py b/example.py +index 1234567..89abcdef 100644 +--- a/example.py ++++ b/example.py +@@ -2,6 +2,10 @@ class Example: + def method(self): + pass + ++ new_field: str = "value" ++ + def another(self): + pass""" + + patch = next(parse_patch(patch_text)) + new_content = apply_diff(patch, original_content) + assert new_content == [ + 'class Example:', + ' def method(self):', + ' pass', + '', + ' new_field: str = "value"', + '', + ' def another(self):', + ' pass', + ] From 13839b427398ee494123b893db89dd652e31cbcf Mon Sep 17 00:00:00 2001 From: Fredy Sierra Date: Mon, 10 Feb 2025 19:56:58 +0100 Subject: [PATCH 3/9] fix: adding support for environment variables type dict (#6672) Co-authored-by: Engel Nyst --- openhands/core/config/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openhands/core/config/utils.py b/openhands/core/config/utils.py index 4fb7a5278bc5..b6bf4b77abad 100644 --- a/openhands/core/config/utils.py +++ b/openhands/core/config/utils.py @@ -3,6 +3,7 @@ import pathlib import platform import sys +from ast import literal_eval from types import UnionType from typing import Any, MutableMapping, get_args, get_origin from uuid import uuid4 @@ -72,6 +73,9 @@ def set_attr_from_env(sub_config: BaseModel, prefix=''): # Attempt to cast the env var to type hinted in the dataclass if field_type is bool: cast_value = str(value).lower() in ['true', '1'] + # parse dicts like SANDBOX_RUNTIME_STARTUP_ENV_VARS + elif get_origin(field_type) is dict: + cast_value = literal_eval(value) else: cast_value = field_type(value) setattr(sub_config, field_name, cast_value) From af0becd65b2b85288d07be354013679c1f8f5c35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:58:37 +0100 Subject: [PATCH 4/9] chore(deps): bump docker/setup-qemu-action from 3.3.0 to 3.4.0 (#6666) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Engel Nyst --- .github/workflows/ghcr-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ghcr-build.yml b/.github/workflows/ghcr-build.yml index a317c9a7ab03..53439e0e7ea7 100644 --- a/.github/workflows/ghcr-build.yml +++ b/.github/workflows/ghcr-build.yml @@ -42,7 +42,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v3.3.0 + uses: docker/setup-qemu-action@v3.4.0 with: image: tonistiigi/binfmt:latest - name: Login to GHCR @@ -91,7 +91,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v3.3.0 + uses: docker/setup-qemu-action@v3.4.0 with: image: tonistiigi/binfmt:latest - name: Login to GHCR From a1107a2c3070395427ebba3d8e2ab02bda0a33a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 20:58:00 +0100 Subject: [PATCH 5/9] chore(deps): bump the version-all group across 1 directory with 9 updates (#6667) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Engel Nyst --- poetry.lock | 180 ++++++++++++++++++++++++------------------------- pyproject.toml | 6 +- 2 files changed, 91 insertions(+), 95 deletions(-) diff --git a/poetry.lock b/poetry.lock index ef37bd55ce1b..75cefb01c7c7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -580,18 +580,18 @@ files = [ [[package]] name = "boto3" -version = "1.36.12" +version = "1.36.16" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "boto3-1.36.12-py3-none-any.whl", hash = "sha256:32cdf0967287f3ec25a9dc09df0d29cb86b8900c3e0546a63d672775d8127abf"}, - {file = "boto3-1.36.12.tar.gz", hash = "sha256:287d84f49bba3255a17b374578127d42b6251e72f55914a62e0ad9ca78c0954b"}, + {file = "boto3-1.36.16-py3-none-any.whl", hash = "sha256:b10583bf8bd35be1b4027ee7e26b7cdf2078c79eab18357fd602cecb6d39400b"}, + {file = "boto3-1.36.16.tar.gz", hash = "sha256:0cf92ca0538ab115447e1c58050d43e1273e88c58ddfea2b6f133fdc508b400a"}, ] [package.dependencies] -botocore = ">=1.36.12,<1.37.0" +botocore = ">=1.36.16,<1.37.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.11.0,<0.12.0" @@ -600,14 +600,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.36.12" +version = "1.36.16" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "botocore-1.36.12-py3-none-any.whl", hash = "sha256:5ae1ed362c8ed908a6ced8cdd12b21e2196c100bc79f9e95c9c1fc7f9ea74f5a"}, - {file = "botocore-1.36.12.tar.gz", hash = "sha256:86ed88beb4f244c96529435c868d3940073c2774116f0023fb7691f6e7053bd9"}, + {file = "botocore-1.36.16-py3-none-any.whl", hash = "sha256:aca0348ccd730332082489b6817fdf89e1526049adcf6e9c8c11c96dd9f42c03"}, + {file = "botocore-1.36.16.tar.gz", hash = "sha256:10c6aa386ba1a9a0faef6bb5dbfc58fc2563a3c6b95352e86a583cd5f14b11f3"}, ] [package.dependencies] @@ -1370,6 +1370,7 @@ files = [ {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, @@ -1380,6 +1381,7 @@ files = [ {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, @@ -4106,20 +4108,20 @@ types-tqdm = "*" [[package]] name = "litellm" -version = "1.60.2" +version = "1.60.8" 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" groups = ["main"] files = [ - {file = "litellm-1.60.2-py3-none-any.whl", hash = "sha256:1cb08cda04bf8c5ef3e690171a779979e4b16a5e3a24cd8dc1f198e7f198d5c4"}, - {file = "litellm-1.60.2.tar.gz", hash = "sha256:a8170584fcfd6f5175201d869e61ccd8a40ffe3264fc5e53c5b805ddf8a6e05a"}, + {file = "litellm-1.60.8-py3-none-any.whl", hash = "sha256:260bdcc9749c769f1a84dc927abe7c91f6294a97da05abc6b513c5dd2dcf17a1"}, + {file = "litellm-1.60.8.tar.gz", hash = "sha256:4a0aca9bd226d727ca4a41aaf8722f825fc10cf33f37a177a3cceb4ee2c442d8"}, ] [package.dependencies] aiohttp = "*" click = "*" -httpx = ">=0.23.0,<0.28.0" +httpx = ">=0.23.0" importlib-metadata = ">=6.8.0" jinja2 = ">=3.1.2,<4.0.0" jsonschema = ">=4.22.0,<5.0.0" @@ -4152,20 +4154,20 @@ pydantic = ">=1.10" [[package]] name = "llama-index" -version = "0.12.15" +version = "0.12.16" description = "Interface between LLMs and your data" optional = false python-versions = "<4.0,>=3.9" groups = ["llama-index"] files = [ - {file = "llama_index-0.12.15-py3-none-any.whl", hash = "sha256:badb0da25dc0a8e2d7c34734378c3f5d88a96b6eb7ffb2c6935bbe7ca33f6f22"}, - {file = "llama_index-0.12.15.tar.gz", hash = "sha256:2d77c3264d624776e8dace51397c296ae438f3f0be5abf83f07100930a4d5329"}, + {file = "llama_index-0.12.16-py3-none-any.whl", hash = "sha256:c94d0cf6735219d97d91e2eca5bcfac89ec1583990917f934b075d5a45686cf6"}, + {file = "llama_index-0.12.16.tar.gz", hash = "sha256:4fd5f5b94eb3f8dd470bb8cc0e1b985d931e8f31473266ef69855488fd8ae3f2"}, ] [package.dependencies] llama-index-agent-openai = ">=0.4.0,<0.5.0" llama-index-cli = ">=0.4.0,<0.5.0" -llama-index-core = ">=0.12.15,<0.13.0" +llama-index-core = ">=0.12.16,<0.13.0" llama-index-embeddings-openai = ">=0.3.0,<0.4.0" llama-index-indices-managed-llama-cloud = ">=0.4.0" llama-index-llms-openai = ">=0.3.0,<0.4.0" @@ -4212,14 +4214,14 @@ llama-index-llms-openai = ">=0.3.0,<0.4.0" [[package]] name = "llama-index-core" -version = "0.12.15" +version = "0.12.16.post1" description = "Interface between LLMs and your data" optional = false python-versions = "<4.0,>=3.9" groups = ["llama-index"] files = [ - {file = "llama_index_core-0.12.15-py3-none-any.whl", hash = "sha256:0c65ca72c4fb43a77a2463f2114d6eb570681d729139879ed659179798ecab7f"}, - {file = "llama_index_core-0.12.15.tar.gz", hash = "sha256:f9aaeef792db24d490b1e3484d2bbd1b3c43e7a24a40fd6dbd1b298efb1f9429"}, + {file = "llama_index_core-0.12.16.post1-py3-none-any.whl", hash = "sha256:95904a44f25e122a45963541c56a50c4daf2ffaf062d1a3224c84a6dc9e6801f"}, + {file = "llama_index_core-0.12.16.post1.tar.gz", hash = "sha256:8fed0554ae71b6c1f80b53164723af28c887951eef7aa1b44ba6c8103c0efb2c"}, ] [package.dependencies] @@ -5014,13 +5016,13 @@ type = ["mypy (==1.11.2)"] [[package]] name = "modal" -version = "0.73.12" +version = "0.73.26" description = "Python client library for Modal" optional = false python-versions = ">=3.9" groups = ["main", "evaluation"] files = [ - {file = "modal-0.73.12-py3-none-any.whl", hash = "sha256:9eecbb36d53fa29c59a2f9d463a835d0c3eb0889c8b34447a4b26d85290140a6"}, + {file = "modal-0.73.26-py3-none-any.whl", hash = "sha256:8b3d3708ee43270723057ddacf13aa28028abfccc0c87e01b707a41bd7440ef2"}, ] [package.dependencies] @@ -5234,50 +5236,44 @@ dill = ">=0.3.8" [[package]] name = "mypy" -version = "1.14.1" +version = "1.15.0" description = "Optional static typing for Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, + {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, + {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, + {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, + {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, + {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, + {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, + {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, + {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, + {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, + {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, + {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, + {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, + {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, + {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, + {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, + {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, + {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, + {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, + {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, + {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, + {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, + {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, ] [package.dependencies] @@ -5842,14 +5838,14 @@ sympy = "*" [[package]] name = "openai" -version = "1.61.0" +version = "1.61.1" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" groups = ["main", "evaluation", "llama-index", "test"] files = [ - {file = "openai-1.61.0-py3-none-any.whl", hash = "sha256:e8c512c0743accbdbe77f3429a1490d862f8352045de8dc81969301eb4a4f666"}, - {file = "openai-1.61.0.tar.gz", hash = "sha256:216f325a24ed8578e929b0f1b3fb2052165f3b04b0461818adaa51aa29c71f8a"}, + {file = "openai-1.61.1-py3-none-any.whl", hash = "sha256:72b0826240ce26026ac2cd17951691f046e5be82ad122d20a8e1b30ca18bd11e"}, + {file = "openai-1.61.1.tar.gz", hash = "sha256:ce1851507218209961f89f3520e06726c0aa7d0512386f0f977e3ac3e4f2472e"}, ] [package.dependencies] @@ -8240,42 +8236,42 @@ pyasn1 = ">=0.1.3" [[package]] name = "ruff" -version = "0.9.4" +version = "0.9.6" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" groups = ["dev", "evaluation"] files = [ - {file = "ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706"}, - {file = "ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf"}, - {file = "ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214"}, - {file = "ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c"}, - {file = "ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0"}, - {file = "ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402"}, - {file = "ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e"}, - {file = "ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41"}, - {file = "ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7"}, + {file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"}, + {file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"}, + {file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"}, + {file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"}, + {file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"}, + {file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"}, + {file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"}, + {file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"}, + {file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"}, ] [[package]] name = "runloop-api-client" -version = "0.19.0" +version = "0.22.0" description = "The official Python library for the runloop API" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "runloop_api_client-0.19.0-py3-none-any.whl", hash = "sha256:e7ed5ca3067f19dbf41e38f112bdb58317f23725d0a379e7ab8e5d8d137e7a54"}, - {file = "runloop_api_client-0.19.0.tar.gz", hash = "sha256:62b3cc3137902c5380cbe74a77fe4631ded38700911ef3f08ba1a423835554e4"}, + {file = "runloop_api_client-0.22.0-py3-none-any.whl", hash = "sha256:54cb3e94970e7734a97fb5dc1adc40e9beb3f2280c6de830154bf3eaa46217de"}, + {file = "runloop_api_client-0.22.0.tar.gz", hash = "sha256:6ec1f3aff4cf3984ea95e6d1498b5bc9bfe7b153cd2acb94d82fc86da2965cd5"}, ] [package.dependencies] @@ -8924,14 +8920,14 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7 [[package]] name = "streamlit" -version = "1.41.1" +version = "1.42.0" description = "A faster way to build and share data apps" optional = false python-versions = "!=3.9.7,>=3.9" groups = ["evaluation"] files = [ - {file = "streamlit-1.41.1-py2.py3-none-any.whl", hash = "sha256:0def00822480071d642e6df36cd63c089f991da3a69fd9eb4ab8f65ce27de4e0"}, - {file = "streamlit-1.41.1.tar.gz", hash = "sha256:6626d32b098ba1458b71eebdd634c62af2dd876380e59c4b6a1e828a39d62d69"}, + {file = "streamlit-1.42.0-py2.py3-none-any.whl", hash = "sha256:edf333fd3525b7c64b19e1156b483a1a93cbdb09a3a06f26478388d68f971090"}, + {file = "streamlit-1.42.0.tar.gz", hash = "sha256:8c48494ccfad33e7d0bc5873151800b203cb71203bfd42bc7418940710ca4970"}, ] [package.dependencies] @@ -8952,11 +8948,11 @@ rich = ">=10.14.0,<14" tenacity = ">=8.1.0,<10" toml = ">=0.10.1,<2" tornado = ">=6.0.3,<7" -typing-extensions = ">=4.3.0,<5" +typing-extensions = ">=4.4.0,<5" watchdog = {version = ">=2.1.5,<7", markers = "platform_system != \"Darwin\""} [package.extras] -snowflake = ["snowflake-connector-python (>=2.8.0)", "snowflake-snowpark-python[modin] (>=1.17.0)"] +snowflake = ["snowflake-connector-python (>=3.3.0)", "snowflake-snowpark-python[modin] (>=1.17.0)"] [[package]] name = "strenum" @@ -10642,4 +10638,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.1" python-versions = "^3.12" -content-hash = "cb3fab7a5e6d48140970edc84b14918bbbd637cdfdefd0a88462e4db42fb1d6f" +content-hash = "74eaaaed3b4f3e617760db7a38bea4fa6b9f66e169c5f4e9053c9a197fe616ca" diff --git a/pyproject.toml b/pyproject.toml index b9a1df2b04fb..81f5b71b6645 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,7 +63,7 @@ protobuf = "^4.21.6,<5.0.0" # chromadb currently fails on 5.0+ opentelemetry-api = "1.25.0" opentelemetry-exporter-otlp-proto-grpc = "1.25.0" modal = ">=0.66.26,<0.74.0" -runloop-api-client = "0.19.0" +runloop-api-client = "0.22.0" libtmux = ">=0.37,<0.40" pygithub = "^2.5.0" joblib = "*" @@ -86,8 +86,8 @@ voyageai = "*" llama-index-embeddings-voyageai = "*" [tool.poetry.group.dev.dependencies] -ruff = "0.9.4" -mypy = "1.14.1" +ruff = "0.9.6" +mypy = "1.15.0" pre-commit = "4.1.0" build = "*" From b12b426e3ded6934b289e2efe2dd7ad0c7d181c1 Mon Sep 17 00:00:00 2001 From: "sp.wack" <83104063+amanape@users.noreply.github.com> Date: Tue, 11 Feb 2025 00:52:59 +0400 Subject: [PATCH 6/9] hotfix: Typecheck routes during frontend build (#6676) --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 7be3f89cbcf6..8634bc195d8b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -50,7 +50,7 @@ "scripts": { "dev": "npm run make-i18n && cross-env VITE_MOCK_API=false react-router dev", "dev:mock": "npm run make-i18n && cross-env VITE_MOCK_API=true react-router dev", - "build": "npm run make-i18n && tsc && react-router build", + "build": "npm run make-i18n && npm run typecheck && react-router build", "start": "npx sirv-cli build/ --single", "test": "vitest run", "test:e2e": "playwright test", From 4615548477b12eed183e85556c3622b22b31a12e Mon Sep 17 00:00:00 2001 From: Xingyao Wang Date: Mon, 10 Feb 2025 16:54:23 -0500 Subject: [PATCH 7/9] Bump OpenHands ACI to 0.2.1 (#6678) --- poetry.lock | 12 +++++------- pyproject.toml | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/poetry.lock b/poetry.lock index 75cefb01c7c7..cf0b20e6f7e3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1370,7 +1370,6 @@ files = [ {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, - {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, @@ -1381,7 +1380,6 @@ files = [ {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, - {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, @@ -5864,14 +5862,14 @@ realtime = ["websockets (>=13,<15)"] [[package]] name = "openhands-aci" -version = "0.2.0" +version = "0.2.1" description = "An Agent-Computer Interface (ACI) designed for software development agents OpenHands." optional = false python-versions = "<4.0,>=3.12" groups = ["main"] files = [ - {file = "openhands_aci-0.2.0-py3-none-any.whl", hash = "sha256:5ca0df7ab6dab1034e70d3982b401db9888dd6deb8149d30e47193bf8588ed65"}, - {file = "openhands_aci-0.2.0.tar.gz", hash = "sha256:6c54defd07a7b2e861ff5c8f683777c2c2503a0f417eeb570382be682e7038d6"}, + {file = "openhands_aci-0.2.1-py3-none-any.whl", hash = "sha256:10f5038e6303b8e1d40af0b61fb967f1d9d00c1ef05c2a06db2529364f3fef04"}, + {file = "openhands_aci-0.2.1.tar.gz", hash = "sha256:7dc72ba3aa7e9d699aacf8b85909ecaa6b87e7e4f203e4d549f740ac56d5ca2b"}, ] [package.dependencies] @@ -10638,4 +10636,4 @@ testing = ["coverage[toml]", "zope.event", "zope.testing"] [metadata] lock-version = "2.1" python-versions = "^3.12" -content-hash = "74eaaaed3b4f3e617760db7a38bea4fa6b9f66e169c5f4e9053c9a197fe616ca" +content-hash = "439164c45c674574af3fc15ade8e69452c11d4d45d95c2e671c752cfed6a3143" diff --git a/pyproject.toml b/pyproject.toml index 81f5b71b6645..70e5836cc4a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,7 +67,7 @@ runloop-api-client = "0.22.0" libtmux = ">=0.37,<0.40" pygithub = "^2.5.0" joblib = "*" -openhands-aci = "^0.2.0" +openhands-aci = "^0.2.1" python-socketio = "^5.11.4" redis = "^5.2.0" sse-starlette = "^2.1.3" From 1a715d2ec4c59a48dd070d02a59ef2869f0f92dd Mon Sep 17 00:00:00 2001 From: Engel Nyst Date: Tue, 11 Feb 2025 00:00:46 +0100 Subject: [PATCH 8/9] Clean up global in llm.py (we figured it's not needed) (#6675) --- .../agenthub/codeact_agent/codeact_agent.py | 1 - openhands/llm/llm.py | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/openhands/agenthub/codeact_agent/codeact_agent.py b/openhands/agenthub/codeact_agent/codeact_agent.py index 62ad243e915b..5a1f6d54a84d 100644 --- a/openhands/agenthub/codeact_agent/codeact_agent.py +++ b/openhands/agenthub/codeact_agent/codeact_agent.py @@ -303,7 +303,6 @@ def get_observation_message( and len(obs.set_of_marks) > 0 and self.config.enable_som_visual_browsing and self.llm.vision_is_active() - and self.llm.is_visual_browser_tool_supported() ): text += 'Image: Current webpage screenshot (Note that only visible portion of webpage is present in the screenshot. You may need to scroll to view the remaining portion of the web-page.)\n' message = Message( diff --git a/openhands/llm/llm.py b/openhands/llm/llm.py index ff3c62772b47..e8dd2f6f1ef8 100644 --- a/openhands/llm/llm.py +++ b/openhands/llm/llm.py @@ -75,16 +75,6 @@ 'o3-mini', ] -# visual browsing tool supported models -# This flag is needed since gpt-4o and gpt-4o-mini do not allow passing image_urls with role='tool' -VISUAL_BROWSING_TOOL_SUPPORTED_MODELS = [ - 'claude-3-5-sonnet', - 'claude-3-5-sonnet-20240620', - 'claude-3-5-sonnet-20241022', - 'o1-2024-12-17', -] - - REASONING_EFFORT_SUPPORTED_MODELS = [ 'o1-2024-12-17', 'o1', @@ -495,15 +485,6 @@ def is_function_calling_active(self) -> bool: """ return self._function_calling_active - def is_visual_browser_tool_supported(self) -> bool: - return ( - self.config.model in VISUAL_BROWSING_TOOL_SUPPORTED_MODELS - or self.config.model.split('/')[-1] in VISUAL_BROWSING_TOOL_SUPPORTED_MODELS - or any( - m in self.config.model for m in VISUAL_BROWSING_TOOL_SUPPORTED_MODELS - ) - ) - def _post_completion(self, response: ModelResponse) -> float: """Post-process the completion response. From 6a6dc93e0379bfdf96096fce06b21a8e51871aec Mon Sep 17 00:00:00 2001 From: Xingyao Wang Date: Mon, 10 Feb 2025 22:21:11 -0500 Subject: [PATCH 9/9] feat(runtime): use `prlimit` to limit resource usage of command to avoid OOM Runtime Kill (#6338) Co-authored-by: openhands Co-authored-by: Engel Nyst Co-authored-by: Graham Neubig --- openhands/runtime/action_execution_server.py | 19 +++ .../runtime/impl/remote/remote_runtime.py | 10 +- openhands/runtime/utils/bash.py | 16 ++- tests/runtime/test_runtime_resource.py | 113 ++++++++++++++++++ tests/runtime/test_stress_docker_runtime.py | 36 ------ 5 files changed, 151 insertions(+), 43 deletions(-) create mode 100644 tests/runtime/test_runtime_resource.py delete mode 100644 tests/runtime/test_stress_docker_runtime.py diff --git a/openhands/runtime/action_execution_server.py b/openhands/runtime/action_execution_server.py index 2148ab2267d1..f2d12196fede 100644 --- a/openhands/runtime/action_execution_server.py +++ b/openhands/runtime/action_execution_server.py @@ -21,6 +21,7 @@ from pathlib import Path from zipfile import ZipFile +import psutil from fastapi import Depends, FastAPI, HTTPException, Request, UploadFile from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse, StreamingResponse @@ -108,6 +109,22 @@ def __init__( self.last_execution_time = self.start_time self._initialized = False + if _override_max_memory_gb := os.environ.get('RUNTIME_MAX_MEMORY_GB', None): + self.max_memory_gb = int(_override_max_memory_gb) + logger.info( + f'Setting max memory to {self.max_memory_gb}GB (according to the RUNTIME_MAX_MEMORY_GB environment variable)' + ) + else: + # Get available system memory + total_memory_gb = psutil.virtual_memory().total / ( + 1024 * 1024 * 1024 + ) # Convert to GB + self.max_memory_gb = int(max(0.5, total_memory_gb - 1.0)) + # Reserve 1GB as head room, minimum of 0.5GB + logger.info( + f'Total memory: {total_memory_gb}GB, setting limit to {self.max_memory_gb}GB (reserved 1GB for action execution server, minimum 0.5GB)' + ) + @property def initial_cwd(self): return self._initial_cwd @@ -120,8 +137,10 @@ async def ainit(self): no_change_timeout_seconds=int( os.environ.get('NO_CHANGE_TIMEOUT_SECONDS', 30) ), + max_memory_mb=self.max_memory_gb * 1024, ) self.bash_session.initialize() + await wait_all( (self._init_plugin(plugin) for plugin in self.plugins_to_load), timeout=30, diff --git a/openhands/runtime/impl/remote/remote_runtime.py b/openhands/runtime/impl/remote/remote_runtime.py index cb10b2c15b78..f33acedbf4ad 100644 --- a/openhands/runtime/impl/remote/remote_runtime.py +++ b/openhands/runtime/impl/remote/remote_runtime.py @@ -212,13 +212,17 @@ def _start_runtime(self): plugins=self.plugins, app_config=self.config, ) + environment = { + 'DEBUG': 'true' + if self.config.debug or os.environ.get('DEBUG', 'false').lower() == 'true' + else {}, + } + environment.update(self.config.sandbox.runtime_startup_env_vars) start_request = { 'image': self.container_image, 'command': command, 'working_dir': '/openhands/code/', - 'environment': {'DEBUG': 'true'} - if self.config.debug or os.environ.get('DEBUG', 'false').lower() == 'true' - else {}, + 'environment': environment, 'session_id': self.sid, 'resource_factor': self.config.sandbox.remote_runtime_resource_factor, } diff --git a/openhands/runtime/utils/bash.py b/openhands/runtime/utils/bash.py index 5fda883d4d01..419573d7546d 100644 --- a/openhands/runtime/utils/bash.py +++ b/openhands/runtime/utils/bash.py @@ -175,25 +175,32 @@ def __init__( work_dir: str, username: str | None = None, no_change_timeout_seconds: int = 30, + max_memory_mb: int | None = None, ): self.NO_CHANGE_TIMEOUT_SECONDS = no_change_timeout_seconds self.work_dir = work_dir self.username = username self._initialized = False + self.max_memory_mb = max_memory_mb def initialize(self): self.server = libtmux.Server() - window_command = '/bin/bash' + _shell_command = '/bin/bash' if self.username in ['root', 'openhands']: # This starts a non-login (new) shell for the given user - window_command = f'su {self.username} -' + _shell_command = f'su {self.username} -' # otherwise, we are running as the CURRENT USER (e.g., when running LocalRuntime) + if self.max_memory_mb is not None: + window_command = ( + f'prlimit --as={self.max_memory_mb * 1024 * 1024} {_shell_command}' + ) + else: + window_command = _shell_command + logger.debug(f'Initializing bash session with command: {window_command}') session_name = f'openhands-{self.username}-{uuid.uuid4()}' self.session = self.server.new_session( session_name=session_name, - window_name='bash', - window_command=window_command, start_directory=self.work_dir, kill_session=True, x=1000, @@ -207,6 +214,7 @@ def initialize(self): # We need to create a new pane because the initial pane's history limit is (default) 2000 _initial_window = self.session.attached_window self.window = self.session.new_window( + window_name='bash', window_shell=window_command, start_directory=self.work_dir, ) diff --git a/tests/runtime/test_runtime_resource.py b/tests/runtime/test_runtime_resource.py new file mode 100644 index 000000000000..2873939f132d --- /dev/null +++ b/tests/runtime/test_runtime_resource.py @@ -0,0 +1,113 @@ +"""Stress tests for the DockerRuntime, which connects to the ActionExecutor running in the sandbox.""" + +from conftest import _close_test_runtime, _load_runtime + +from openhands.core.logger import openhands_logger as logger +from openhands.events.action import CmdRunAction + + +def test_stress_docker_runtime(temp_dir, runtime_cls, repeat=1): + runtime, config = _load_runtime( + temp_dir, + runtime_cls, + docker_runtime_kwargs={ + 'cpu_period': 100000, # 100ms + 'cpu_quota': 100000, # Can use 100ms out of each 100ms period (1 CPU) + 'mem_limit': '4G', # 4 GB of memory + }, + ) + + action = CmdRunAction( + command='sudo apt-get update && sudo apt-get install -y stress-ng' + ) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + assert obs.exit_code == 0 + + for _ in range(repeat): + # run stress-ng stress tests for 1 minute + action = CmdRunAction(command='stress-ng --all 1 -t 30s') + action.set_hard_timeout(120) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + + _close_test_runtime(runtime) + + +def test_stress_docker_runtime_hit_memory_limits(temp_dir, runtime_cls): + """Test runtime behavior under resource constraints.""" + runtime, config = _load_runtime( + temp_dir, + runtime_cls, + docker_runtime_kwargs={ + 'cpu_period': 100000, # 100ms + 'cpu_quota': 100000, # Can use 100ms out of each 100ms period (1 CPU) + 'mem_limit': '4G', # 4 GB of memory + 'memswap_limit': '0', # No swap + 'mem_swappiness': 0, # Disable swapping + 'oom_kill_disable': False, # Enable OOM killer + }, + runtime_startup_env_vars={ + 'RUNTIME_MAX_MEMORY_GB': '3', + }, + ) + + action = CmdRunAction( + command='sudo apt-get update && sudo apt-get install -y stress-ng' + ) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + assert obs.exit_code == 0 + + action = CmdRunAction( + command='stress-ng --vm 1 --vm-bytes 6G --timeout 30s --metrics' + ) + action.set_hard_timeout(120) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + assert 'aborted early, out of system resources' in obs.content + assert obs.exit_code == 3 # OOM killed! + + _close_test_runtime(runtime) + + +def test_stress_docker_runtime_within_memory_limits(temp_dir, runtime_cls): + """Test runtime behavior under resource constraints.""" + runtime, config = _load_runtime( + temp_dir, + runtime_cls, + docker_runtime_kwargs={ + 'cpu_period': 100000, # 100ms + 'cpu_quota': 100000, # Can use 100ms out of each 100ms period (1 CPU) + 'mem_limit': '4G', # 4 GB of memory + 'memswap_limit': '0', # No swap + 'mem_swappiness': 0, # Disable swapping + 'oom_kill_disable': False, # Enable OOM killer + }, + runtime_startup_env_vars={ + 'RUNTIME_MAX_MEMORY_GB': '7', + }, + ) + + action = CmdRunAction( + command='sudo apt-get update && sudo apt-get install -y stress-ng' + ) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + assert obs.exit_code == 0 + + action = CmdRunAction( + command='stress-ng --vm 1 --vm-bytes 6G --timeout 30s --metrics' + ) + action.set_hard_timeout(120) + logger.info(action, extra={'msg_type': 'ACTION'}) + obs = runtime.run_action(action) + logger.info(obs, extra={'msg_type': 'OBSERVATION'}) + assert obs.exit_code == 0 + + _close_test_runtime(runtime) diff --git a/tests/runtime/test_stress_docker_runtime.py b/tests/runtime/test_stress_docker_runtime.py deleted file mode 100644 index b679a0836253..000000000000 --- a/tests/runtime/test_stress_docker_runtime.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Stress tests for the DockerRuntime, which connects to the ActionExecutor running in the sandbox.""" - -from conftest import _close_test_runtime, _load_runtime - -from openhands.core.logger import openhands_logger as logger -from openhands.events.action import CmdRunAction - - -def test_stress_docker_runtime(temp_dir, runtime_cls, repeat=1): - runtime, config = _load_runtime( - temp_dir, - runtime_cls, - docker_runtime_kwargs={ - 'cpu_period': 100000, # 100ms - 'cpu_quota': 100000, # Can use 100ms out of each 100ms period (1 CPU) - 'mem_limit': '4G', # 4 GB of memory - }, - ) - - action = CmdRunAction( - command='sudo apt-get update && sudo apt-get install -y stress-ng' - ) - logger.info(action, extra={'msg_type': 'ACTION'}) - obs = runtime.run_action(action) - logger.info(obs, extra={'msg_type': 'OBSERVATION'}) - assert obs.exit_code == 0 - - for _ in range(repeat): - # run stress-ng stress tests for 1 minute - action = CmdRunAction(command='stress-ng --all 1 -t 1m') - action.set_hard_timeout(120) - logger.info(action, extra={'msg_type': 'ACTION'}) - obs = runtime.run_action(action) - logger.info(obs, extra={'msg_type': 'OBSERVATION'}) - - _close_test_runtime(runtime)