fix: restore legacy /projects/projects endpoint for older CLI versions

Older versions of basic-memory CLI (v0.17.4 and earlier) call
GET /projects/projects to list projects. This endpoint was removed
when we migrated to v2 routers.

Add explicit route at /projects/projects (without trailing slash) to
avoid 307 redirects that the cloud proxy doesn't follow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
phernandez
2026-02-02 19:54:34 -06:00
parent 24ca5f6804
commit a0e754b7ae
2 changed files with 34 additions and 0 deletions
+8
View File
@@ -4,6 +4,7 @@ from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException
from fastapi.exception_handlers import http_exception_handler
from fastapi.routing import APIRouter
from loguru import logger
from basic_memory import __version__ as version
@@ -18,6 +19,7 @@ from basic_memory.api.v2.routers import (
prompt_router as v2_prompt,
importer_router as v2_importer,
)
from basic_memory.api.v2.routers.project_router import list_projects
from basic_memory.config import init_api_logging
from basic_memory.services.initialization import initialize_app
@@ -82,6 +84,12 @@ app.include_router(v2_project, prefix="/v2")
# Legacy web app proxy paths (compat with /proxy/projects/projects)
app.include_router(v2_project, prefix="/proxy/projects")
# Legacy v1 compat: older CLI versions call GET /projects/projects (without trailing slash)
# Using router mount causes 307 redirect which proxy doesn't follow, so add explicit route
legacy_router = APIRouter(tags=["legacy"])
legacy_router.add_api_route("/projects/projects", list_projects, methods=["GET"])
app.include_router(legacy_router)
# V2 routers are the only public API surface
+26
View File
@@ -340,3 +340,29 @@ async def test_resolve_project_empty_identifier(client: AsyncClient, v2_projects
response = await client.post(f"{v2_projects_url}/resolve", json=resolve_data)
assert response.status_code == 422 # Validation error
# --- Legacy v1 compatibility tests ---
@pytest.mark.asyncio
async def test_legacy_v1_list_projects_endpoint(client: AsyncClient, test_project: Project):
"""Test that the legacy /projects/projects endpoint still works for older CLI versions.
This endpoint was removed when we migrated to v2 but older versions of
basic-memory-cloud CLI still call it for `bm project list`.
Note: The route must be without trailing slash to avoid 307 redirects
that the cloud proxy doesn't follow.
"""
# The legacy v1 endpoint was at /projects/projects (no trailing slash)
response = await client.get("/projects/projects")
assert response.status_code == 200
data = response.json()
assert "projects" in data
assert "default_project" in data
# Verify the test project is in the list
project_names = [p["name"] for p in data["projects"]]
assert test_project.name in project_names