@relayplane/proxy 1.8.13 → 1.8.16
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 +30 -21
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.js +4 -4
- package/dist/config.js.map +1 -1
- package/dist/standalone-proxy.d.ts +9 -0
- package/dist/standalone-proxy.d.ts.map +1 -1
- package/dist/standalone-proxy.js +89 -15
- package/dist/standalone-proxy.js.map +1 -1
- package/package.json +1 -1
package/dist/standalone-proxy.js
CHANGED
|
@@ -62,6 +62,7 @@ exports.extractResponseText = extractResponseText;
|
|
|
62
62
|
exports.parseModelSuffix = parseModelSuffix;
|
|
63
63
|
exports.classifyComplexity = classifyComplexity;
|
|
64
64
|
exports.shouldEscalate = shouldEscalate;
|
|
65
|
+
exports.resolveExplicitModel = resolveExplicitModel;
|
|
65
66
|
exports.startProxy = startProxy;
|
|
66
67
|
const http = __importStar(require("node:http"));
|
|
67
68
|
const fs = __importStar(require("node:fs"));
|
|
@@ -1891,10 +1892,48 @@ function parsePreferredModel(preferredModel) {
|
|
|
1891
1892
|
return { provider: provider, model };
|
|
1892
1893
|
}
|
|
1893
1894
|
/**
|
|
1894
|
-
* Resolve explicit model name to provider and model
|
|
1895
|
-
|
|
1895
|
+
* Resolve explicit model name to provider and model.
|
|
1896
|
+
/**
|
|
1897
|
+
* Add provider prefix to bare model names for aggregator routing (e.g., OpenRouter).
|
|
1898
|
+
* Complexity routing produces bare names like 'claude-sonnet-4-6' — aggregators need
|
|
1899
|
+
* the full 'anthropic/claude-sonnet-4-6' format to identify the upstream provider.
|
|
1900
|
+
* If the model already has a prefix (contains '/'), it's returned unchanged.
|
|
1896
1901
|
*/
|
|
1897
|
-
function
|
|
1902
|
+
function addProviderPrefix(model, detectedProvider) {
|
|
1903
|
+
// Already has a prefix (e.g., 'anthropic/claude-sonnet-4-6')
|
|
1904
|
+
if (model.includes('/'))
|
|
1905
|
+
return model;
|
|
1906
|
+
// Map detected provider to OpenRouter-style prefix
|
|
1907
|
+
const prefixMap = {
|
|
1908
|
+
anthropic: 'anthropic',
|
|
1909
|
+
openai: 'openai',
|
|
1910
|
+
google: 'google',
|
|
1911
|
+
deepseek: 'deepseek',
|
|
1912
|
+
mistral: 'mistralai',
|
|
1913
|
+
together: 'together',
|
|
1914
|
+
groq: 'groq',
|
|
1915
|
+
};
|
|
1916
|
+
const prefix = prefixMap[detectedProvider];
|
|
1917
|
+
if (prefix)
|
|
1918
|
+
return `${prefix}/${model}`;
|
|
1919
|
+
// Fallback: infer from model name patterns
|
|
1920
|
+
if (model.startsWith('claude') || model.startsWith('claude-'))
|
|
1921
|
+
return `anthropic/${model}`;
|
|
1922
|
+
if (model.startsWith('gpt') || model.startsWith('o1') || model.startsWith('o3'))
|
|
1923
|
+
return `openai/${model}`;
|
|
1924
|
+
if (model.startsWith('gemini'))
|
|
1925
|
+
return `google/${model}`;
|
|
1926
|
+
return model;
|
|
1927
|
+
}
|
|
1928
|
+
/**
|
|
1929
|
+
* When `defaultProvider` is set, ALL models are routed to that provider
|
|
1930
|
+
* regardless of model name prefix — the model name is preserved as-is
|
|
1931
|
+
* so OpenRouter receives the full `anthropic/claude-sonnet-4-6` format.
|
|
1932
|
+
*/
|
|
1933
|
+
function resolveExplicitModel(modelName, defaultProvider) {
|
|
1934
|
+
if (defaultProvider) {
|
|
1935
|
+
return { provider: defaultProvider, model: modelName };
|
|
1936
|
+
}
|
|
1898
1937
|
// Resolve aliases first (e.g., relayplane:auto → rp:balanced)
|
|
1899
1938
|
const resolvedAlias = resolveModelAlias(modelName);
|
|
1900
1939
|
// Check SMART_ALIASES (rp:best, rp:fast, etc.)
|
|
@@ -1954,7 +1993,10 @@ function resolveExplicitModel(modelName) {
|
|
|
1954
1993
|
}
|
|
1955
1994
|
return null;
|
|
1956
1995
|
}
|
|
1957
|
-
function resolveConfigModel(modelName) {
|
|
1996
|
+
function resolveConfigModel(modelName, defaultProvider) {
|
|
1997
|
+
if (defaultProvider) {
|
|
1998
|
+
return { provider: defaultProvider, model: modelName };
|
|
1999
|
+
}
|
|
1958
2000
|
return resolveExplicitModel(modelName) ?? parsePreferredModel(modelName);
|
|
1959
2001
|
}
|
|
1960
2002
|
function extractResponseTextAuto(responseData) {
|
|
@@ -2147,18 +2189,27 @@ function resolveProviderApiKey(provider, ctx, envApiKey) {
|
|
|
2147
2189
|
}
|
|
2148
2190
|
const apiKeyEnv = exports.DEFAULT_ENDPOINTS[provider]?.apiKeyEnv ?? `${provider.toUpperCase()}_API_KEY`;
|
|
2149
2191
|
const apiKey = process.env[apiKeyEnv];
|
|
2150
|
-
if (
|
|
2151
|
-
return {
|
|
2152
|
-
error: {
|
|
2153
|
-
status: 500,
|
|
2154
|
-
payload: {
|
|
2155
|
-
error: `Missing ${apiKeyEnv} environment variable`,
|
|
2156
|
-
hint: `Cross-provider routing requires API keys for each provider. Set ${apiKeyEnv} to enable ${provider} models.`,
|
|
2157
|
-
},
|
|
2158
|
-
},
|
|
2159
|
-
};
|
|
2192
|
+
if (apiKey) {
|
|
2193
|
+
return { apiKey };
|
|
2160
2194
|
}
|
|
2161
|
-
|
|
2195
|
+
// Auth passthrough: use incoming Authorization: Bearer token when no env key is configured.
|
|
2196
|
+
// This supports defaultProvider scenarios where the caller passes the API key in the request
|
|
2197
|
+
// (e.g., OpenRouter users who pass their key via Authorization header).
|
|
2198
|
+
if (ctx.authHeader) {
|
|
2199
|
+
const bearerMatch = ctx.authHeader.match(/^Bearer\s+(.+)$/i);
|
|
2200
|
+
if (bearerMatch) {
|
|
2201
|
+
return { apiKey: bearerMatch[1] };
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
return {
|
|
2205
|
+
error: {
|
|
2206
|
+
status: 500,
|
|
2207
|
+
payload: {
|
|
2208
|
+
error: `Missing ${apiKeyEnv} environment variable`,
|
|
2209
|
+
hint: `Cross-provider routing requires API keys for each provider. Set ${apiKeyEnv} to enable ${provider} models.`,
|
|
2210
|
+
},
|
|
2211
|
+
},
|
|
2212
|
+
};
|
|
2162
2213
|
}
|
|
2163
2214
|
function getCascadeModels(config) {
|
|
2164
2215
|
return config.routing?.cascade?.models ?? [];
|
|
@@ -4279,6 +4330,25 @@ async function startProxy(config = {}) {
|
|
|
4279
4330
|
}
|
|
4280
4331
|
}
|
|
4281
4332
|
}
|
|
4333
|
+
// ── defaultProvider: override provider for all non-cascade cloud routing ──
|
|
4334
|
+
// When set, ALL models route to this provider regardless of model prefix.
|
|
4335
|
+
// Ollama is excluded — local routing takes priority over defaultProvider.
|
|
4336
|
+
if (proxyConfig.defaultProvider && !useCascade && targetProvider !== 'ollama') {
|
|
4337
|
+
const originalProvider = targetProvider;
|
|
4338
|
+
targetProvider = proxyConfig.defaultProvider;
|
|
4339
|
+
// When routing to OpenRouter (or any aggregator), model names need provider prefixes.
|
|
4340
|
+
// Complexity routing produces bare names like 'claude-sonnet-4-6' — OpenRouter needs
|
|
4341
|
+
// 'anthropic/claude-sonnet-4-6'. Passthrough mode preserves the original request model.
|
|
4342
|
+
if (routingMode === 'passthrough') {
|
|
4343
|
+
targetModel = requestedModel;
|
|
4344
|
+
}
|
|
4345
|
+
else {
|
|
4346
|
+
// Add provider prefix for bare model names when routing to an aggregator
|
|
4347
|
+
targetModel = addProviderPrefix(targetModel, originalProvider);
|
|
4348
|
+
}
|
|
4349
|
+
log(`defaultProvider override: ${originalProvider} → ${targetProvider} (model: ${targetModel})`);
|
|
4350
|
+
}
|
|
4351
|
+
// ── End defaultProvider override ──
|
|
4282
4352
|
if (!useCascade) {
|
|
4283
4353
|
log(`Routing to: ${targetProvider}/${targetModel}`);
|
|
4284
4354
|
}
|
|
@@ -4529,6 +4599,10 @@ async function startProxy(config = {}) {
|
|
|
4529
4599
|
console.log(` POST /v1/messages/count_tokens - Token counting`);
|
|
4530
4600
|
console.log(` GET /v1/models - Model list`);
|
|
4531
4601
|
console.log(` Models: relayplane:auto, relayplane:cost, relayplane:fast, relayplane:quality`);
|
|
4602
|
+
if (proxyConfig.defaultProvider) {
|
|
4603
|
+
console.log(` Providers:`);
|
|
4604
|
+
console.log(` ✓ ${proxyConfig.defaultProvider.charAt(0).toUpperCase() + proxyConfig.defaultProvider.slice(1)} (default provider — all models route here)`);
|
|
4605
|
+
}
|
|
4532
4606
|
console.log(` Auth: Passthrough for Anthropic, env vars for other providers`);
|
|
4533
4607
|
console.log(` Streaming: ✅ Enabled`);
|
|
4534
4608
|
startWatchdog();
|