@jacobbd/relay-ai 0.12.4 → 0.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/dist/{chunk-LPOAO33X.js → chunk-5MEDBKPX.js} +163 -18
- package/dist/chunk-5MEDBKPX.js.map +1 -0
- package/dist/{chunk-2OEMU2WC.js → chunk-6ULON7FU.js} +2 -2
- package/dist/{chunk-5INR7PKO.js → chunk-VPDX24ZR.js} +463 -11
- package/dist/chunk-VPDX24ZR.js.map +1 -0
- package/dist/cli.js +130 -25
- package/dist/cli.js.map +1 -1
- package/dist/core/index.js +623 -34
- package/dist/core/index.js.map +1 -1
- package/dist/{manual-models-MZUHC3UN.js → manual-models-EIKWUZEG.js} +3 -3
- package/dist/{ui-command-XCYCQQRA.js → ui-command-U3L4LI2K.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-5INR7PKO.js.map +0 -1
- package/dist/chunk-LPOAO33X.js.map +0 -1
- /package/dist/{chunk-2OEMU2WC.js.map → chunk-6ULON7FU.js.map} +0 -0
- /package/dist/{manual-models-MZUHC3UN.js.map → manual-models-EIKWUZEG.js.map} +0 -0
- /package/dist/{ui-command-XCYCQQRA.js.map → ui-command-U3L4LI2K.js.map} +0 -0
package/README.md
CHANGED
|
@@ -564,6 +564,19 @@ For agent / alef-agent integration (boot flags, NDJSON): **[docs/AI-AGENTS.md](d
|
|
|
564
564
|
|
|
565
565
|
When OpenCode Zen is in your registry, `subscriptionFilter` controls which Zen models appear (`free` = free tier only; default = all Zen models). Add or change Zen via `relay-ai providers`.
|
|
566
566
|
|
|
567
|
+
Zen, Go, OpenRouter, and Command Code gateways can expose both Chat
|
|
568
|
+
Completions and Anthropic Messages. Relay uses current model metadata first, so
|
|
569
|
+
newly named models are not forced into a provider-wide format. For requests
|
|
570
|
+
Relay translates (OpenAI-format models, and any model used from Codex, Gemini,
|
|
571
|
+
or Antigravity), an early protocol or gateway error makes Relay retry the same
|
|
572
|
+
provider/account/model once on the sibling endpoint before streaming any
|
|
573
|
+
output. Successful choices are remembered for 24 hours; two failed attempts
|
|
574
|
+
pause protocol retries for five minutes. Authentication, quota, context,
|
|
575
|
+
moderation, and cancellation errors do not trigger a retry. Anthropic-format
|
|
576
|
+
models in Claude Code, and the server's direct routes, are forwarded untouched
|
|
577
|
+
so prompt caching, beta headers, and thinking keep working; they do not retry
|
|
578
|
+
on the sibling endpoint.
|
|
579
|
+
|
|
567
580
|
### Environment isolation
|
|
568
581
|
|
|
569
582
|
When you launch, relay-ai builds a clean child environment:
|
|
@@ -584,7 +597,7 @@ OpenCode exposes models through different API formats. relay-ai handles them whe
|
|
|
584
597
|
|
|
585
598
|
| Model format | Examples | How it works | Label |
|
|
586
599
|
|---|---|---|---|
|
|
587
|
-
| Anthropic native | Claude, Qwen, MiniMax (Go) | Direct connection | *(none)* |
|
|
600
|
+
| Anthropic native | Claude, Union Alpha, Qwen, MiniMax (Go) | Direct connection | *(none)* |
|
|
588
601
|
| OpenAI chat completions | DeepSeek, Kimi, MiMo, GLM, Grok, GPT-4o (OpenCode OpenAI provider) | SDK adapter proxy (Vercel AI SDK) | `via proxy` |
|
|
589
602
|
| OpenAI Responses API | GPT-5.4+, GPT-5.5, Codex, o-series (OpenCode OpenAI provider only) | Same proxy; SDK picks Responses API | `via proxy` |
|
|
590
603
|
| Gemini native | Gemini (OpenCode Google provider) | SDK adapter, Gemini native API | `via proxy` |
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
injectClaudeCodeBillingSystemLine,
|
|
48
48
|
injectClaudeIdentity,
|
|
49
49
|
isBrowserRedirectOAuth,
|
|
50
|
+
isOpencodeApi,
|
|
50
51
|
isOpencodeOAuth,
|
|
51
52
|
isSdkMigratedNpm,
|
|
52
53
|
isValidProviderId,
|
|
@@ -78,6 +79,7 @@ import {
|
|
|
78
79
|
silenceSdkWarnings,
|
|
79
80
|
slugifyProviderId,
|
|
80
81
|
splitToolUseId,
|
|
82
|
+
sseChunk,
|
|
81
83
|
streamAnthropicResponse,
|
|
82
84
|
stripOneMContextSuffix,
|
|
83
85
|
supportsNativeOAuth,
|
|
@@ -85,7 +87,7 @@ import {
|
|
|
85
87
|
translateRequest,
|
|
86
88
|
upstreamHttpStatus,
|
|
87
89
|
validateCustomEndpointUrl
|
|
88
|
-
} from "./chunk-
|
|
90
|
+
} from "./chunk-VPDX24ZR.js";
|
|
89
91
|
|
|
90
92
|
// src/registry/google-model-id.ts
|
|
91
93
|
var GOOGLE_MODEL_PREFIX = "models/";
|
|
@@ -1901,7 +1903,7 @@ function estimateAnthropicInputTokens(body) {
|
|
|
1901
1903
|
}
|
|
1902
1904
|
|
|
1903
1905
|
// src/upstream-forward.ts
|
|
1904
|
-
import {
|
|
1906
|
+
import { once } from "events";
|
|
1905
1907
|
|
|
1906
1908
|
// src/server/auth.ts
|
|
1907
1909
|
function sanitizeCredential(value) {
|
|
@@ -1959,7 +1961,7 @@ async function fetchWithOAuthRetry(apiKey, request, refreshToken) {
|
|
|
1959
1961
|
response = await request(refreshed);
|
|
1960
1962
|
return { response, apiKey: refreshed, refreshed: true };
|
|
1961
1963
|
}
|
|
1962
|
-
async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWantsStream, inboundBeta, authType, log7, claudeCodeSessionId, extraHeaders, refreshToken, onTokenRefreshed) {
|
|
1964
|
+
async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWantsStream, inboundBeta, authType, log7, claudeCodeSessionId, extraHeaders, refreshToken, onTokenRefreshed, retryEmptyStream = false) {
|
|
1963
1965
|
const doFetch = (key) => fetch(messagesUrl, {
|
|
1964
1966
|
method: "POST",
|
|
1965
1967
|
headers: anthropicUpstreamHeaders(key, clientWantsStream, inboundBeta, authType, claudeCodeSessionId, extraHeaders),
|
|
@@ -1981,12 +1983,46 @@ async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWant
|
|
|
1981
1983
|
return;
|
|
1982
1984
|
}
|
|
1983
1985
|
if (clientWantsStream && upstreamRes.body) {
|
|
1986
|
+
const reader = upstreamRes.body.getReader();
|
|
1987
|
+
const first = await reader.read().catch(() => ({ done: true, value: void 0 }));
|
|
1988
|
+
if (first.done) {
|
|
1989
|
+
reader.releaseLock();
|
|
1990
|
+
if (retryEmptyStream) {
|
|
1991
|
+
log7?.("anthropic upstream returned an empty stream; retrying without streaming");
|
|
1992
|
+
await replayWithoutStreaming(
|
|
1993
|
+
res,
|
|
1994
|
+
messagesUrl,
|
|
1995
|
+
body,
|
|
1996
|
+
apiKey,
|
|
1997
|
+
inboundBeta,
|
|
1998
|
+
authType,
|
|
1999
|
+
claudeCodeSessionId,
|
|
2000
|
+
extraHeaders,
|
|
2001
|
+
log7
|
|
2002
|
+
);
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
1984
2006
|
res.writeHead(200, {
|
|
1985
2007
|
"Content-Type": "text/event-stream",
|
|
1986
2008
|
"Cache-Control": "no-cache",
|
|
1987
2009
|
"Connection": "keep-alive"
|
|
1988
2010
|
});
|
|
1989
|
-
|
|
2011
|
+
if (first.done) {
|
|
2012
|
+
res.end();
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
res.write(Buffer.from(first.value));
|
|
2016
|
+
try {
|
|
2017
|
+
while (true) {
|
|
2018
|
+
const next = await reader.read();
|
|
2019
|
+
if (next.done) break;
|
|
2020
|
+
if (!res.write(Buffer.from(next.value))) await once(res, "drain");
|
|
2021
|
+
}
|
|
2022
|
+
res.end();
|
|
2023
|
+
} catch {
|
|
2024
|
+
res.destroy();
|
|
2025
|
+
}
|
|
1990
2026
|
return;
|
|
1991
2027
|
}
|
|
1992
2028
|
if (!upstreamRes.body) {
|
|
@@ -2008,6 +2044,85 @@ async function relayAnthropicMessages(res, messagesUrl, body, apiKey, clientWant
|
|
|
2008
2044
|
});
|
|
2009
2045
|
res.end(text4);
|
|
2010
2046
|
}
|
|
2047
|
+
async function replayWithoutStreaming(res, messagesUrl, body, apiKey, inboundBeta, authType, claudeCodeSessionId, extraHeaders, log7) {
|
|
2048
|
+
let retryRes;
|
|
2049
|
+
try {
|
|
2050
|
+
retryRes = await fetch(messagesUrl, {
|
|
2051
|
+
method: "POST",
|
|
2052
|
+
headers: anthropicUpstreamHeaders(apiKey, false, inboundBeta, authType, claudeCodeSessionId, extraHeaders),
|
|
2053
|
+
body: JSON.stringify({ ...body, stream: false })
|
|
2054
|
+
});
|
|
2055
|
+
} catch (err) {
|
|
2056
|
+
throw new UpstreamUnreachableError(err);
|
|
2057
|
+
}
|
|
2058
|
+
const text4 = await retryRes.text();
|
|
2059
|
+
if (!retryRes.ok) {
|
|
2060
|
+
log7?.(`anthropic upstream ${retryRes.status} on empty-stream retry: ${text4}`);
|
|
2061
|
+
res.writeHead(retryRes.status, { "Content-Type": retryRes.headers.get("content-type") || "application/json" });
|
|
2062
|
+
res.end(text4);
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
let message;
|
|
2066
|
+
try {
|
|
2067
|
+
message = JSON.parse(text4);
|
|
2068
|
+
} catch {
|
|
2069
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
2070
|
+
res.end(JSON.stringify({ type: "error", error: { type: "api_error", message: "Upstream response was not valid JSON" } }));
|
|
2071
|
+
return;
|
|
2072
|
+
}
|
|
2073
|
+
res.writeHead(200, {
|
|
2074
|
+
"Content-Type": "text/event-stream",
|
|
2075
|
+
"Cache-Control": "no-cache",
|
|
2076
|
+
"Connection": "keep-alive"
|
|
2077
|
+
});
|
|
2078
|
+
writeMessageAsSse(res, message);
|
|
2079
|
+
}
|
|
2080
|
+
function writeMessageAsSse(res, message) {
|
|
2081
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
2082
|
+
res.write(sseChunk("message_start", {
|
|
2083
|
+
type: "message_start",
|
|
2084
|
+
message: { ...message, content: [], stop_reason: null, stop_sequence: null }
|
|
2085
|
+
}));
|
|
2086
|
+
content.forEach((block, index) => {
|
|
2087
|
+
const type = block.type;
|
|
2088
|
+
const opening = type === "text" ? { type: "text", text: "" } : type === "thinking" ? { type: "thinking", thinking: "", signature: "" } : type === "tool_use" ? { type: "tool_use", id: block.id, name: block.name, input: {} } : block;
|
|
2089
|
+
res.write(sseChunk("content_block_start", { type: "content_block_start", index, content_block: opening }));
|
|
2090
|
+
if (type === "text") {
|
|
2091
|
+
res.write(sseChunk("content_block_delta", {
|
|
2092
|
+
type: "content_block_delta",
|
|
2093
|
+
index,
|
|
2094
|
+
delta: { type: "text_delta", text: block.text ?? "" }
|
|
2095
|
+
}));
|
|
2096
|
+
} else if (type === "thinking") {
|
|
2097
|
+
res.write(sseChunk("content_block_delta", {
|
|
2098
|
+
type: "content_block_delta",
|
|
2099
|
+
index,
|
|
2100
|
+
delta: { type: "thinking_delta", thinking: block.thinking ?? "" }
|
|
2101
|
+
}));
|
|
2102
|
+
if (typeof block.signature === "string") {
|
|
2103
|
+
res.write(sseChunk("content_block_delta", {
|
|
2104
|
+
type: "content_block_delta",
|
|
2105
|
+
index,
|
|
2106
|
+
delta: { type: "signature_delta", signature: block.signature }
|
|
2107
|
+
}));
|
|
2108
|
+
}
|
|
2109
|
+
} else if (type === "tool_use") {
|
|
2110
|
+
res.write(sseChunk("content_block_delta", {
|
|
2111
|
+
type: "content_block_delta",
|
|
2112
|
+
index,
|
|
2113
|
+
delta: { type: "input_json_delta", partial_json: JSON.stringify(block.input ?? {}) }
|
|
2114
|
+
}));
|
|
2115
|
+
}
|
|
2116
|
+
res.write(sseChunk("content_block_stop", { type: "content_block_stop", index }));
|
|
2117
|
+
});
|
|
2118
|
+
res.write(sseChunk("message_delta", {
|
|
2119
|
+
type: "message_delta",
|
|
2120
|
+
delta: { stop_reason: message.stop_reason ?? "end_turn", stop_sequence: message.stop_sequence ?? null },
|
|
2121
|
+
usage: message.usage ?? {}
|
|
2122
|
+
}));
|
|
2123
|
+
res.write(sseChunk("message_stop", { type: "message_stop" }));
|
|
2124
|
+
res.end();
|
|
2125
|
+
}
|
|
2011
2126
|
|
|
2012
2127
|
// src/antigravity/anthropic-to-cloudcode.ts
|
|
2013
2128
|
import { randomUUID } from "crypto";
|
|
@@ -2859,7 +2974,8 @@ function startProxyCatalog(routes, defaultAliasId, debug = false) {
|
|
|
2859
2974
|
route.refreshToken,
|
|
2860
2975
|
(refreshed) => {
|
|
2861
2976
|
route.apiKey = refreshed;
|
|
2862
|
-
}
|
|
2977
|
+
},
|
|
2978
|
+
true
|
|
2863
2979
|
);
|
|
2864
2980
|
} catch (err) {
|
|
2865
2981
|
const message = err instanceof UpstreamUnreachableError ? err.message : String(err);
|
|
@@ -3594,8 +3710,7 @@ function readModelsFromModelsDev(backendId, cache = loadModelsDevCache()) {
|
|
|
3594
3710
|
const id = entry.id ?? modelKey;
|
|
3595
3711
|
if (entry.status === "deprecated") continue;
|
|
3596
3712
|
const isFree = entry.cost !== void 0 && entry.cost.input === 0 && entry.cost.output === 0;
|
|
3597
|
-
const
|
|
3598
|
-
const modelFormat = backendId === "go" && rawFormat === "anthropic" ? "openai" : rawFormat;
|
|
3713
|
+
const modelFormat = classifyModelFormat(id, entry.provider?.npm);
|
|
3599
3714
|
result.set(id, {
|
|
3600
3715
|
id,
|
|
3601
3716
|
name: entry.name ?? id,
|
|
@@ -3630,10 +3745,7 @@ function mergeModels(apiIds, cache, backendId) {
|
|
|
3630
3745
|
const uniqueIds = Array.from(new Set(apiIds));
|
|
3631
3746
|
return uniqueIds.filter((id) => !shouldHideModel({ providerId: backendId, modelId: id, agent: "claude" })).map((id) => {
|
|
3632
3747
|
const cached = cache?.get(id);
|
|
3633
|
-
if (cached) {
|
|
3634
|
-
const modelFormat2 = backendId === "go" && cached.modelFormat === "anthropic" ? "openai" : cached.modelFormat;
|
|
3635
|
-
return { ...cached, sourceBackend: backendId, modelFormat: modelFormat2 };
|
|
3636
|
-
}
|
|
3748
|
+
if (cached) return { ...cached, sourceBackend: backendId };
|
|
3637
3749
|
const modelFormat = classifyModelFormat(id, void 0);
|
|
3638
3750
|
return {
|
|
3639
3751
|
id,
|
|
@@ -3799,7 +3911,12 @@ function buildImportProviderList(raw, authEntries) {
|
|
|
3799
3911
|
const oauthByProviderId = /* @__PURE__ */ new Map();
|
|
3800
3912
|
const covered = /* @__PURE__ */ new Set();
|
|
3801
3913
|
const merged = [];
|
|
3802
|
-
|
|
3914
|
+
const rawWithLegacyKeys = raw.map((provider) => {
|
|
3915
|
+
const authEntry = authEntries[provider.id];
|
|
3916
|
+
if (provider.key?.trim() || !isOpencodeApi(authEntry)) return provider;
|
|
3917
|
+
return { ...provider, key: authEntry.key };
|
|
3918
|
+
});
|
|
3919
|
+
for (const provider of normalizeProviders(rawWithLegacyKeys)) {
|
|
3803
3920
|
const normalized = normalizeImportProviderIdentity(provider);
|
|
3804
3921
|
if (covered.has(normalized.id)) continue;
|
|
3805
3922
|
merged.push(normalized);
|
|
@@ -3856,7 +3973,7 @@ function listCredentialSkippedProviders(raw, authEntries, importedIds, alreadyRe
|
|
|
3856
3973
|
if (isOpencodeOAuth(authEntries[provider.id])) continue;
|
|
3857
3974
|
if (!provider.models || Object.keys(provider.models).length === 0) continue;
|
|
3858
3975
|
const reason = classifyOpencodeCredentialGap(provider.id);
|
|
3859
|
-
if (reason !== "oauth-no-token" && !registryProviderIds.has(provider.id)) continue;
|
|
3976
|
+
if (reason !== "oauth-no-token" && !provider.configured && !registryProviderIds.has(provider.id)) continue;
|
|
3860
3977
|
skipped.push({ id: provider.id, name: provider.name, reason });
|
|
3861
3978
|
}
|
|
3862
3979
|
return skipped;
|
|
@@ -3919,7 +4036,30 @@ function buildCatalogRoutes(startingRoute, favorites, resolveRoute, max = MAX_MO
|
|
|
3919
4036
|
|
|
3920
4037
|
// src/registry/materialize.ts
|
|
3921
4038
|
init_provider_templates();
|
|
3922
|
-
|
|
4039
|
+
|
|
4040
|
+
// src/registry/model-protocol.ts
|
|
4041
|
+
function reconcileCachedModelProtocol(model, provider, metadata = loadModelsDevCache()) {
|
|
4042
|
+
if (model.source === "manual") return model;
|
|
4043
|
+
const isZenGo = provider.id === "zen" || provider.id === "go" || provider.templateId === "zen" || provider.templateId === "go";
|
|
4044
|
+
if (!isZenGo) return model;
|
|
4045
|
+
const metadataNpm = findModelsDevModel(provider.id, model.id, metadata)?.provider?.npm;
|
|
4046
|
+
if (!metadataNpm) return model;
|
|
4047
|
+
const format = classifyModelFormat(model.id, metadataNpm);
|
|
4048
|
+
if (format === "unsupported") return model;
|
|
4049
|
+
const backendId = provider.id === "go" || provider.templateId === "go" ? "go" : "zen";
|
|
4050
|
+
const apiUrl = model.apiUrl ?? provider.api.url ?? BACKENDS[backendId].baseUrl;
|
|
4051
|
+
return {
|
|
4052
|
+
...model,
|
|
4053
|
+
modelFormat: format,
|
|
4054
|
+
npm: metadataNpm,
|
|
4055
|
+
apiUrl
|
|
4056
|
+
};
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
// src/registry/materialize.ts
|
|
4060
|
+
function cachedModelToLocal(cached, provider, metadata = loadModelsDevCache()) {
|
|
4061
|
+
const reconciled = reconcileCachedModelProtocol(cached, provider, metadata);
|
|
4062
|
+
cached = reconciled;
|
|
3923
4063
|
const freeStatus = classifyFreeStatus({
|
|
3924
4064
|
model: cached,
|
|
3925
4065
|
providerId: provider.id,
|
|
@@ -3941,20 +4081,24 @@ function cachedModelToLocal(cached, provider) {
|
|
|
3941
4081
|
interleavedReasoningField: cached.interleavedReasoningField
|
|
3942
4082
|
};
|
|
3943
4083
|
}
|
|
4084
|
+
const modelsDev = findModelsDevModel(provider.id, cached.id, metadata);
|
|
4085
|
+
const isZenGo = provider.id === "zen" || provider.id === "go" || provider.templateId === "zen" || provider.templateId === "go";
|
|
4086
|
+
const metadataNpm = !cached.source && isZenGo ? modelsDev?.provider?.npm : void 0;
|
|
3944
4087
|
const npm = cached.npm ?? provider.api.npm ?? "";
|
|
3945
|
-
const apiUrl = cached.apiUrl ?? provider.api.url ?? "";
|
|
4088
|
+
const apiUrl = cached.apiUrl ?? provider.api.url ?? (isZenGo ? BACKENDS[provider.id === "go" || provider.templateId === "go" ? "go" : "zen"].baseUrl : "");
|
|
3946
4089
|
const endpoint = resolveEndpoint(npm, apiUrl);
|
|
3947
4090
|
if (endpoint === null) return null;
|
|
3948
|
-
const modelsDev = findModelsDevModel(provider.id, cached.id);
|
|
3949
4091
|
const { id, upstreamModelId: upstreamModelId2 } = normalizeGoogleModelId(cached.id, npm);
|
|
3950
4092
|
const normalizedUpstream = normalizeGoogleModelId(cached.upstreamModelId ?? cached.id, npm).upstreamModelId;
|
|
3951
4093
|
const family = npm === "@ai-sdk/google" ? id.split(/[-/:]/)[0] ?? id : cached.family ?? "";
|
|
4094
|
+
const classifiedFormat = classifyModelFormat(cached.id, npm);
|
|
4095
|
+
const resolvedFormat = classifiedFormat === "anthropic" ? classifiedFormat : "openai";
|
|
3952
4096
|
return {
|
|
3953
4097
|
id,
|
|
3954
4098
|
name: npm === "@ai-sdk/google" ? normalizeGoogleDisplayName(cached.name, id) : cached.name,
|
|
3955
4099
|
family,
|
|
3956
4100
|
brand: npm === "@ai-sdk/google" ? deriveBrand(family) : cached.brand ?? deriveBrand(cached.family ?? ""),
|
|
3957
|
-
modelFormat: cached.modelFormat ?? endpoint.format,
|
|
4101
|
+
modelFormat: metadataNpm ? resolvedFormat : cached.modelFormat ?? endpoint.format,
|
|
3958
4102
|
upstreamModelId: normalizedUpstream,
|
|
3959
4103
|
baseUrl: endpoint.baseUrl,
|
|
3960
4104
|
completionsUrl: endpoint.completionsUrl,
|
|
@@ -8292,6 +8436,7 @@ function httpProxyModelId(providerId, modelId) {
|
|
|
8292
8436
|
return `${HTTP_PROXY_MODEL_PREFIX}${providerId}:${modelId}`;
|
|
8293
8437
|
}
|
|
8294
8438
|
function supportsClaudeTransparentMode(model) {
|
|
8439
|
+
if (model.modelFormat === "anthropic") return Boolean(model.baseUrl);
|
|
8295
8440
|
return model.modelFormat === "openai" && isSdkMigratedNpm(model.npm);
|
|
8296
8441
|
}
|
|
8297
8442
|
function buildHttpProxyRoutes(providers, favorites, selected, max = MAX_MODEL_CATALOG) {
|
|
@@ -9661,4 +9806,4 @@ export {
|
|
|
9661
9806
|
supportsClaudeTransparentMode,
|
|
9662
9807
|
buildHttpProxyRoutes
|
|
9663
9808
|
};
|
|
9664
|
-
//# sourceMappingURL=chunk-
|
|
9809
|
+
//# sourceMappingURL=chunk-5MEDBKPX.js.map
|