Skip to content

feat(desktop): add LiteLLM Gateway provider preset - #463

Merged
Sun-sunshine06 merged 1 commit into
OpenCoworkAI:mainfrom
Lxr-max:feat/litellm-preset
Oct 4, 2026
Merged

Sun-sunshine06 merged 1 commit into
OpenCoworkAI:mainfrom
Lxr-max:feat/litellm-preset

Conversation

@Lxr-max

@Lxr-max Lxr-max commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds a slim LiteLLM Gateway preset so users with an existing LiteLLM proxy can connect without hand-rolling a custom provider. It reuses what main already has: the PROXY_PRESETS list (same shape as the Requesty preset in #397), the Add provider menu 鈫?AddCustomProviderModal prefill path (same as CLIProxyAPI), and the keyless requiresApiKey flag from 71dbd2f. No new IPC, schema, or dependencies, and LiteLLM is not bundled.

  • packages/shared: new litellm entry in PROXY_PRESETS (provider: 'openai', baseUrl: 'http://localhost:4000/v1').
  • apps/desktop: an Add provider 鈫?LiteLLM Gateway menu item opens the custom-provider modal with the name, the base URL (read from the shared preset), and the openai-chat wire filled in. It starts in keyless mode (requiresApiKey: false), which matches a LiteLLM proxy with no master_key set. Users can untick it and paste a master or virtual key. initialValues gains two optional fields, requiresApiKey and hint. Edit mode is unchanged because editTarget still wins.
  • packages/i18n: settings.providers.litellm.{presetName,presetDescription,hint} in en / zh-CN / es / pt-BR.
  • The private-network test opt-in is not pre-checked, on purpose. The CLIProxyAPI preset works the same way. The hint tells users to tick it for localhost.

This replaces the closed #419, which was too big for one PR. Connection diagnostics for LiteLLM 401/404 and the Chrome-timeout CI change are left for later PRs.

Type of change

  • Bug fix
  • New feature
  • Refactor (no behavior change)
  • Documentation
  • Build / CI / tooling
  • Breaking change

Linked issue

Refs #208

Replaces #419 (closed).

Checklist

  • I checked the linked issue / relevant context before starting
  • pnpm lint && pnpm typecheck && pnpm test passes locally (lint and typecheck pass. Under Node 22, all 2088 desktop tests that loaded passed, but 29 desktop suites that need the Electron binary would not load, because Electron isn't installed in my environment. Every other workspace package passes.)
  • Added/updated tests for the change
  • Added a changeset (pnpm changeset) if user-visible
  • Updated docs if behavior changed (not needed: the preset documents itself in the menu and modal)

PRINCIPLES 搂5b

  • Compatibility: purely additive. Existing presets, stored configs, and edit flows are unchanged. requiresApiKey defaults to true unless a preset opts out.
  • Upgradeability: no on-disk or IPC schema changes. The saved provider is a normal custom OpenAI-compatible entry with the existing requiresApiKey field.
  • No bloat: no new dependencies. About 100 LOC across 10 files, including tests, a changeset, and 4 locales.
  • Elegance: reuses PROXY_PRESETS, the existing modal prefill path, and the keyless flag. There is no LiteLLM-specific branching in the modal, and the base URL lives in one place (getPresetById('litellm')).

Screenshots / recordings (UI changes)

No screenshot attached: the UI change is a new "LiteLLM Gateway" entry in the Add provider menu that opens the existing custom-provider modal prefilled with the name, http://localhost:4000/v1, openai-chat, "No API key required" checked, and a short hint. Covered by the new AddCustomProviderModal render test.

Add a LiteLLM Gateway entry to PROXY_PRESETS and the Settings add-provider menu. It pre-fills the OpenAI-compatible default http://localhost:4000/v1, starts in keyless mode via the existing requiresApiKey flag, and shows setup copy in all locales. LiteLLM is not bundled.

Closes OpenCoworkAI#208
@github-actions github-actions Bot added docs Documentation area:desktop apps/desktop (Electron shell, renderer) labels Oct 3, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • [Minor] Closes #208 may overstate the scope this PR delivers — the PR body itself says "Connection diagnostics for LiteLLM 401/404 and the Chrome-timeout CI change are left for later PRs", and the repo template (.github/PULL_REQUEST_TEMPLATE.md) says to use Closes #123 only when the PR fully resolves the issue and Refs #123 for partial slices. If #208's acceptance criteria cover connection diagnostics or other deferred work, this PR does not fully resolve it. Note: I could not load the body of #208 in this run, so this is based on the PR's own description plus the template rule, not a line-by-line diff against the issue.
    Suggested fix: if #208 includes the deferred diagnostics/CI work, change the link to Refs #208 and keep (or open) a follow-up issue for the 401/404 diagnostics and CLI change.

  • [Nit] The "base URL lives in one place" / single-source claim in the PR body is only partially true — baseUrl is read from the shared preset (apps/desktop/src/renderer/src/components/settings/ModelsTab.tsx:1053), but http://localhost:4000/v1 is also baked into the localized hint strings in all four locales (packages/i18n/src/locales/en.json:695, es.json:519, pt-BR.json:496, zh-CN.json:695) and the provider name: 'LiteLLM Gateway' is hardcoded there too while also existing as PROXY_PRESETS[].label (packages/shared/src/proxy-presets.ts:63) and presetName. Not blocking; if you want it truly single-source, derive name from getPresetById('litellm')?.label and/or drop the explicit URL from the hint text.
    Suggested fix: low priority — either accept the duplication (it matches the existing CLIProxyAPI pattern) or centralize the name and URL.

Questions

  • The LiteLLM preset opens with keyless mode on (requiresApiKey: false, ModelsTab.tsx:1055), which is the trigger for endpoint auto-discovery (buildEndpointDiscoveryPayload returns a payload only when requiresApiKey === false, AddCustomProviderModal.tsx:110). If the modal auto-runs discovery on open, it would run against the localhost default with the private-network opt-in still unchecked, producing a failed discovery before the user ticks the box. Does the existing CLIProxyAPI preset also open keyless (i.e., is this already-shipped behavior), or is LiteLLM the first keyless-by-default localhost preset? If it's new, consider pre-checking the private-network toggle for localhost defaults, or deferring auto-discovery until the opt-in is set. (I couldn't verify the modal's on-mount discovery effect from the diff alone.)

Summary

Review mode: initial

Directionally sound and small: no new dependencies, no IPC/schema changes, no LiteLLM bundling, and a changeset is present for all three affected packages (@open-codesign/shared, @open-codesign/i18n, @open-codesign/desktop). The requiresApiKey init change (editTarget ?? initialValues)?.requiresApiKey !== false correctly preserves edit-mode precedence and only affects create-mode presets, matching the stated Compatibility/Upgradeability claims. The new tests (proxy-presets.test.ts, the added AddCustomProviderModal case) adequately cover the preset shape and prefill/hint rendering.

The only substantive item is the linked-issue claim (#208) — please confirm the deferred connection diagnostics are outside #208's acceptance criteria before keeping Closes #208. Residual risks: no test exercises the new onAddLiteLLM menu handler in ModelsTab, and the keyless + private-network interaction for a localhost default is unverified.

Testing

Not run (automation). Suggested additions: a ModelsTab test asserting the LiteLLM menu item calls the handler with the preset base URL and requiresApiKey: false, and (if applicable) a modal test confirming discovery behavior for a keyless localhost preset when private-network testing is off.

Open-CoDesign Bot

@Lxr-max

Lxr-max commented Oct 4, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. I checked #208, the CLIProxyAPI preset, and when the modal starts discovery. No code change.

Closes #208. #208 also asks for LiteLLM-aware connection diagnostics. This PR does not add 401/404 hints; those stay a follow-up, along with the Chrome-timeout CI note from the earlier larger attempt. What landed is the preset: add LiteLLM Gateway without hand-filling a custom provider, keyless or a master/virtual key, and model discovery through the existing endpoint test. The Closes #208 line in the PR description and on the commit should be Refs #208 so merge leaves the issue open for diagnostics. I am not rewriting the commit in this push.

Single source for the name and URL. The base URL the modal saves comes from getPresetById('litellm')?.baseUrl (http://localhost:4000/v1 in PROXY_PRESETS). The four locale hints repeat that URL inside the setup sentence, which is the text translators edit. The menu label is settings.providers.litellm.presetName; the modal title and PROXY_PRESETS[].label use the same product name, LiteLLM Gateway. CLIProxyAPI is the same shape: a hardcoded display name and http://127.0.0.1:8317 in the menu handler, plus locale strings. I am keeping that pattern.

Keyless localhost discovery. CLIProxyAPI does not open keyless. It omits requiresApiKey, and the modal treats that as required. LiteLLM is the preset that starts with requiresApiKey: false and http://localhost:4000/v1. Discovery does not run on open. scheduleDiscovery runs from the base URL field, the wire control, the TLS toggle, the private-network checkbox, and the keyless checkbox. There is no mount effect. With the private-network box unchecked, opening the preset leaves discovery idle, so the modal does not call testEndpoint on localhost before the user opts in. Checking “allow private-network testing” calls scheduleDiscovery with allowPrivateNetwork: true and the current keyless state, which is the point where a localhost gateway can be listed. The box stays unchecked until that click. handleConfigV1TestEndpoint rejects non-public URLs unless allowPrivateNetwork is true, and the hint already tells the user to allow it for localhost.

Menu handler test. There is no ModelsTab render harness. The handler only stores the preset fields the modal test already covers: keyless, the preset base URL, and the hint. I am not adding a second harness for that wiring.

@Sun-sunshine06
Sun-sunshine06 merged commit 6799d55 into OpenCoworkAI:main Oct 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:desktop apps/desktop (Electron shell, renderer) docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants