Skip to content

fix(chat): route /api/repos/{repo_id}/chat/messages by workspace_sessions#146

Open
enyr-srl wants to merge 1 commit intorepowise-dev:mainfrom
enyr-srl:fix/chat-workspace-mode
Open

fix(chat): route /api/repos/{repo_id}/chat/messages by workspace_sessions#146
enyr-srl wants to merge 1 commit intorepowise-dev:mainfrom
enyr-srl:fix/chat-workspace-mode

Conversation

@enyr-srl
Copy link
Copy Markdown

@enyr-srl enyr-srl commented May 8, 2026

fix(chat): route /api/repos/{repo_id}/chat/messages by workspace_sessions

Summary

In workspace mode, every non-primary repo's chat returns
404 Repository <id> not found even though the same id is listed
in both GET /api/repos and GET /api/workspace.repos[].repo_id.
The chat router was the only /api/repos/{repo_id}/... endpoint
not honouring app.state.workspace_sessions.

The conversation endpoints (GET /chat/conversations, etc.)
already work correctly because they use Depends(get_db_session),
which routes by repo_id automatically. chat_messages couldn't
use that dep — it needs the factory (not a single session) so it
can open multiple sessions over the SSE lifetime — so it was
hand-wiring request.app.state.session_factory and missing the
workspace branch.

Fix

  • Extract the factory-resolution logic from get_db_session into
    two reusable helpers in deps.py:
    • resolve_session_factory(app_state, repo_id) — pure
      function, same logic as the existing private helper in
      routers/repos.py.
    • resolve_request_session_factory(request) — request-scoped
      sibling that reads repo_id from path/query params (mirrors
      what get_db_session encodes).
  • chat_messages calls resolve_request_session_factory(request)
    instead of request.app.state.session_factory directly.
  • routers/repos.py::_resolve_repo_session_factory is now a
    one-line alias around the shared helper, removing the duplicate
    logic.

Tests

New regression test tests/unit/server/test_chat_workspace.py:

  • test_chat_messages_resolves_non_primary_repo_in_workspace_mode
    — POST to a non-primary repo_id no longer returns 404.
    Verified to fail on the unpatched source with the exact
    Repository <id> not found message.
  • test_chat_messages_still_finds_primary_repo — the
    single-factory fallback still works when workspace_sessions is
    empty (single-repo mode and the primary repo of a workspace).

All 126 existing tests/unit/server/ tests pass with the patch
(verified locally).

Repro (against an unpatched workspace deployment)

curl -X POST \
  http://localhost:7337/api/repos/<non-primary-id>/chat/messages \
  -H "Content-Type: application/json" \
  -d '{"message":"hi"}'
# {"detail":"Repository <non-primary-id> not found"}

The same <non-primary-id> appears in
GET /api/workspace.repos[].repo_id.

Test plan

  • New regression test fails on unpatched source with the exact
    user-visible 404 message
  • New regression test passes after the fix
  • All existing tests/unit/server/ tests still pass
  • Manual smoke test against a 2-repo workspace from a fresh
    install (reviewer)

Closes #145.

…ions

In workspace mode every non-primary repo's chat returns
``404 Repository <id> not found`` even though the same id is
listed in both ``GET /api/repos`` and
``GET /api/workspace.repos[].repo_id``. The chat router was the
only ``/api/repos/{repo_id}/...`` endpoint not honouring
``app.state.workspace_sessions``.

The conversation endpoints (``GET /chat/conversations``, etc.)
already work correctly because they use ``Depends(get_db_session)``,
which routes by ``repo_id`` automatically. ``chat_messages``
couldn't use that dep — it needs the *factory* (not a single
session) so it can open multiple sessions over the SSE lifetime —
so it was hand-wiring ``request.app.state.session_factory`` and
missing the workspace branch.

Fix:

* Extract the factory-resolution logic from ``get_db_session``
  into two reusable helpers in ``deps.py``:
    - ``resolve_session_factory(app_state, repo_id)`` — pure
      function, same logic as the existing private helper in
      ``routers/repos.py``.
    - ``resolve_request_session_factory(request)`` —
      request-scoped sibling that reads ``repo_id`` from
      path/query params (mirrors what ``get_db_session`` encodes).
* ``chat_messages`` calls
  ``resolve_request_session_factory(request)`` instead of
  ``request.app.state.session_factory`` directly.
* ``routers/repos.py::_resolve_repo_session_factory`` is now a
  one-line alias around the shared helper, removing the duplicate
  logic.

Test:

* New regression test ``tests/unit/server/test_chat_workspace.py``:
    - ``test_chat_messages_resolves_non_primary_repo_in_workspace_mode``
      — POST to a non-primary ``repo_id`` no longer returns 404.
      Verified to fail on the unpatched source with the exact
      ``Repository <id> not found`` message.
    - ``test_chat_messages_still_finds_primary_repo`` — the
      single-factory fallback still works when
      ``workspace_sessions`` is empty (single-repo mode and the
      primary repo of a workspace).
* All 126 existing ``tests/unit/server/`` tests pass with the patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Chat 404 for non-primary repos in workspace mode

1 participant