@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/cli.mjs
CHANGED
|
@@ -1578,12 +1578,19 @@ var StrategySchema = z.object({
|
|
|
1578
1578
|
minConfidence: z.number().min(0).max(1).optional(),
|
|
1579
1579
|
fallback: z.string().optional()
|
|
1580
1580
|
});
|
|
1581
|
+
var AuthSchema = z.object({
|
|
1582
|
+
anthropicApiKey: z.string().optional(),
|
|
1583
|
+
anthropicMaxToken: z.string().optional(),
|
|
1584
|
+
useMaxForModels: z.array(z.string()).optional()
|
|
1585
|
+
// Default: ['opus']
|
|
1586
|
+
}).optional();
|
|
1581
1587
|
var ConfigSchema = z.object({
|
|
1582
1588
|
strategies: z.record(z.string(), StrategySchema).optional(),
|
|
1583
1589
|
defaults: z.object({
|
|
1584
1590
|
qualityModel: z.string().optional(),
|
|
1585
1591
|
costModel: z.string().optional()
|
|
1586
|
-
}).optional()
|
|
1592
|
+
}).optional(),
|
|
1593
|
+
auth: AuthSchema
|
|
1587
1594
|
});
|
|
1588
1595
|
var DEFAULT_CONFIG = {
|
|
1589
1596
|
strategies: {
|
|
@@ -1643,6 +1650,19 @@ function loadConfig() {
|
|
|
1643
1650
|
function getStrategy(config, taskType) {
|
|
1644
1651
|
return config.strategies?.[taskType] ?? null;
|
|
1645
1652
|
}
|
|
1653
|
+
function getAnthropicAuth(config, model) {
|
|
1654
|
+
const auth = config.auth;
|
|
1655
|
+
const useMaxForModels = auth?.useMaxForModels ?? ["opus"];
|
|
1656
|
+
const shouldUseMax = useMaxForModels.some((m) => model.toLowerCase().includes(m.toLowerCase()));
|
|
1657
|
+
if (shouldUseMax && auth?.anthropicMaxToken) {
|
|
1658
|
+
return { type: "max", value: auth.anthropicMaxToken };
|
|
1659
|
+
}
|
|
1660
|
+
const apiKey = auth?.anthropicApiKey ?? process.env["ANTHROPIC_API_KEY"];
|
|
1661
|
+
if (apiKey) {
|
|
1662
|
+
return { type: "apiKey", value: apiKey };
|
|
1663
|
+
}
|
|
1664
|
+
return null;
|
|
1665
|
+
}
|
|
1646
1666
|
function watchConfig(onChange) {
|
|
1647
1667
|
const configPath = getConfigPath();
|
|
1648
1668
|
const dir = path2.dirname(configPath);
|
|
@@ -1663,7 +1683,7 @@ function watchConfig(onChange) {
|
|
|
1663
1683
|
}
|
|
1664
1684
|
|
|
1665
1685
|
// src/proxy.ts
|
|
1666
|
-
var VERSION = "0.1.
|
|
1686
|
+
var VERSION = "0.1.9";
|
|
1667
1687
|
var recentRuns = [];
|
|
1668
1688
|
var MAX_RECENT_RUNS = 100;
|
|
1669
1689
|
var modelCounts = {};
|
|
@@ -1731,13 +1751,17 @@ function extractPromptText(messages) {
|
|
|
1731
1751
|
return "";
|
|
1732
1752
|
}).join("\n");
|
|
1733
1753
|
}
|
|
1734
|
-
async function forwardToAnthropic(request, targetModel,
|
|
1754
|
+
async function forwardToAnthropic(request, targetModel, auth, betaHeaders) {
|
|
1735
1755
|
const anthropicBody = buildAnthropicBody(request, targetModel, false);
|
|
1736
1756
|
const headers = {
|
|
1737
1757
|
"Content-Type": "application/json",
|
|
1738
|
-
"x-api-key": apiKey,
|
|
1739
1758
|
"anthropic-version": "2023-06-01"
|
|
1740
1759
|
};
|
|
1760
|
+
if (auth.type === "max") {
|
|
1761
|
+
headers["Authorization"] = `Bearer ${auth.value}`;
|
|
1762
|
+
} else {
|
|
1763
|
+
headers["x-api-key"] = auth.value;
|
|
1764
|
+
}
|
|
1741
1765
|
if (betaHeaders) {
|
|
1742
1766
|
headers["anthropic-beta"] = betaHeaders;
|
|
1743
1767
|
}
|
|
@@ -1748,13 +1772,17 @@ async function forwardToAnthropic(request, targetModel, apiKey, betaHeaders) {
|
|
|
1748
1772
|
});
|
|
1749
1773
|
return response;
|
|
1750
1774
|
}
|
|
1751
|
-
async function forwardToAnthropicStream(request, targetModel,
|
|
1775
|
+
async function forwardToAnthropicStream(request, targetModel, auth, betaHeaders) {
|
|
1752
1776
|
const anthropicBody = buildAnthropicBody(request, targetModel, true);
|
|
1753
1777
|
const headers = {
|
|
1754
1778
|
"Content-Type": "application/json",
|
|
1755
|
-
"x-api-key": apiKey,
|
|
1756
1779
|
"anthropic-version": "2023-06-01"
|
|
1757
1780
|
};
|
|
1781
|
+
if (auth.type === "max") {
|
|
1782
|
+
headers["Authorization"] = `Bearer ${auth.value}`;
|
|
1783
|
+
} else {
|
|
1784
|
+
headers["x-api-key"] = auth.value;
|
|
1785
|
+
}
|
|
1758
1786
|
if (betaHeaders) {
|
|
1759
1787
|
headers["anthropic-beta"] = betaHeaders;
|
|
1760
1788
|
}
|
|
@@ -2560,12 +2588,24 @@ async function startProxy(config = {}) {
|
|
|
2560
2588
|
}
|
|
2561
2589
|
}
|
|
2562
2590
|
log(`Routing to: ${targetProvider}/${targetModel}`);
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
if (
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2591
|
+
let apiKey;
|
|
2592
|
+
let anthropicAuth = null;
|
|
2593
|
+
if (targetProvider === "anthropic") {
|
|
2594
|
+
anthropicAuth = getAnthropicAuth(currentConfig, targetModel);
|
|
2595
|
+
if (!anthropicAuth) {
|
|
2596
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
2597
|
+
res.end(JSON.stringify({ error: "No Anthropic auth configured (set ANTHROPIC_API_KEY or config.auth.anthropicMaxToken)" }));
|
|
2598
|
+
return;
|
|
2599
|
+
}
|
|
2600
|
+
log(`Using ${anthropicAuth.type === "max" ? "MAX token" : "API key"} auth for ${targetModel}`);
|
|
2601
|
+
} else {
|
|
2602
|
+
const apiKeyEnv = DEFAULT_ENDPOINTS[targetProvider]?.apiKeyEnv ?? `${targetProvider.toUpperCase()}_API_KEY`;
|
|
2603
|
+
apiKey = process.env[apiKeyEnv];
|
|
2604
|
+
if (!apiKey) {
|
|
2605
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
2606
|
+
res.end(JSON.stringify({ error: `Missing ${apiKeyEnv} environment variable` }));
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2569
2609
|
}
|
|
2570
2610
|
const startTime = Date.now();
|
|
2571
2611
|
const betaHeaders = req.headers["anthropic-beta"];
|
|
@@ -2576,6 +2616,7 @@ async function startProxy(config = {}) {
|
|
|
2576
2616
|
targetProvider,
|
|
2577
2617
|
targetModel,
|
|
2578
2618
|
apiKey,
|
|
2619
|
+
anthropicAuth,
|
|
2579
2620
|
relay,
|
|
2580
2621
|
promptText,
|
|
2581
2622
|
taskType,
|
|
@@ -2592,6 +2633,7 @@ async function startProxy(config = {}) {
|
|
|
2592
2633
|
targetProvider,
|
|
2593
2634
|
targetModel,
|
|
2594
2635
|
apiKey,
|
|
2636
|
+
anthropicAuth,
|
|
2595
2637
|
relay,
|
|
2596
2638
|
promptText,
|
|
2597
2639
|
taskType,
|
|
@@ -2621,12 +2663,13 @@ async function startProxy(config = {}) {
|
|
|
2621
2663
|
});
|
|
2622
2664
|
});
|
|
2623
2665
|
}
|
|
2624
|
-
async function handleStreamingRequest(res, request, targetProvider, targetModel, apiKey, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2666
|
+
async function handleStreamingRequest(res, request, targetProvider, targetModel, apiKey, anthropicAuth, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2625
2667
|
let providerResponse;
|
|
2626
2668
|
try {
|
|
2627
2669
|
switch (targetProvider) {
|
|
2628
2670
|
case "anthropic":
|
|
2629
|
-
|
|
2671
|
+
if (!anthropicAuth) throw new Error("No Anthropic auth");
|
|
2672
|
+
providerResponse = await forwardToAnthropicStream(request, targetModel, anthropicAuth, betaHeaders);
|
|
2630
2673
|
break;
|
|
2631
2674
|
case "google":
|
|
2632
2675
|
providerResponse = await forwardToGeminiStream(request, targetModel, apiKey);
|
|
@@ -2704,13 +2747,14 @@ async function handleStreamingRequest(res, request, targetProvider, targetModel,
|
|
|
2704
2747
|
});
|
|
2705
2748
|
res.end();
|
|
2706
2749
|
}
|
|
2707
|
-
async function handleNonStreamingRequest(res, request, targetProvider, targetModel, apiKey, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2750
|
+
async function handleNonStreamingRequest(res, request, targetProvider, targetModel, apiKey, anthropicAuth, relay, promptText, taskType, confidence, routingMode, startTime, log, betaHeaders) {
|
|
2708
2751
|
let providerResponse;
|
|
2709
2752
|
let responseData;
|
|
2710
2753
|
try {
|
|
2711
2754
|
switch (targetProvider) {
|
|
2712
2755
|
case "anthropic": {
|
|
2713
|
-
|
|
2756
|
+
if (!anthropicAuth) throw new Error("No Anthropic auth");
|
|
2757
|
+
providerResponse = await forwardToAnthropic(request, targetModel, anthropicAuth, betaHeaders);
|
|
2714
2758
|
const rawData = await providerResponse.json();
|
|
2715
2759
|
if (!providerResponse.ok) {
|
|
2716
2760
|
res.writeHead(providerResponse.status, { "Content-Type": "application/json" });
|