Repository navigation
feat(sidecar): add provider manifest client - #6083
KooshaPari wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new client, providerPluginManifestClient.ts, along with corresponding unit tests and documentation, to resolve and fetch the provider plugin manifest instead of hard-coding its route. The review feedback focuses on improving robustness and preventing potential runtime crashes. Specifically, it suggests checking if process is defined before accessing process.env to support non-Node environments, and adding defensive checks to ensure the fetched manifest and its providers array are valid before accessing their properties.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| export function resolveProviderPluginManifestUrl( | ||
| options: Pick<ProviderPluginManifestClientOptions, "baseUrl" | "manifestUrl"> = {}, | ||
| ): string { | ||
| const explicitUrl = options.manifestUrl?.trim(); | ||
| if (explicitUrl) return explicitUrl; | ||
|
|
||
| const envUrl = process.env[PROVIDER_PLUGIN_MANIFEST_ENV]?.trim(); | ||
| if (envUrl) return envUrl; | ||
|
|
||
| const baseUrl = options.baseUrl?.trim(); | ||
| if (baseUrl) { | ||
| return `${trimTrailingSlash(baseUrl)}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | ||
| } | ||
|
|
||
| const host = process.env.HOST || "127.0.0.1"; | ||
| const port = process.env.PORT || process.env.DASHBOARD_PORT || process.env.API_PORT || "20128"; | ||
| const protocol = process.env.OMNIROUTE_PUBLIC_PROTOCOL || "http"; | ||
| return `${protocol}://${host}:${port}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | ||
| } |
There was a problem hiding this comment.
In environments where process is not globally defined (such as browser environments or certain edge runtimes), directly accessing process.env will throw a ReferenceError. It is safer to check if process is defined before accessing its properties.
| export function resolveProviderPluginManifestUrl( | |
| options: Pick<ProviderPluginManifestClientOptions, "baseUrl" | "manifestUrl"> = {}, | |
| ): string { | |
| const explicitUrl = options.manifestUrl?.trim(); | |
| if (explicitUrl) return explicitUrl; | |
| const envUrl = process.env[PROVIDER_PLUGIN_MANIFEST_ENV]?.trim(); | |
| if (envUrl) return envUrl; | |
| const baseUrl = options.baseUrl?.trim(); | |
| if (baseUrl) { | |
| return `${trimTrailingSlash(baseUrl)}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | |
| } | |
| const host = process.env.HOST || "127.0.0.1"; | |
| const port = process.env.PORT || process.env.DASHBOARD_PORT || process.env.API_PORT || "20128"; | |
| const protocol = process.env.OMNIROUTE_PUBLIC_PROTOCOL || "http"; | |
| return `${protocol}://${host}:${port}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | |
| } | |
| export function resolveProviderPluginManifestUrl( | |
| options: Pick<ProviderPluginManifestClientOptions, "baseUrl" | "manifestUrl"> = {}, | |
| ): string { | |
| const explicitUrl = options.manifestUrl?.trim(); | |
| if (explicitUrl) return explicitUrl; | |
| const env = typeof process !== "undefined" ? process.env : {}; | |
| const envUrl = env[PROVIDER_PLUGIN_MANIFEST_ENV]?.trim(); | |
| if (envUrl) return envUrl; | |
| const baseUrl = options.baseUrl?.trim(); | |
| if (baseUrl) { | |
| return `${trimTrailingSlash(baseUrl)}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | |
| } | |
| const host = env.HOST || "127.0.0.1"; | |
| const port = env.PORT || env.DASHBOARD_PORT || env.API_PORT || "20128"; | |
| const protocol = env.OMNIROUTE_PUBLIC_PROTOCOL || "http"; | |
| return `${protocol}://${host}:${port}${PROVIDER_PLUGIN_MANIFEST_PATH}`; | |
| } |
| const manifest = (await response.json()) as ProviderPluginManifest; | ||
| if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.providers)) { |
There was a problem hiding this comment.
If the response body is empty, null, or not an object, accessing manifest.schemaVersion will throw a TypeError. Adding a null/object check ensures defensive programming and robust error handling.
| const manifest = (await response.json()) as ProviderPluginManifest; | |
| if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.providers)) { | |
| const manifest = (await response.json()) as ProviderPluginManifest; | |
| if (!manifest || manifest.schemaVersion !== 1 || !Array.isArray(manifest.providers)) { |
| export function getProviderPluginManifestEntryForModelFromManifest( | ||
| manifest: ProviderPluginManifest, | ||
| model: string | undefined, | ||
| ): ProviderPluginManifestEntry | null { | ||
| if (!model) return null; |
There was a problem hiding this comment.
To prevent runtime crashes if manifest is null/undefined or if manifest.providers is not an array, add defensive checks before accessing its properties.
| export function getProviderPluginManifestEntryForModelFromManifest( | |
| manifest: ProviderPluginManifest, | |
| model: string | undefined, | |
| ): ProviderPluginManifestEntry | null { | |
| if (!model) return null; | |
| export function getProviderPluginManifestEntryForModelFromManifest( | |
| manifest: ProviderPluginManifest, | |
| model: string | undefined, | |
| ): ProviderPluginManifestEntry | null { | |
| if (!model || !manifest || !Array.isArray(manifest.providers)) return null; |
|
Thank you, @KooshaPari 🙏 — closing as deferred, not rejected. This PR is the sidecar provider-manifest client — infra with no production consumer yet; lands once a native adapter reads it. It's one piece of the native-router backend workstream tracked in #5670, where I've cataloged all of these as the staged backlog for the 3.9.0/4.0 window (see my comment there). Merging these subsystem pieces individually into the hot |
Summary
koosha/sidecar-provider-manifest-clientbranch, not the stale local sidecar worktreeWhy
Bifrost, CLIProxyAPI, and future native sidecars should consume provider metadata through a stable HTTP manifest contract.
Validation
node --import tsx --test /tmp/omniroute-pr-6042-replay/tests/unit/provider-plugin-manifest-client.test.tsnode --import tsx --test /tmp/omniroute-pr-6042-replay/tests/unit/ui/quick-start-api-keys-link-5695.test.tsgit -C /tmp/omniroute-pr-6042-replay diff --check upstream/release/v3.8.44...HEAD