mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
2e5813d31e
Refactor CLI commands to use typed ProjectClient instead of raw HTTP calls, and add workspace metadata to cloud project listings so users can distinguish personal vs organization projects. Key changes: - 🔧 CLI commands now use ProjectClient typed API clients instead of call_get/call_post with manual URL construction - 🏢 Cloud project listings include workspace_name, workspace_type, and workspace_tenant_id for each cloud-sourced project - Pass config.default_workspace when fetching cloud projects via _fetch_cloud_projects() and CLI list_projects - Add --workspace flag to `bm project list` for explicit workspace override - Add "Workspace" column to CLI project list table - Add `bm tool list-projects` and `bm tool list-workspaces` JSON commands - Comprehensive tests for workspace passthrough, merge behavior, and CLI routing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
"""Regression tests for project info error handling."""
|
|
|
|
from contextlib import asynccontextmanager
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
import typer
|
|
from mcp.server.fastmcp.exceptions import ToolError
|
|
from typer.testing import CliRunner
|
|
|
|
from basic_memory.cli.app import app
|
|
from basic_memory.mcp.clients.project import ProjectClient
|
|
import basic_memory.cli.commands.command_utils as command_utils
|
|
import basic_memory.cli.commands.project as project_cmd # noqa: F401
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_info_cloud_config_error_has_clear_message(monkeypatch, capsys):
|
|
"""Cloud internal proxy config failures should surface actionable guidance."""
|
|
|
|
@asynccontextmanager
|
|
async def fake_get_client(project_name=None):
|
|
yield object()
|
|
|
|
async def fake_get_active_project(client, project, context):
|
|
return SimpleNamespace(external_id="proj-123")
|
|
|
|
async def fake_get_info(self, project_external_id):
|
|
raise ToolError("Internal proxy error: Project 'demo' not found in configuration")
|
|
|
|
monkeypatch.setattr(command_utils, "get_client", fake_get_client)
|
|
monkeypatch.setattr(command_utils, "get_active_project", fake_get_active_project)
|
|
monkeypatch.setattr(ProjectClient, "get_info", fake_get_info)
|
|
|
|
with pytest.raises(typer.Exit) as exc:
|
|
await command_utils.get_project_info("demo")
|
|
|
|
assert exc.value.exit_code == 1
|
|
captured = capsys.readouterr()
|
|
combined_output = captured.out + captured.err
|
|
assert "Project info failed: cloud returned an internal configuration error" in combined_output
|
|
assert "bm project list" in combined_output
|
|
assert "--cloud" in combined_output
|
|
|
|
|
|
def test_project_info_does_not_print_wrapper_exit_code(monkeypatch):
|
|
"""project info should not append a secondary 'Error getting project info: 1' line."""
|
|
|
|
async def fake_get_project_info(_project_name: str):
|
|
raise typer.Exit(1)
|
|
|
|
monkeypatch.setattr(project_cmd, "get_project_info", fake_get_project_info)
|
|
|
|
result = runner.invoke(app, ["project", "info", "demo"])
|
|
|
|
assert result.exit_code == 1
|
|
assert "Error getting project info" not in result.output
|