diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..98ec385 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,32 @@ +name: Test Suite + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.11, 3.12, 3.13] + continue-on-error: true + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install .[dev] + + - name: Run tests + run: | + python -m pytest tests/ -v \ No newline at end of file diff --git a/nanobot/channels/matrix.py b/nanobot/channels/matrix.py index 0d7a908..3f3f132 100644 --- a/nanobot/channels/matrix.py +++ b/nanobot/channels/matrix.py @@ -149,13 +149,22 @@ class MatrixChannel(BaseChannel): name = "matrix" display_name = "Matrix" - def __init__(self, config: Any, bus: MessageBus): + def __init__( + self, + config: Any, + bus: MessageBus, + *, + restrict_to_workspace: bool = False, + workspace: str | Path | None = None, + ): super().__init__(config, bus) self.client: AsyncClient | None = None self._sync_task: asyncio.Task | None = None self._typing_tasks: dict[str, asyncio.Task] = {} - self._restrict_to_workspace = False - self._workspace: Path | None = None + self._restrict_to_workspace = bool(restrict_to_workspace) + self._workspace = ( + Path(workspace).expanduser().resolve(strict=False) if workspace is not None else None + ) self._server_upload_limit_bytes: int | None = None self._server_upload_limit_checked = False diff --git a/tests/test_commands.py b/tests/test_commands.py index 583ef6f..9bd107d 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -1,3 +1,4 @@ +import re import shutil from pathlib import Path from unittest.mock import AsyncMock, MagicMock, patch @@ -11,6 +12,12 @@ from nanobot.providers.litellm_provider import LiteLLMProvider from nanobot.providers.openai_codex_provider import _strip_model_prefix from nanobot.providers.registry import find_by_model + +def _strip_ansi(text): + """Remove ANSI escape codes from text.""" + ansi_escape = re.compile(r'\x1b\[[0-9;]*m') + return ansi_escape.sub('', text) + runner = CliRunner() @@ -199,10 +206,11 @@ def test_agent_help_shows_workspace_and_config_options(): result = runner.invoke(app, ["agent", "--help"]) assert result.exit_code == 0 - assert "--workspace" in result.stdout - assert "-w" in result.stdout - assert "--config" in result.stdout - assert "-c" in result.stdout + stripped_output = _strip_ansi(result.stdout) + assert re.search(r'-{1,2}workspace', stripped_output) + assert re.search(r'-w', stripped_output) + assert re.search(r'-{1,2}config', stripped_output) + assert re.search(r'-c', stripped_output) def test_agent_uses_default_config_when_no_workspace_or_config_flags(mock_agent_runtime):