@relayplane/proxy 0.1.8 → 0.1.9
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 +49 -0
- package/dist/cli.js +60 -16
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +60 -16
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +60 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +60 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1071,6 +1071,19 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1071
1071
|
qualityModel?: string | undefined;
|
|
1072
1072
|
costModel?: string | undefined;
|
|
1073
1073
|
}>>;
|
|
1074
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
1075
|
+
anthropicApiKey: z.ZodOptional<z.ZodString>;
|
|
1076
|
+
anthropicMaxToken: z.ZodOptional<z.ZodString>;
|
|
1077
|
+
useMaxForModels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1078
|
+
}, "strip", z.ZodTypeAny, {
|
|
1079
|
+
anthropicApiKey?: string | undefined;
|
|
1080
|
+
anthropicMaxToken?: string | undefined;
|
|
1081
|
+
useMaxForModels?: string[] | undefined;
|
|
1082
|
+
}, {
|
|
1083
|
+
anthropicApiKey?: string | undefined;
|
|
1084
|
+
anthropicMaxToken?: string | undefined;
|
|
1085
|
+
useMaxForModels?: string[] | undefined;
|
|
1086
|
+
}>>;
|
|
1074
1087
|
}, "strip", z.ZodTypeAny, {
|
|
1075
1088
|
strategies?: Record<string, {
|
|
1076
1089
|
model: string;
|
|
@@ -1081,6 +1094,11 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1081
1094
|
qualityModel?: string | undefined;
|
|
1082
1095
|
costModel?: string | undefined;
|
|
1083
1096
|
} | undefined;
|
|
1097
|
+
auth?: {
|
|
1098
|
+
anthropicApiKey?: string | undefined;
|
|
1099
|
+
anthropicMaxToken?: string | undefined;
|
|
1100
|
+
useMaxForModels?: string[] | undefined;
|
|
1101
|
+
} | undefined;
|
|
1084
1102
|
}, {
|
|
1085
1103
|
strategies?: Record<string, {
|
|
1086
1104
|
model: string;
|
|
@@ -1091,6 +1109,11 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1091
1109
|
qualityModel?: string | undefined;
|
|
1092
1110
|
costModel?: string | undefined;
|
|
1093
1111
|
} | undefined;
|
|
1112
|
+
auth?: {
|
|
1113
|
+
anthropicApiKey?: string | undefined;
|
|
1114
|
+
anthropicMaxToken?: string | undefined;
|
|
1115
|
+
useMaxForModels?: string[] | undefined;
|
|
1116
|
+
} | undefined;
|
|
1094
1117
|
}>;
|
|
1095
1118
|
type StrategyConfig = z.infer<typeof StrategySchema>;
|
|
1096
1119
|
type Config = z.infer<typeof ConfigSchema>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1071,6 +1071,19 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1071
1071
|
qualityModel?: string | undefined;
|
|
1072
1072
|
costModel?: string | undefined;
|
|
1073
1073
|
}>>;
|
|
1074
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
1075
|
+
anthropicApiKey: z.ZodOptional<z.ZodString>;
|
|
1076
|
+
anthropicMaxToken: z.ZodOptional<z.ZodString>;
|
|
1077
|
+
useMaxForModels: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1078
|
+
}, "strip", z.ZodTypeAny, {
|
|
1079
|
+
anthropicApiKey?: string | undefined;
|
|
1080
|
+
anthropicMaxToken?: string | undefined;
|
|
1081
|
+
useMaxForModels?: string[] | undefined;
|
|
1082
|
+
}, {
|
|
1083
|
+
anthropicApiKey?: string | undefined;
|
|
1084
|
+
anthropicMaxToken?: string | undefined;
|
|
1085
|
+
useMaxForModels?: string[] | undefined;
|
|
1086
|
+
}>>;
|
|
1074
1087
|
}, "strip", z.ZodTypeAny, {
|
|
1075
1088
|
strategies?: Record<string, {
|
|
1076
1089
|
model: string;
|
|
@@ -1081,6 +1094,11 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1081
1094
|
qualityModel?: string | undefined;
|
|
1082
1095
|
costModel?: string | undefined;
|
|
1083
1096
|
} | undefined;
|
|
1097
|
+
auth?: {
|
|
1098
|
+
anthropicApiKey?: string | undefined;
|
|
1099
|
+
anthropicMaxToken?: string | undefined;
|
|
1100
|
+
useMaxForModels?: string[] | undefined;
|
|
1101
|
+
} | undefined;
|
|
1084
1102
|
}, {
|
|
1085
1103
|
strategies?: Record<string, {
|
|
1086
1104
|
model: string;
|
|
@@ -1091,6 +1109,11 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
1091
1109
|
qualityModel?: string | undefined;
|
|
1092
1110
|
costModel?: string | undefined;
|
|
1093
1111
|
} | undefined;
|
|
1112
|
+
auth?: {
|
|
1113
|
+
anthropicApiKey?: string | undefined;
|
|
1114
|
+
anthropicMaxToken?: string | undefined;
|
|
1115
|
+
useMaxForModels?: string[] | undefined;
|
|
1116
|
+
} | undefined;
|
|
1094
1117
|
}>;
|
|
1095
1118
|
type StrategyConfig = z.infer<typeof StrategySchema>;
|
|
1096
1119
|
type Config = z.infer<typeof ConfigSchema>;
|
package/dist/index.js
CHANGED
|
@@ -1638,12 +1638,19 @@ var StrategySchema = import_zod.z.object({
|
|
|
1638
1638
|
minConfidence: import_zod.z.number().min(0).max(1).optional(),
|
|
1639
1639
|
fallback: import_zod.z.string().optional()
|
|
1640
1640
|
});
|
|
1641
|
+
var AuthSchema = import_zod.z.object({
|
|
1642
|
+
anthropicApiKey: import_zod.z.string().optional(),
|
|
1643
|
+
anthropicMaxToken: import_zod.z.string().optional(),
|
|
1644
|
+
useMaxForModels: import_zod.z.array(import_zod.z.string()).optional()
|
|
1645
|
+
// Default: ['opus']
|
|
1646
|
+
}).optional();
|
|
1641
1647
|
var ConfigSchema = import_zod.z.object({
|
|
1642
1648
|
strategies: import_zod.z.record(import_zod.z.string(), StrategySchema).optional(),
|
|
1643
1649
|
defaults: import_zod.z.object({
|
|
1644
1650
|
qualityModel: import_zod.z.string().optional(),
|
|
1645
1651
|
costModel: import_zod.z.string().optional()
|
|
1646
|
-
}).optional()
|
|
1652
|
+
}).optional(),
|
|
1653
|
+
auth: AuthSchema
|
|
1647
1654
|
});
|
|
1648
1655
|
var DEFAULT_CONFIG = {
|
|
1649
1656
|
strategies: {
|
|
@@ -1703,6 +1710,19 @@ function loadConfig() {
|
|
|
1703
1710
|
function getStrategy(config, taskType) {
|
|
1704
1711
|
return config.strategies?.[taskType] ?? null;
|
|
1705
1712
|
}
|
|
1713
|
+
function getAnthropicAuth(config, model) {
|
|
1714
|
+
const auth = config.auth;
|
|
1715
|
+
const useMaxForModels = auth?.useMaxForModels ?? ["opus"];
|
|
1716
|
+
const shouldUseMax = useMaxForModels.some((m) => model.toLowerCase().includes(m.toLowerCase()));
|
|
1717
|
+
if (shouldUseMax && auth?.anthropicMaxToken) {
|
|
1718
|
+
return { type: "max", value: auth.anthropicMaxToken };
|
|
1719
|
+
}
|
|
1720
|
+
const apiKey = auth?.anthropicApiKey ?? process.env["ANTHROPIC_API_KEY"];
|
|
1721
|
+
if (apiKey) {
|
|
1722
|
+
return { type: "apiKey", value: apiKey };
|
|
1723
|
+
}
|
|
1724
|
+
return null;
|
|
1725
|
+
}
|
|
1706
1726
|
function watchConfig(onChange) {
|
|
1707
1727
|
const configPath = getConfigPath();
|
|
1708
1728
|
const dir = path2.dirname(configPath);
|
|
@@ -1723,7 +1743,7 @@ function watchConfig(onChange) {
|
|
|
1723
1743
|
}
|
|
1724
1744
|
|
|
1725
1745
|
// src/proxy.ts
|
|
1726
|
-
var VERSION = "0.1.
|
|
1746
|
+
var VERSION = "0.1.9";
|
|
1727
1747
|
var recentRuns = [];
|
|
1728
1748
|
var MAX_RECENT_RUNS = 100;
|
|
1729
1749
|
var modelCounts = {};
|
|
@@ -1791,13 +1811,17 @@ function extractPromptText(messages) {
|
|
|
1791
1811
|
return "";
|
|
1792
1812
|
}).join("\n");
|
|
1793
1813
|
}
|
|
1794
|
-
async function forwardToAnthropic(request, targetModel,
|
|
1814
|
+
async function forwardToAnthropic(request, targetModel, auth, betaHeaders) {
|
|
1795
1815
|
const anthropicBody = buildAnthropicBody(request, targetModel, false);
|
|
1796
1816
|
const headers = {
|
|
1797
1817
|
"Content-Type": "application/json",
|
|
1798
|
-
"x-api-key": apiKey,
|
|
1799
1818
|
"anthropic-version": "2023-06-01"
|
|
1800
1819
|
};
|
|
1820
|
+
if (auth.type === "max") {
|
|
1821
|
+
headers["Authorization"] = `Bearer ${auth.value}`;
|
|
1822
|
+
} else {
|
|
1823
|
+
headers["x-api-key"] = auth.value;
|
|
1824
|
+
}
|
|
1801
1825
|
if (betaHeaders) {
|
|
1802
1826
|
headers["anthropic-beta"] = betaHeaders;
|
|
1803
1827
|
}
|
|
@@ -1808,13 +1832,17 @@ async function forwardToAnthropic(request, targetModel, apiKey, betaHeaders) {
|
|
|
1808
1832
|
});
|
|
1809
1833
|
return response;
|
|
1810
1834
|
}
|
|
1811
|
-
async function forwardToAnthropicStream(request, targetModel,
|
|
1835
|
+
async function forwardToAnthropicStream(request, targetModel, auth, betaHeaders) {
|
|
1812
1836
|
const anthropicBody = buildAnthropicBody(request, targetModel, true);
|
|
1813
1837
|
const headers = {
|
|
1814
1838
|
"Content-Type": "application/json",
|
|
1815
|
-
"x-api-key": apiKey,
|
|
1816
1839
|
"anthropic-version": "2023-06-01"
|
|
1817
1840
|
};
|
|
1841
|
+
if (auth.type === "max") {
|
|
1842
|
+
headers["Authorization"] = `Bearer ${auth.value}`;
|
|
1843
|
+
} else {
|
|
1844
|
+
headers["x-api-key"] = auth.value;
|
|
1845
|
+
}
|
|
1818
1846
|
if (betaHeaders) {
|
|
1819
1847
|
headers["anthropic-beta"] = betaHeaders;
|
|
1820
1848
|
}
|
|
@@ -2620,12 +2648,24 @@ async function startProxy(config = {}) {
|
|
|
2620
2648
|
}
|
|
2621
2649
|
}
|
|
2622
2650
|
log(`Routing to: ${targetProvider}/${targetModel}`);
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
if (
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2651
|
+
let apiKey;
|
|
2652
|
+
let anthropicAuth = null;
|
|
2653
|
+
if (targetProvider === "anthropic") {
|
|
2654
|
+
anthropicAuth = getAnthropicAuth(currentConfig, targetModel);
|
|
2655
|
+
if (!anthropicAuth) {
|
|
2656
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
2657
|
+
res.end(JSON.stringify({ error: "No Anthropic auth configured (set ANTHROPIC_API_KEY or config.auth.anthropicMaxToken)" }));
|
|
2658
|
+
return;
|
|
2659
|
+
}
|
|
2660
|
+
log(`Using ${anthropicAuth.type === "max" ? "MAX token" : "API key"} auth for ${targetModel}`);
|
|
2661
|
+
} else {
|
|
2662
|
+
const apiKeyEnv = DEFAULT_ENDPOINTS[targetProvider]?.apiKeyEnv ?? `${targetProvider.toUpperCase()}_API_KEY`;
|
|
2663
|
+
apiKey = process.env[apiKeyEnv];
|
|
2664
|
+
if (!apiKey) {
|
|
2665
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
2666
|
+
res.end(JSON.stringify({ error: `Missing ${apiKeyEnv} environment variable` }));
|
|
2667
|
+
return;
|
|
2668
|
+
}
|
|
2629
2669
|
}
|
|
2630
2670
|
const startTime = Date.now();
|
|
2631
2671
|
const betaHeaders = req.headers["anthropic-beta"];
|
|
@@ -2636,6 +2676,7 @@ async function startProxy(config = {}) {
|
|
|
2636
2676
|
targetProvider,
|
|
2637
2677
|
targetModel,
|
|
2638
2678
|
apiKey,
|
|
2679
|
+
anthropicAuth,
|
|
2639
2680
|
relay,
|
|
2640
2681
|
promptText,
|
|
2641
2682
|
taskType,
|
|
@@ -2652,6 +2693,7 @@ async function startProxy(config = {}) {
|
|
|
2652
2693
|
targetProvider,
|
|
2653
2694
|
targetModel,
|
|
2654
2695
|
apiKey,
|
|
2696
|
+
anthropicAuth,
|
|
2655
2697
|
relay,
|
|
2656
2698
|
promptText,
|
|
2657
2699
|
taskType,
|
|
@@ -2681,12 +2723,13 @@ async function startProxy(config = {}) {
|
|
|
2681
2723
|
});
|
|
2682
2724
|
});
|
|
2683
2725
|
}
|
|
2684
|
-
async function handleStreamingRequest(res, request, targetProvider, targetModel, apiKey, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2726
|
+
async function handleStreamingRequest(res, request, targetProvider, targetModel, apiKey, anthropicAuth, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2685
2727
|
let providerResponse;
|
|
2686
2728
|
try {
|
|
2687
2729
|
switch (targetProvider) {
|
|
2688
2730
|
case "anthropic":
|
|
2689
|
-
|
|
2731
|
+
if (!anthropicAuth) throw new Error("No Anthropic auth");
|
|
2732
|
+
providerResponse = await forwardToAnthropicStream(request, targetModel, anthropicAuth, betaHeaders);
|
|
2690
2733
|
break;
|
|
2691
2734
|
case "google":
|
|
2692
2735
|
providerResponse = await forwardToGeminiStream(request, targetModel, apiKey);
|
|
@@ -2764,13 +2807,14 @@ async function handleStreamingRequest(res, request, targetProvider, targetModel,
|
|
|
2764
2807
|
});
|
|
2765
2808
|
res.end();
|
|
2766
2809
|
}
|
|
2767
|
-
async function handleNonStreamingRequest(res, request, targetProvider, targetModel, apiKey, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2810
|
+
async function handleNonStreamingRequest(res, request, targetProvider, targetModel, apiKey, anthropicAuth, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2768
2811
|
let providerResponse;
|
|
2769
2812
|
let responseData;
|
|
2770
2813
|
try {
|
|
2771
2814
|
switch (targetProvider) {
|
|
2772
2815
|
case "anthropic": {
|
|
2773
|
-
|
|
2816
|
+
if (!anthropicAuth) throw new Error("No Anthropic auth");
|
|
2817
|
+
providerResponse = await forwardToAnthropic(request, targetModel, anthropicAuth, betaHeaders);
|
|
2774
2818
|
const rawData = await providerResponse.json();
|
|
2775
2819
|
if (!providerResponse.ok) {
|
|
2776
2820
|
res.writeHead(providerResponse.status, { "Content-Type": "application/json" });
|