Skip to content

feat(companion): make all enabled backends selectable (Codex + Claude) - #418

Merged
claudiusthebot merged 1 commit into
fix/companion-react-targetfrom
feat/companion-backend-selector
Jul 1, 2026
Merged

feat(companion): make all enabled backends selectable (Codex + Claude)#418
claudiusthebot merged 1 commit into
fix/companion-react-targetfrom
feat/companion-backend-selector

Conversation

@claudiusthebot

Copy link
Copy Markdown
Collaborator

Problem

Dylan has both Codex and Claude backends enabled on the gateway, but the companion app only ever showed Claude. Root cause: the native bridge never exposed the backend layer at all β€” it had listModels/setModel but no concept of backends. (Telegram already has a /model backend submenu; the bridge was the gap.)

Fix β€” fully gateway-driven, nothing hardcoded

Bridge / engine

  • protocol: ClientChat gains backend; new BackendOption type.
  • server: GET /backends?chatId= and POST /backend. /backend always returns 200 with {ok,error} (the client decoder drops β‰₯400 bodies, and this is an app-level result).
  • index: listBackends() returns the enabled backends (listAvailableBackends(config), honouring enabledBackends) + the chat's active one; setBackend() mirrors the Telegram flow β€” verify enabled β†’ rebindChat β†’ pin override β†’ reset session/history/pulse (sessions aren't portable across backends) β†’ broadcast chat_updated + status. listModels() takes an optional chatId so the active-model hint tracks the chat's backend.

Client

  • BackendOption model; ClientChat.backend; BridgeClient.backends()/setBackend(); AppState.backends()/setBackend()/refreshModels(chatId).
  • Model sheet: a BACKEND chip row (only shown when >1 backend is enabled), a switching spinner, a "starts a fresh conversation" note, and a SnackBar on failure.

Whatever the gateway reports as enabled is what shows β€” no assumptions about specific backends/models.

Test

tsc --noEmit clean Β· flutter analyze lib β†’ No issues Β· native-frontend + bridge suites (25) pass.

Stacked on #417 β†’ #415 (native-frontend chain, avoids index.ts conflicts). Merge order: #415 β†’ #417 β†’ this. Diff here is only the backend-selector work.

πŸ€– Generated with Claude Code

Dylan has both the Claude and Codex backends enabled on the gateway but
the companion app only ever showed Claude β€” the native bridge never
exposed the backend layer. The multi-backend machinery already exists
(per-chat override, listAvailableBackends, rebindChat, the Telegram
/model backend submenu); this wires it through the bridge and adds a
picker to the app.

Bridge/engine:
- protocol: ClientChat gains `backend`; new BackendOption type.
- server: GET /backends (chatId) and POST /backend (chatId, backend).
  /backend always returns 200 with {ok,error} β€” the client's decoder
  drops >=400 bodies, and this is an app result, not an HTTP error.
- index: toClientChat reports the chat's backend; listBackends() returns
  the enabled backends + the chat's active one; setBackend() mirrors the
  Telegram flow β€” verify enabled, rebindChat, pin override, reset the
  session/history/pulse (sessions aren't portable across backends),
  broadcast chat_updated + status. listModels() now takes an optional
  chatId so the active-model hint tracks the chat's backend.

Client:
- BackendOption model; ClientChat.backend; BridgeClient.backends()/
  setBackend(); models() takes an optional chatId; AppState.backends()/
  setBackend()/refreshModels(chatId).
- model sheet: a BACKEND chip row (shown when >1 backend is enabled) with
  a switching spinner, a "starts a fresh conversation" note, and a
  SnackBar on failure. Backends are fully gateway-driven β€” nothing is
  hardcoded, so whatever the gateway reports as enabled is what shows.

tsc + flutter analyze clean; native-frontend + bridge suites (25) pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claudiusthebot
claudiusthebot merged commit cbc673f into fix/companion-react-target Jul 1, 2026
1 check passed
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.

1 participant