diff --git a/astrbot/core/computer/computer_client.py b/astrbot/core/computer/computer_client.py index 9be646265e..4eae562c92 100644 --- a/astrbot/core/computer/computer_client.py +++ b/astrbot/core/computer/computer_client.py @@ -507,7 +507,9 @@ async def _sync_skills_to_sandbox(booter: ComputerBooter) -> None: remote_zip = Path(SANDBOX_SKILLS_ROOT) / "skills.zip" logger.info("Uploading skills bundle to sandbox...") await booter.shell.exec(f"mkdir -p {SANDBOX_SKILLS_ROOT}") - upload_result = await booter.upload_file(str(zip_path), str(remote_zip)) + upload_result = await booter.upload_file( + str(zip_path), remote_zip.as_posix() + ) if not upload_result.get("success", False): raise RuntimeError("Failed to upload skills bundle to sandbox.") else: diff --git a/astrbot/core/provider/sources/openai_source.py b/astrbot/core/provider/sources/openai_source.py index 8aa2778f1b..e744b9ac27 100644 --- a/astrbot/core/provider/sources/openai_source.py +++ b/astrbot/core/provider/sources/openai_source.py @@ -270,12 +270,12 @@ def _file_uri_to_path(file_uri: str) -> str: netloc = unquote(parsed.netloc or "") path = unquote(parsed.path or "") if re.fullmatch(r"[A-Za-z]:", netloc): - return str(Path(f"{netloc}{path}")) + return Path(f"{netloc}{path}").as_posix() if re.match(r"^/[A-Za-z]:/", path): path = path[1:] if netloc and netloc != "localhost": path = f"//{netloc}{path}" - return str(Path(path)) + return Path(path).as_posix() async def _image_ref_to_data_url( self, diff --git a/astrbot/core/skills/skill_manager.py b/astrbot/core/skills/skill_manager.py index 838301c044..95cb46ae1b 100644 --- a/astrbot/core/skills/skill_manager.py +++ b/astrbot/core/skills/skill_manager.py @@ -196,7 +196,7 @@ def _build_skill_read_command_example(path: str) -> str: return f"cat {path}" if _is_windows_prompt_path(path): command = "type" - path_arg = f'"{os.path.normpath(path)}"' + path_arg = f'"{path.replace(chr(92), "/")}"' else: command = "cat" path_arg = shlex.quote(path) diff --git a/astrbot/core/utils/__init__.py b/astrbot/core/utils/__init__.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/astrbot/core/utils/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/test_computer_fs_tools.py b/tests/test_computer_fs_tools.py index eaf72ec66e..faf86b3410 100644 --- a/tests/test_computer_fs_tools.py +++ b/tests/test_computer_fs_tools.py @@ -212,7 +212,7 @@ async def test_restricted_local_member_can_read_plugin_provided_skill( path=str(plugin_skill), ) - assert result == "# Demo Skill\n\nRead plugin docs." + assert result.replace("\r\n", "\n") == "# Demo Skill\n\nRead plugin docs." @pytest.mark.asyncio @@ -237,7 +237,7 @@ async def test_restricted_local_member_can_read_plugin_skill_inventory_even_if_p path=str(plugin_skill), ) - assert result == "# Demo Skill\n" + assert result.replace("\r\n", "\n") == "# Demo Skill\n" @pytest.mark.asyncio @@ -314,7 +314,7 @@ async def test_file_read_tool_allows_partial_read_for_large_text_file( limit=3, ) - assert result == "".join(lines[1000:1003]) + assert result.replace("\r\n", "\n") == "".join(lines[1000:1003]) @pytest.mark.asyncio diff --git a/tests/test_openai_source.py b/tests/test_openai_source.py index b5587ffb14..a8d0effd72 100644 --- a/tests/test_openai_source.py +++ b/tests/test_openai_source.py @@ -1063,7 +1063,10 @@ async def test_prepare_chat_payload_materializes_context_localhost_file_uri_imag image_path = tmp_path / "quoted-image.png" PILImage.new("RGBA", (1, 1), (255, 0, 0, 255)).save(image_path) - localhost_uri = f"file://localhost{image_path.as_posix()}" + posix_path = image_path.as_posix() + if not posix_path.startswith("/"): + posix_path = "/" + posix_path + localhost_uri = f"file://localhost{posix_path}" payloads, _ = await provider._prepare_chat_payload( prompt=None, contexts=[ diff --git a/tests/test_pip_helper_modules.py b/tests/test_pip_helper_modules.py index 1ce4967139..9893f6b01a 100644 --- a/tests/test_pip_helper_modules.py +++ b/tests/test_pip_helper_modules.py @@ -442,7 +442,8 @@ def test_get_core_constraints_logs_resolution_step_context(monkeypatch): assert any("解析核心分发名称失败" in log for log in warning_logs) -def test_iter_requirements_supports_direct_line_input(): +def test_iter_requirements_supports_direct_line_input(monkeypatch): + monkeypatch.setattr("sys.platform", "linux") parsed = list( requirements_utils.iter_requirements( lines=["demo-package>=1.0", 'other-package; sys_platform == "win32"'] diff --git a/tests/test_pip_installer.py b/tests/test_pip_installer.py index 266d9195b0..29afb9451e 100644 --- a/tests/test_pip_installer.py +++ b/tests/test_pip_installer.py @@ -788,6 +788,7 @@ def test_find_missing_requirements_honors_version_specifiers(monkeypatch, tmp_pa def test_find_missing_requirements_skips_unmatched_markers(monkeypatch, tmp_path): + monkeypatch.setattr("sys.platform", "linux") requirements_path = tmp_path / "requirements.txt" requirements_path.write_text( 'demo-package; sys_platform == "win32"\n', diff --git a/tests/unit/test_computer.py b/tests/unit/test_computer.py index 71b31a301a..8aa1758fae 100644 --- a/tests/unit/test_computer.py +++ b/tests/unit/test_computer.py @@ -194,7 +194,7 @@ async def test_exec_simple_code(self): """Test executing simple Python code.""" python = LocalPythonComponent() result = await python.exec("print('hello')") - assert result["data"]["output"]["text"] == "hello\n" + assert result["data"]["output"]["text"].replace("\r\n", "\n") == "hello\n" @pytest.mark.asyncio async def test_exec_with_error(self):