Skip to content

feat: per-provider user_provided API key UI + real expiry on chat sends (#70)#81

Merged
garfiec merged 1 commit into
developfrom
feat/issue-70-user-provided-keys-ui
May 11, 2026
Merged

feat: per-provider user_provided API key UI + real expiry on chat sends (#70)#81
garfiec merged 1 commit into
developfrom
feat/issue-70-user-provided-keys-ui

Conversation

@garfiec

@garfiec garfiec commented May 10, 2026

Copy link
Copy Markdown
Owner

Closes #70.

Summary

  • Adds Settings → Provider API Keys and a "Set API Key" CTA on greyed endpoint groups in the chat model selector. Mobile-only users on a user_provided server can now configure and revoke per-endpoint keys without the web client — unblocks the smoking-gun scenarios behind Incorrect passing of API tokens #60.
  • Replaces the key: "never" literal in EndpointClassifier with the real per-endpoint expiry from getKeyExpiry. The backend's checkUserKeyExpiry guard now sees the truth instead of a silent-pass Invalid Date.
  • Maps the typed no_user_key / expired_user_key SSE errors to a snackbar that deep-links into the Set API Key dialog for the offending endpoint, instead of a generic SSE failure.
  • Fixes the latent KeysApi bugs called out in Per-provider user_provided API key UI + send real expiry on chat sends #70 (wrong getKeyExpiry signature, fictional UserKey.value, updateKey typed against a non-existent response body).

What changed

  • New KeyState domain type and a KeyInvalidation SharedFlow on KeyRepository — single source of truth for per-endpoint key state, with cross-screen refresh when a set/revoke happens elsewhere.
  • EndpointClassifier now takes the resolved expiry and writes the real ISO string (or "never" only when the user genuinely has a non-expiring key) onto the chat-send body.
  • Provider API Keys screen + Set Key dialog under Settings. Service-key JSON paths get live validation; the dialog default matches the web client's 12-hour expiry. Refresh is reactive — admin-side endpoint changes and post-save model-list updates flow through without a manual reload.
  • Chat model selector renders user-provide endpoints whose key is Unset/Expired as greyed with a primary-tinted "⚙ Set API Key" chip. Tapping the chip deep-links straight into the dialog for that endpoint. Comparison-mode sheet uses the same presentation. Transient fetch errors (e.g. a 401 mid-auth-refresh) preserve the previously-resolved row state instead of flashing every endpoint to greyed.
  • Navigator.navigateToProviderKeys(endpointName) with top-of-stack dedup so rapid double-taps don't push duplicate entries.
  • Full per-endpoint form parity with the web SetKeyDialog: Azure (4-field quad → nested JSON envelope), OpenAI / Assistants (apiKey + rendered-but-optional baseURL when userProvideURL=true, matching the upstream isOpenAIBase skip), Custom (<name> API Key / <name> API URL interpolated labels, baseURL required when userProvideURL=true), Google (paste-or-import service-account JSON with client-side client_email/project_id/private_key validation + optional Gemini API key, marshalled as { GOOGLE_SERVICE_KEY, GOOGLE_API_KEY }), Bedrock (structured { accessKeyId, secretAccessKey, sessionToken? } — deliberately diverges from web's OtherConfig fallthrough; documented in code), and the single-input fallback for everything else. azureAssistants intentionally routes to the plain OpenAI form to mirror upstream's SetKeyDialog.tsx:215 behavior (documented inline).
  • 10 new test files cover wire parsing, parallel fan-out + fail-closed semantics, the cancel-and-restart refresh race in ProviderKeysViewModel, navigation dedup, and KeysApi real-wire decoding. The Set Key dialog has 40 unit tests covering every form variant's wire envelope, validation rules, expiry handling, file picker, and revoke flow.

Screenshots

Greyed endpoint + Set API Key chip Provider Keys screen Set Key dialog
Model selector with Set API Key chip Provider API Keys list Set API Key for OpenRouter dialog

Captured on Pixel_10_Pro_Fold AVD against a server with an OpenRouter (userProvide) endpoint and no key set. Tapping the "Set API Key" chip in the model selector deep-links directly into the Set Key dialog over the Provider Keys screen.

@github-actions

github-actions Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Android debug APK

Artifact: librechat-android-debug-81
Download: librechat-android-debug-81.zip
Retention: 90 days
Commit: 231d21e739ee310643cf5cae88495bf6c9ed4127

Download requires a GitHub login. Installs over previous debug builds without uninstalling (stable signing key).

garfiec added a commit that referenced this pull request May 10, 2026
garfiec added a commit that referenced this pull request May 10, 2026
garfiec added a commit that referenced this pull request May 10, 2026
@garfiec garfiec self-assigned this May 10, 2026
@garfiec garfiec force-pushed the feat/issue-70-user-provided-keys-ui branch 2 times, most recently from 865d2ad to 174426c Compare May 11, 2026 01:32
Adds a Provider API Keys screen under Settings → Security and a "Set API Key"
CTA on greyed endpoint groups in the chat model selector for endpoints
configured with userProvide / userProvideURL. Mirrors the LibreChat web UX
so mobile-only users can unblock user-provided endpoints without the web app.

- core/model: promote KeyState to shared domain; add KeyInvalidation and
  ProviderKeyName helpers; ExpiredUserKey.endpoint is nullable
- core/data: KeyRepository emits invalidation events (replay=0, DROP_OLDEST)
  for cross-screen refresh after set/revoke
- feature/settings: ProviderKeysScreen + SetProviderKeyDialog with
  cancel-and-restart refresh and merge-on-cancel so the just-mutated row
  survives a concurrent endpointConfigs emission
- feature/chat: EndpointKeyStatusDelegate fans out per-endpoint key state,
  ModelSelectorSheet renders greyed groups with a Set API Key chip, and
  UserKeyError snackbars deep-link to the dialog
- shared/navigation: Navigator.navigateToProviderKeys(endpointName) with
  top-of-stack dedup
@garfiec garfiec force-pushed the feat/issue-70-user-provided-keys-ui branch from 174426c to 231d21e Compare May 11, 2026 22:52
@garfiec garfiec merged commit 266c3af into develop May 11, 2026
5 checks passed
@garfiec garfiec deleted the feat/issue-70-user-provided-keys-ui branch May 11, 2026 23:14
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.

Per-provider user_provided API key UI + send real expiry on chat sends

2 participants