mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 12:52:11 +03:00
* feat(providers): rebase ClinePass dual-auth (OAuth + BYOK) onto release/v3.8.47
ClinePass now offers both sign-in methods on its dashboard page: OAuth
(reusing the Cline WorkOS flow, primary "Connect" button) or a pasted
BYOK API key ("Manual API key"), instead of only the API-key-only
provider shipped in #5942.
- Registry: authType oauth + oauth urls, alias aligned to "cp" (matches
the OAUTH_PROVIDERS catalog alias so <alias>/<modelId> routing
resolves); keeps the #6165 forceStream:true fix (streaming-only API).
- Executor: new buildClinepassHeaders() (src/shared/utils/clineAuth.ts)
picks buildClineHeaders() for an OAuth accessToken or a plain Bearer +
Cline identification headers for a BYOK key — extracted to a leaf
module to avoid growing the frozen open-sse/executors/default.ts.
- Refresh: dispatch clinepass to the shared refreshClineToken() (was
falling through to the generic refresh and failing silently).
- Catalog: admit the BYOK path through a dedicated
DUAL_AUTH_APIKEY_PROVIDER_IDS gate (src/lib/providers/catalog.ts) so
POST /api/providers accepts an apikey connection without flipping
isOAuth off (which would break the primary Connect->OAuth routing).
- Dashboard: render both "Connect" + "Manual API key" buttons for
clinepass (ConnectionsHeaderToolbar.tsx, EmptyConnectionsPlaceholder.tsx).
- Dedup: removed the now-redundant API-key-only APIKEY_PROVIDERS_GATEWAYS
entry so ClinePass is listed once (OAuth-primary).
- oauth.ts: added the clinepass catalog entry (was reverted by staleness
during rebase); src/lib/oauth/providers/index.ts: clinepass -> cline.
This branch was ~167 commits / weeks behind release/v3.8.47; a real
merge surfaced 61 conflicting files, several of which are already-shipped
fixes (forceStream #6165, zed-hosted, requesty, agentrouter CC-wire-image,
NVIDIA/Mistral/kimi executor fixes, chatCore hardening) that a naive
resolution would have silently reverted. Reconstructed clean on top of
current release/v3.8.47, isolating and re-applying only the clinepass
dual-auth feature and preserving every already-shipped fix untouched.
tokenRefresh.ts's frozen-file cap raised by the irreducible 1-line
`case "clinepass":` switch label (config/quality/file-size-baseline.json,
justified inline); open-sse/executors/default.ts stays under its cap via
the buildClinepassHeaders() extraction.
Regression guard: tests/unit/clinepass-provider.test.ts (15/15, extended
with the dual-auth admission-gate and alias-consistency guards).
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* test(providers): update APIKEY_PROVIDERS spread-merge count 171->170
The ClinePass dual-auth rebase (this PR) removed the now-redundant
API-key-only APIKEY_PROVIDERS_GATEWAYS.clinepass entry (dedup — clinepass
is OAuth-primary now, with its BYOK path admitted through the
DUAL_AUTH_APIKEY_PROVIDER_IDS gate instead of a second catalog entry),
which drops the total APIKEY_PROVIDERS spread-merge count by one.
tests/unit/providers-constants-split.test.ts hardcoded the prior count
(171); updated to 170 to match, confirmed via CI (Unit Tests fast-path
1/2 and 2/2 both failed on the stale count).
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(oauth): register clinepass in PROVIDERS enum to fix Unknown provider error
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* chore(test): rebaseline oauth-providers-config.test.ts frozen size for clinepass entries
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(changelog): re-restore #6126 bullet after release sync
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: hajilok <hajilok@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
/**
|
|
* Cline (cline.bot) auth-shape helpers.
|
|
*
|
|
* Cline's API expects the bearer token to be prefixed with `workos:` (the
|
|
* upstream auth provider), and a set of Cline client-identification headers
|
|
* (HTTP-Referer / X-Title / X-CLIENT-* / X-PLATFORM*). Plain `Bearer <token>`
|
|
* without the `workos:` prefix is rejected upstream, so every Cline request
|
|
* must route its headers through `buildClineHeaders()`.
|
|
*/
|
|
|
|
const APP_VERSION = process.env.npm_package_version || "0.0.0";
|
|
|
|
/**
|
|
* Normalize a raw Cline token into the `workos:`-prefixed access-token shape
|
|
* Cline expects. Idempotent: a token that already carries the prefix is
|
|
* returned untouched. Non-string / empty input yields an empty string.
|
|
*/
|
|
export function getClineAccessToken(token: unknown): string {
|
|
if (typeof token !== "string") return "";
|
|
const trimmed = token.trim();
|
|
if (!trimmed) return "";
|
|
return trimmed.startsWith("workos:") ? trimmed : `workos:${trimmed}`;
|
|
}
|
|
|
|
/**
|
|
* Build the full `Authorization` header value for a Cline request, or an empty
|
|
* string when no usable token is present.
|
|
*/
|
|
export function getClineAuthorizationHeader(token: unknown): string {
|
|
const accessToken = getClineAccessToken(token);
|
|
return accessToken ? `Bearer ${accessToken}` : "";
|
|
}
|
|
|
|
/**
|
|
* Build the complete Cline client header set, optionally merged with caller
|
|
* extras. The `Authorization` header is only added when a usable token is
|
|
* present (so callers can build probe headers without a token).
|
|
*/
|
|
export function buildClineHeaders(
|
|
token: unknown,
|
|
extraHeaders: Record<string, string> = {}
|
|
): Record<string, string> {
|
|
const authorization = getClineAuthorizationHeader(token);
|
|
const headers: Record<string, string> = {
|
|
"HTTP-Referer": "https://cline.bot",
|
|
"X-Title": "Cline",
|
|
"User-Agent": `OmniRoute/${APP_VERSION}`,
|
|
"X-PLATFORM": process.platform || "unknown",
|
|
"X-PLATFORM-VERSION": process.version || "unknown",
|
|
"X-CLIENT-TYPE": "omniroute",
|
|
"X-CLIENT-VERSION": APP_VERSION,
|
|
"X-CORE-VERSION": APP_VERSION,
|
|
"X-IS-MULTIROOT": "false",
|
|
...extraHeaders,
|
|
};
|
|
|
|
if (authorization) {
|
|
headers.Authorization = authorization;
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
/**
|
|
* Build headers for a ClinePass request. ClinePass is dual-auth: an OAuth
|
|
* connection (workos:-prefixed token in `accessToken`) needs the full Cline
|
|
* client header set from `buildClineHeaders()`; a BYOK API-key connection
|
|
* (`sk_...` key, #5942) sends the key as a plain Bearer token — no `workos:`
|
|
* prefix — alongside the Cline identification headers.
|
|
*/
|
|
export function buildClinepassHeaders(
|
|
credentials: { accessToken?: unknown; apiKey?: unknown } | null | undefined,
|
|
effectiveKey?: string
|
|
): Record<string, string> {
|
|
if (credentials?.accessToken) {
|
|
return buildClineHeaders(credentials.accessToken);
|
|
}
|
|
const headers: Record<string, string> = {
|
|
"HTTP-Referer": "https://cline.bot",
|
|
"X-Title": "Cline",
|
|
};
|
|
const byokKey = effectiveKey || (credentials?.apiKey as string | undefined);
|
|
if (byokKey) headers.Authorization = `Bearer ${byokKey}`;
|
|
return headers;
|
|
}
|