Rename Workspace -> FileWorkspace; expand interface

This commit is contained in:
Reinier van der Leer
2023-10-13 20:51:06 -07:00
parent e6b21bdd57
commit 0c2d564c33
26 changed files with 246 additions and 203 deletions

View File

@@ -38,8 +38,8 @@ from autogpt.models.context_item import ContextItem
from .base import BaseAgent, BaseAgentConfiguration, BaseAgentSettings
from .features.context import ContextMixin
from .features.file_workspace import FileWorkspaceMixin
from .features.watchdog import WatchdogMixin
from .features.workspace import WorkspaceMixin
from .prompt_strategies.one_shot import (
OneShotAgentPromptConfiguration,
OneShotAgentPromptStrategy,
@@ -64,7 +64,7 @@ class AgentSettings(BaseAgentSettings):
class Agent(
ContextMixin,
WorkspaceMixin,
FileWorkspaceMixin,
WatchdogMixin,
BaseAgent,
Configurable[AgentSettings],

View File

@@ -7,20 +7,20 @@ if TYPE_CHECKING:
from ..base import BaseAgent
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from ..base import AgentFileManager, BaseAgentConfiguration
class WorkspaceMixin:
class FileWorkspaceMixin:
"""Mixin that adds workspace support to a class"""
workspace: Workspace | None
workspace: FileWorkspace = None
"""Workspace that the agent has access to, e.g. for reading/writing files."""
def __init__(self, **kwargs):
# Initialize other bases first, because we need the config from BaseAgent
super(WorkspaceMixin, self).__init__(**kwargs)
super(FileWorkspaceMixin, self).__init__(**kwargs)
config: BaseAgentConfiguration = getattr(self, "config")
if not isinstance(config, BaseAgentConfiguration):
@@ -34,7 +34,7 @@ class WorkspaceMixin:
self.workspace = _setup_workspace(file_manager, config)
def attach_fs(self, agent_dir: Path):
res = super(WorkspaceMixin, self).attach_fs(agent_dir)
res = super(FileWorkspaceMixin, self).attach_fs(agent_dir)
self.workspace = _setup_workspace(self.file_manager, self.config)
@@ -42,16 +42,16 @@ class WorkspaceMixin:
def _setup_workspace(file_manager: AgentFileManager, config: BaseAgentConfiguration):
workspace = Workspace(
workspace = FileWorkspace(
file_manager.root / "workspace",
restrict_to_workspace=not config.allow_fs_access,
restrict_to_root=not config.allow_fs_access,
)
workspace.initialize()
return workspace
def get_agent_workspace(agent: BaseAgent) -> Workspace | None:
if isinstance(agent, WorkspaceMixin):
def get_agent_workspace(agent: BaseAgent) -> FileWorkspace | None:
if isinstance(agent, FileWorkspaceMixin):
return agent.workspace
return None

View File

@@ -32,12 +32,12 @@ from autogpt.models.context_item import ContextItem
from .agent import execute_command, extract_command
from .base import BaseAgent
from .features.context import ContextMixin
from .features.workspace import WorkspaceMixin
from .features.file_workspace import FileWorkspaceMixin
logger = logging.getLogger(__name__)
class PlanningAgent(ContextMixin, WorkspaceMixin, BaseAgent):
class PlanningAgent(ContextMixin, FileWorkspaceMixin, BaseAgent):
"""Agent class for interacting with AutoGPT."""
ThoughtProcessID = Literal["plan", "action", "evaluate"]

View File

@@ -0,0 +1,5 @@
from .file_workspace import FileWorkspace
__all__ = [
"FileWorkspace",
]

View File

@@ -0,0 +1,145 @@
"""
The FileWorkspace class provides an interface for interacting with a file workspace.
"""
from __future__ import annotations
import logging
from pathlib import Path
from typing import Any, Callable, Optional
logger = logging.getLogger(__name__)
class FileWorkspace:
"""A class that represents a file workspace."""
NULL_BYTES = ["\0", "\000", "\x00", "\u0000"]
on_write_file: Callable[[Path], Any] | None = None
"""
Event hook, executed after writing a file.
Params:
Path: The path of the file that was written, relative to the workspace root.
"""
def __init__(self, root: str | Path, restrict_to_root: bool):
self._root = self._sanitize_path(root)
self._restrict_to_root = restrict_to_root
@property
def root(self) -> Path:
"""The root directory of the file workspace."""
return self._root
@property
def restrict_to_root(self):
"""Whether to restrict generated paths to the root."""
return self._restrict_to_root
def initialize(self) -> None:
self.root.mkdir(exist_ok=True, parents=True)
def get_path(self, relative_path: str | Path) -> Path:
"""Get the full path for an item in the workspace.
Parameters:
relative_path: The relative path to resolve in the workspace.
Returns:
Path: The resolved path relative to the workspace.
"""
return self._sanitize_path(
relative_path,
root=self.root,
restrict_to_root=self.restrict_to_root,
)
def open_file(self, path: str | Path, mode: str = "r"):
"""Open a file in the workspace."""
full_path = self.get_path(path)
return open(full_path, mode)
def read_file(self, path: str | Path):
"""Read a file in the workspace."""
with self.open_file(path, "r") as file:
return file.read()
def write_file(self, path: str | Path, content: str | bytes):
"""Write to a file in the workspace."""
with self.open_file(path, "w") as file:
file.write(content)
if self.on_write_file:
path = Path(path)
if path.is_absolute():
path = path.relative_to(self.root)
self.on_write_file(path)
def list_files(self, path: str | Path = "."):
"""List all files in a directory in the workspace."""
full_path = self.get_path(path)
return [str(file) for file in full_path.glob("*") if file.is_file()]
def delete_file(self, path: str | Path):
"""Delete a file in the workspace."""
full_path = self.get_path(path)
full_path.unlink()
@staticmethod
def _sanitize_path(
relative_path: str | Path,
root: Optional[str | Path] = None,
restrict_to_root: bool = True,
) -> Path:
"""Resolve the relative path within the given root if possible.
Parameters:
relative_path: The relative path to resolve.
root: The root path to resolve the relative path within.
restrict_to_root: Whether to restrict the path to the root.
Returns:
Path: The resolved path.
Raises:
ValueError: If the path is absolute and a root is provided.
ValueError: If the path is outside the root and the root is restricted.
"""
# Posix systems disallow null bytes in paths. Windows is agnostic about it.
# Do an explicit check here for all sorts of null byte representations.
for null_byte in FileWorkspace.NULL_BYTES:
if null_byte in str(relative_path) or null_byte in str(root):
raise ValueError("embedded null byte")
if root is None:
return Path(relative_path).resolve()
logger.debug(f"Resolving path '{relative_path}' in workspace '{root}'")
root, relative_path = Path(root).resolve(), Path(relative_path)
logger.debug(f"Resolved root as '{root}'")
# Allow absolute paths if they are contained in the workspace.
if (
relative_path.is_absolute()
and restrict_to_root
and not relative_path.is_relative_to(root)
):
raise ValueError(
f"Attempted to access absolute path '{relative_path}' in workspace '{root}'."
)
full_path = root.joinpath(relative_path).resolve()
logger.debug(f"Joined paths as '{full_path}'")
if restrict_to_root and not full_path.is_relative_to(root):
raise ValueError(
f"Attempted to access path '{full_path}' outside of workspace '{root}'."
)
return full_path

View File

@@ -1,5 +0,0 @@
from autogpt.workspace.workspace import Workspace
__all__ = [
"Workspace",
]

View File

@@ -1,127 +0,0 @@
"""
=========
Workspace
=========
The workspace is a directory containing configuration and working files for an AutoGPT
agent.
"""
from __future__ import annotations
import logging
from pathlib import Path
from typing import Optional
logger = logging.getLogger(__name__)
class Workspace:
"""A class that represents a workspace for an AutoGPT agent."""
NULL_BYTES = ["\0", "\000", "\x00", "\u0000"]
def __init__(self, workspace_root: str | Path, restrict_to_workspace: bool):
self._root = self._sanitize_path(workspace_root)
self._restrict_to_workspace = restrict_to_workspace
@property
def root(self) -> Path:
"""The root directory of the workspace."""
return self._root
@property
def restrict_to_workspace(self):
"""Whether to restrict generated paths to the workspace."""
return self._restrict_to_workspace
def initialize(self) -> None:
self.root.mkdir(exist_ok=True, parents=True)
def get_path(self, relative_path: str | Path) -> Path:
"""Get the full path for an item in the workspace.
Parameters
----------
relative_path
The relative path to resolve in the workspace.
Returns
-------
Path
The resolved path relative to the workspace.
"""
return self._sanitize_path(
relative_path,
root=self.root,
restrict_to_root=self.restrict_to_workspace,
)
@staticmethod
def _sanitize_path(
relative_path: str | Path,
root: Optional[str | Path] = None,
restrict_to_root: bool = True,
) -> Path:
"""Resolve the relative path within the given root if possible.
Parameters
----------
relative_path
The relative path to resolve.
root
The root path to resolve the relative path within.
restrict_to_root
Whether to restrict the path to the root.
Returns
-------
Path
The resolved path.
Raises
------
ValueError
If the path is absolute and a root is provided.
ValueError
If the path is outside the root and the root is restricted.
"""
# Posix systems disallow null bytes in paths. Windows is agnostic about it.
# Do an explicit check here for all sorts of null byte representations.
for null_byte in Workspace.NULL_BYTES:
if null_byte in str(relative_path) or null_byte in str(root):
raise ValueError("embedded null byte")
if root is None:
return Path(relative_path).resolve()
logger.debug(f"Resolving path '{relative_path}' in workspace '{root}'")
root, relative_path = Path(root).resolve(), Path(relative_path)
logger.debug(f"Resolved root as '{root}'")
# Allow exception for absolute paths if they are contained in your workspace directory.
if (
relative_path.is_absolute()
and restrict_to_root
and not relative_path.is_relative_to(root)
):
raise ValueError(
f"Attempted to access absolute path '{relative_path}' in workspace '{root}'."
)
full_path = root.joinpath(relative_path).resolve()
logger.debug(f"Joined paths as '{full_path}'")
if restrict_to_root and not full_path.is_relative_to(root):
raise ValueError(
f"Attempted to access path '{full_path}' outside of workspace '{root}'."
)
return full_path

View File

@@ -1,6 +1,6 @@
import pytest
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import run_challenge
@@ -16,7 +16,7 @@ def test_browse_website(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
run_challenge(

View File

@@ -1,7 +1,7 @@
import pytest
from autogpt.config import Config
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -23,7 +23,7 @@ def test_write_file(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
run_challenge(

View File

@@ -6,7 +6,7 @@ from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureRequest
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge import Challenge
from tests.vcr import before_record_response
@@ -64,12 +64,14 @@ def check_beat_challenges(request: FixtureRequest) -> None:
@pytest.fixture
def patched_make_workspace(mocker: MockerFixture, workspace: Workspace) -> Generator:
def patched_make_workspace(
mocker: MockerFixture, workspace: FileWorkspace
) -> Generator:
def patched_make_workspace(*args: Any, **kwargs: Any) -> str:
return workspace.root
mocker.patch.object(
Workspace,
FileWorkspace,
"make_workspace",
new=patched_make_workspace,
)

View File

@@ -5,7 +5,7 @@ from pytest_mock import MockerFixture
from autogpt.agents import Agent
from autogpt.commands.execute_code import execute_python_file
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import (
copy_file_into_workspace,
@@ -32,7 +32,7 @@ def test_debug_code_challenge_a(
patched_api_requestor: MockerFixture,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""

View File

@@ -1,7 +1,7 @@
import pytest
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.basic_abilities.test_browse_website import USER_INPUTS
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -23,7 +23,7 @@ def test_information_retrieval_challenge_a(
patched_api_requestor: MockerFixture,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""

View File

@@ -1,7 +1,7 @@
import pytest
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -18,7 +18,7 @@ def test_information_retrieval_challenge_b(
patched_api_requestor: MockerFixture,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""

View File

@@ -1,7 +1,7 @@
import pytest
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -22,7 +22,7 @@ def test_information_retrieval_challenge_c(
patched_api_requestor: MockerFixture,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""

View File

@@ -4,7 +4,7 @@ import pytest
import yaml
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -19,7 +19,7 @@ def test_kubernetes_template_challenge_a(
patched_api_requestor: MockerFixture,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""

View File

@@ -2,7 +2,7 @@ import pytest
from pytest_mock import MockerFixture
from autogpt.config import Config
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -18,7 +18,7 @@ def test_memory_challenge_a(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""
@@ -44,7 +44,7 @@ def test_memory_challenge_a(
def create_instructions_files(
workspace: Workspace,
workspace: FileWorkspace,
num_files: int,
task_id: str,
base_filename: str = "instructions_",

View File

@@ -1,7 +1,7 @@
import pytest
from pytest_mock import MockerFixture
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import generate_noise, get_workspace_path, run_challenge
@@ -16,7 +16,7 @@ def test_memory_challenge_b(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""
@@ -44,7 +44,7 @@ def test_memory_challenge_b(
def create_instructions_files(
workspace: Workspace,
workspace: FileWorkspace,
level: int,
task_ids: list,
base_filename: str = "instructions_",

View File

@@ -2,7 +2,7 @@ import pytest
from pytest_mock import MockerFixture
from autogpt.commands.file_operations import read_file
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import generate_noise, get_workspace_path, run_challenge
@@ -17,7 +17,7 @@ def test_memory_challenge_c(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""
@@ -62,7 +62,7 @@ def test_memory_challenge_c(
def create_instructions_files(
workspace: Workspace,
workspace: FileWorkspace,
level: int,
task_ids: list,
base_filename: str = "instructions_",

View File

@@ -5,7 +5,7 @@ import pytest
from pytest_mock import MockerFixture
from autogpt.commands.file_operations import read_file
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
from tests.challenges.challenge_decorator.challenge_decorator import challenge
from tests.challenges.utils import get_workspace_path, run_challenge
@@ -21,7 +21,7 @@ def test_memory_challenge_d(
monkeypatch: pytest.MonkeyPatch,
level_to_run: int,
challenge_name: str,
workspace: Workspace,
workspace: FileWorkspace,
patched_make_workspace: pytest.fixture,
) -> None:
"""
@@ -173,7 +173,7 @@ def extract_beliefs(content: str) -> Dict[str, Dict[str, str]]:
def create_instructions_files(
workspace: Workspace,
workspace: FileWorkspace,
level: int,
test_phrases: list,
base_filename: str = "instructions_",

View File

@@ -7,8 +7,8 @@ from typing import Any, AsyncIterator
import pytest
from agbenchmark_config.benchmarks import run_specific_agent
from autogpt.file_workspace import FileWorkspace
from autogpt.logs import LogCycleHandler
from autogpt.workspace import Workspace
from tests.challenges.schema import Task
@@ -55,12 +55,12 @@ def setup_mock_log_cycle_agent_name(
)
def get_workspace_path(workspace: Workspace, file_name: str) -> str:
def get_workspace_path(workspace: FileWorkspace, file_name: str) -> str:
return str(workspace.get_path(file_name))
def copy_file_into_workspace(
workspace: Workspace, directory_path: Path, file_path: str
workspace: FileWorkspace, directory_path: Path, file_path: str
) -> None:
workspace_code_file_path = get_workspace_path(workspace, file_path)
code_file_path = directory_path / file_path

View File

@@ -10,11 +10,11 @@ from autogpt.agents.agent import Agent, AgentConfiguration, AgentSettings
from autogpt.app.main import _configure_openai_provider
from autogpt.config import AIProfile, Config, ConfigBuilder
from autogpt.core.resource.model_providers import ChatModelProvider, OpenAIProvider
from autogpt.file_workspace import FileWorkspace
from autogpt.llm.api_manager import ApiManager
from autogpt.logs.config import configure_logging
from autogpt.memory.vector import get_memory
from autogpt.models.command_registry import CommandRegistry
from autogpt.workspace import Workspace
pytest_plugins = [
"tests.integration.agent_factory",
@@ -44,8 +44,8 @@ def workspace_root(agent_data_dir: Path) -> Path:
@pytest.fixture()
def workspace(workspace_root: Path) -> Workspace:
workspace = Workspace(workspace_root, restrict_to_workspace=True)
def workspace(workspace_root: Path) -> FileWorkspace:
workspace = FileWorkspace(workspace_root, restrict_to_root=True)
workspace.initialize()
return workspace

View File

@@ -4,11 +4,13 @@ import orjson
import pytest
from autogpt.config import Config
from autogpt.file_workspace import FileWorkspace
from autogpt.memory.vector import JSONFileMemory, MemoryItem
from autogpt.workspace import Workspace
def test_json_memory_init_without_backing_file(config: Config, workspace: Workspace):
def test_json_memory_init_without_backing_file(
config: Config, workspace: FileWorkspace
):
index_file = workspace.root / f"{config.memory_index}.json"
assert not index_file.exists()
@@ -17,7 +19,9 @@ def test_json_memory_init_without_backing_file(config: Config, workspace: Worksp
assert index_file.read_text() == "[]"
def test_json_memory_init_with_backing_empty_file(config: Config, workspace: Workspace):
def test_json_memory_init_with_backing_empty_file(
config: Config, workspace: FileWorkspace
):
index_file = workspace.root / f"{config.memory_index}.json"
index_file.touch()
@@ -28,7 +32,7 @@ def test_json_memory_init_with_backing_empty_file(config: Config, workspace: Wor
def test_json_memory_init_with_backing_invalid_file(
config: Config, workspace: Workspace
config: Config, workspace: FileWorkspace
):
index_file = workspace.root / f"{config.memory_index}.json"
index_file.touch()

View File

@@ -6,16 +6,29 @@ from autogpt.app.setup import (
apply_overrides_to_ai_settings,
interactively_revise_ai_settings,
)
from autogpt.config.ai_profile import AIProfile
from autogpt.config import AIDirectives, Config
from autogpt.config.ai_profile import AIProfile
@pytest.mark.asyncio
async def test_apply_overrides_to_ai_settings():
ai_profile = AIProfile(ai_name="Test AI", ai_role="Test Role")
directives = AIDirectives(resources=["Resource1"], constraints=["Constraint1"], best_practices=["BestPractice1"])
directives = AIDirectives(
resources=["Resource1"],
constraints=["Constraint1"],
best_practices=["BestPractice1"],
)
apply_overrides_to_ai_settings(ai_profile, directives, override_name="New AI", override_role="New Role", replace_directives=True, resources=["NewResource"], constraints=["NewConstraint"], best_practices=["NewBestPractice"])
apply_overrides_to_ai_settings(
ai_profile,
directives,
override_name="New AI",
override_role="New Role",
replace_directives=True,
resources=["NewResource"],
constraints=["NewConstraint"],
best_practices=["NewBestPractice"],
)
assert ai_profile.ai_name == "New AI"
assert ai_profile.ai_role == "New Role"
@@ -27,7 +40,11 @@ async def test_apply_overrides_to_ai_settings():
@pytest.mark.asyncio
async def test_interactively_revise_ai_settings(config: Config):
ai_profile = AIProfile(ai_name="Test AI", ai_role="Test Role")
directives = AIDirectives(resources=["Resource1"], constraints=["Constraint1"], best_practices=["BestPractice1"])
directives = AIDirectives(
resources=["Resource1"],
constraints=["Constraint1"],
best_practices=["BestPractice1"],
)
user_inputs = [
"y",
@@ -41,7 +58,9 @@ async def test_interactively_revise_ai_settings(config: Config):
"",
]
with patch("autogpt.app.utils.clean_input", side_effect=user_inputs):
ai_profile, directives = await interactively_revise_ai_settings(ai_profile, directives, config)
ai_profile, directives = await interactively_revise_ai_settings(
ai_profile, directives, config
)
assert ai_profile.ai_name == "New AI"
assert ai_profile.ai_role == "New Role"

View File

@@ -11,7 +11,7 @@ import pytest
from autogpt.app.configurator import GPT_3_MODEL, GPT_4_MODEL, apply_overrides_to_config
from autogpt.config import Config, ConfigBuilder
from autogpt.workspace.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
def test_initial_values(config: Config) -> None:
@@ -122,7 +122,7 @@ def test_smart_and_fast_llms_set_to_gpt4(mock_list_models: Any, config: Config)
config.smart_llm = smart_llm
def test_missing_azure_config(workspace: Workspace) -> None:
def test_missing_azure_config(workspace: FileWorkspace) -> None:
config_file = workspace.get_path("azure_config.yaml")
with pytest.raises(FileNotFoundError):
ConfigBuilder.load_azure_config(config_file)
@@ -136,7 +136,7 @@ def test_missing_azure_config(workspace: Workspace) -> None:
assert azure_config["azure_model_to_deployment_id_map"] == {}
def test_azure_config(config: Config, workspace: Workspace) -> None:
def test_azure_config(config: Config, workspace: FileWorkspace) -> None:
config_file = workspace.get_path("azure_config.yaml")
yaml_content = """
azure_api_type: azure

View File

@@ -15,9 +15,9 @@ import autogpt.commands.file_operations as file_ops
from autogpt.agents.agent import Agent
from autogpt.agents.utils.exceptions import DuplicateOperationError
from autogpt.config import Config
from autogpt.file_workspace import FileWorkspace
from autogpt.memory.vector.memory_item import MemoryItem
from autogpt.memory.vector.utils import Embedding
from autogpt.workspace import Workspace
@pytest.fixture()
@@ -50,7 +50,7 @@ def test_file_name():
@pytest.fixture
def test_file_path(test_file_name: Path, workspace: Workspace):
def test_file_path(test_file_name: Path, workspace: FileWorkspace):
return workspace.get_path(test_file_name)
@@ -73,12 +73,12 @@ def test_file_with_content_path(test_file: TextIOWrapper, file_content, agent: A
@pytest.fixture()
def test_directory(workspace: Workspace):
def test_directory(workspace: FileWorkspace):
return workspace.get_path("test_directory")
@pytest.fixture()
def test_nested_file(workspace: Workspace):
def test_nested_file(workspace: FileWorkspace):
return workspace.get_path("nested/test_file.txt")
@@ -280,7 +280,7 @@ def test_append_to_file_uses_checksum_from_appended_file(
)
def test_list_files(workspace: Workspace, test_directory: Path, agent: Agent):
def test_list_files(workspace: FileWorkspace, test_directory: Path, agent: Agent):
# Case 1: Create files A and B, search for A, and ensure we don't return A and B
file_a = workspace.get_path("file_a.txt")
file_b = workspace.get_path("file_b.txt")

View File

@@ -3,7 +3,7 @@ from pathlib import Path
import pytest
from autogpt.workspace import Workspace
from autogpt.file_workspace import FileWorkspace
_WORKSPACE_ROOT = Path("home/users/monty/auto_gpt_workspace")
@@ -40,7 +40,7 @@ _INACCESSIBLE_PATHS = (
"test_folder/{null_byte}",
"test_folder/{null_byte}test_file.txt",
],
Workspace.NULL_BYTES,
FileWorkspace.NULL_BYTES,
)
]
+ [
@@ -68,7 +68,7 @@ def inaccessible_path(request):
def test_sanitize_path_accessible(accessible_path, workspace_root):
full_path = Workspace._sanitize_path(
full_path = FileWorkspace._sanitize_path(
accessible_path,
root=workspace_root,
restrict_to_root=True,
@@ -79,7 +79,7 @@ def test_sanitize_path_accessible(accessible_path, workspace_root):
def test_sanitize_path_inaccessible(inaccessible_path, workspace_root):
with pytest.raises(ValueError):
Workspace._sanitize_path(
FileWorkspace._sanitize_path(
inaccessible_path,
root=workspace_root,
restrict_to_root=True,
@@ -87,13 +87,13 @@ def test_sanitize_path_inaccessible(inaccessible_path, workspace_root):
def test_get_path_accessible(accessible_path, workspace_root):
workspace = Workspace(workspace_root, True)
workspace = FileWorkspace(workspace_root, True)
full_path = workspace.get_path(accessible_path)
assert full_path.is_absolute()
assert full_path.is_relative_to(workspace_root)
def test_get_path_inaccessible(inaccessible_path, workspace_root):
workspace = Workspace(workspace_root, True)
workspace = FileWorkspace(workspace_root, True)
with pytest.raises(ValueError):
workspace.get_path(inaccessible_path)