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