opencode-anthropic-multi-account 0.2.17 → 0.2.19
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/dist/index.d.ts +3 -1
- package/dist/index.js +365 -38
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Plugin } from '@opencode-ai/plugin';
|
|
2
2
|
|
|
3
3
|
declare const ClaudeMultiAuthPlugin: Plugin;
|
|
4
|
+
declare function setProviderModelsObserverForTest(observer: ((models: Record<string, unknown>) => void) | null): void;
|
|
5
|
+
declare function resetProviderModelsObserverForTest(): void;
|
|
4
6
|
|
|
5
|
-
export { ClaudeMultiAuthPlugin };
|
|
7
|
+
export { ClaudeMultiAuthPlugin, resetProviderModelsObserverForTest, setProviderModelsObserverForTest };
|
package/dist/index.js
CHANGED
|
@@ -1529,8 +1529,52 @@ function loadClaudeIdentity() {
|
|
|
1529
1529
|
|
|
1530
1530
|
// src/upstream-request.ts
|
|
1531
1531
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "crypto";
|
|
1532
|
+
|
|
1533
|
+
// src/model-capabilities.ts
|
|
1534
|
+
var runtimeModelCapabilities = /* @__PURE__ */ new Map();
|
|
1535
|
+
function isRecord(value) {
|
|
1536
|
+
return typeof value === "object" && value !== null;
|
|
1537
|
+
}
|
|
1538
|
+
function readNumber(value) {
|
|
1539
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1540
|
+
}
|
|
1541
|
+
function readBoolean(value) {
|
|
1542
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1543
|
+
}
|
|
1544
|
+
function normalizeModelId(modelId) {
|
|
1545
|
+
const trimmed = modelId.trim().toLowerCase();
|
|
1546
|
+
const slashIndex = trimmed.indexOf("/");
|
|
1547
|
+
return slashIndex >= 0 ? trimmed.slice(slashIndex + 1) : trimmed;
|
|
1548
|
+
}
|
|
1549
|
+
function readLimitOutput(raw) {
|
|
1550
|
+
const limit = isRecord(raw.limit) ? raw.limit : void 0;
|
|
1551
|
+
const capabilityLimit = isRecord(raw.capabilities) && isRecord(raw.capabilities.limit) ? raw.capabilities.limit : void 0;
|
|
1552
|
+
return readNumber(limit?.output) ?? readNumber(capabilityLimit?.output);
|
|
1553
|
+
}
|
|
1554
|
+
function readThinkingSupport(raw) {
|
|
1555
|
+
return readBoolean(raw.reasoning) ?? readBoolean(raw.thinking) ?? readBoolean(raw.supportsThinking) ?? (isRecord(raw.capabilities) ? readBoolean(raw.capabilities.reasoning) ?? readBoolean(raw.capabilities.thinking) ?? readBoolean(raw.capabilities.supportsThinking) : void 0);
|
|
1556
|
+
}
|
|
1557
|
+
function ingestProviderModelsCapabilities(models) {
|
|
1558
|
+
runtimeModelCapabilities.clear();
|
|
1559
|
+
for (const [key, value] of Object.entries(models)) {
|
|
1560
|
+
if (!isRecord(value)) {
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1563
|
+
const resolvedId = typeof value.id === "string" ? value.id : key;
|
|
1564
|
+
const capability = {
|
|
1565
|
+
maxOutputTokens: readLimitOutput(value),
|
|
1566
|
+
supportsThinking: readThinkingSupport(value)
|
|
1567
|
+
};
|
|
1568
|
+
runtimeModelCapabilities.set(normalizeModelId(resolvedId), capability);
|
|
1569
|
+
runtimeModelCapabilities.set(normalizeModelId(key), capability);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
function getRuntimeModelCapability(modelId) {
|
|
1573
|
+
return runtimeModelCapabilities.get(normalizeModelId(modelId));
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
// src/upstream-request.ts
|
|
1532
1577
|
var BILLING_SEED = "59cf53e54c78";
|
|
1533
|
-
var DEFAULT_CC_VERSION = "2.1.100";
|
|
1534
1578
|
var SESSION_IDLE_ROTATE_MS = 15 * 60 * 1e3;
|
|
1535
1579
|
var MAX_TOOL_RESULT_TEXT_LENGTH = 30 * 1024;
|
|
1536
1580
|
var TRUNCATION_SUFFIX = "[...truncated]";
|
|
@@ -1587,7 +1631,7 @@ function getActiveSessionId() {
|
|
|
1587
1631
|
function getUpstreamSessionId() {
|
|
1588
1632
|
return getActiveSessionId();
|
|
1589
1633
|
}
|
|
1590
|
-
function
|
|
1634
|
+
function isRecord2(value) {
|
|
1591
1635
|
return typeof value === "object" && value !== null;
|
|
1592
1636
|
}
|
|
1593
1637
|
function cloneBody(value) {
|
|
@@ -1611,7 +1655,7 @@ function stripCacheControl(value) {
|
|
|
1611
1655
|
}
|
|
1612
1656
|
return;
|
|
1613
1657
|
}
|
|
1614
|
-
if (!
|
|
1658
|
+
if (!isRecord2(value)) {
|
|
1615
1659
|
return;
|
|
1616
1660
|
}
|
|
1617
1661
|
delete value.cache_control;
|
|
@@ -1633,11 +1677,15 @@ function sanitizeMessageBlock(block) {
|
|
|
1633
1677
|
if (!Array.isArray(block.content)) {
|
|
1634
1678
|
return;
|
|
1635
1679
|
}
|
|
1636
|
-
|
|
1637
|
-
if (
|
|
1638
|
-
|
|
1680
|
+
block.content = block.content.map((item) => {
|
|
1681
|
+
if (isRecord2(item) && typeof item.text === "string") {
|
|
1682
|
+
return {
|
|
1683
|
+
...item,
|
|
1684
|
+
text: truncateToolResultText(sanitizeAndScrubText(item.text))
|
|
1685
|
+
};
|
|
1639
1686
|
}
|
|
1640
|
-
|
|
1687
|
+
return item;
|
|
1688
|
+
}).filter((item) => !isRecord2(item) || typeof item.text !== "string" || item.text.trim().length > 0);
|
|
1641
1689
|
}
|
|
1642
1690
|
function stripAssistantThinkingBlocks(messages) {
|
|
1643
1691
|
for (const message of messages) {
|
|
@@ -1655,9 +1703,12 @@ function hasMeaningfulContent(content) {
|
|
|
1655
1703
|
return false;
|
|
1656
1704
|
}
|
|
1657
1705
|
return content.some((block) => {
|
|
1658
|
-
if (!
|
|
1706
|
+
if (!isRecord2(block)) {
|
|
1659
1707
|
return false;
|
|
1660
1708
|
}
|
|
1709
|
+
if (block.type === "tool_use") {
|
|
1710
|
+
return true;
|
|
1711
|
+
}
|
|
1661
1712
|
if (typeof block.text === "string" && block.text.trim().length > 0) {
|
|
1662
1713
|
return true;
|
|
1663
1714
|
}
|
|
@@ -1676,6 +1727,79 @@ function trimTrailingEmptyTurns(messages) {
|
|
|
1676
1727
|
messages.pop();
|
|
1677
1728
|
}
|
|
1678
1729
|
}
|
|
1730
|
+
function compactMessageContent(messages) {
|
|
1731
|
+
for (const message of messages) {
|
|
1732
|
+
if (!Array.isArray(message.content)) {
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
message.content = message.content.filter((block) => {
|
|
1736
|
+
if (!isRecord2(block)) {
|
|
1737
|
+
return false;
|
|
1738
|
+
}
|
|
1739
|
+
if (block.type === "text") {
|
|
1740
|
+
return typeof block.text !== "string" || block.text.trim().length > 0;
|
|
1741
|
+
}
|
|
1742
|
+
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
1743
|
+
return block.content.length > 0;
|
|
1744
|
+
}
|
|
1745
|
+
return true;
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
function stripUnsupportedSamplingFields(body) {
|
|
1750
|
+
delete body.temperature;
|
|
1751
|
+
delete body.top_p;
|
|
1752
|
+
delete body.top_k;
|
|
1753
|
+
}
|
|
1754
|
+
function stripThinkingControlFields(body) {
|
|
1755
|
+
delete body.thinking;
|
|
1756
|
+
delete body.context_management;
|
|
1757
|
+
delete body.output_config;
|
|
1758
|
+
}
|
|
1759
|
+
var ADAPTIVE_THINKING_MODEL_MATCHERS = [
|
|
1760
|
+
(modelId) => modelId.includes("claude-sonnet-4-6") || modelId.includes("claude-sonnet-4.6"),
|
|
1761
|
+
(modelId) => modelId.includes("claude-opus-4-6") || modelId.includes("claude-opus-4.6"),
|
|
1762
|
+
(modelId) => /claude-opus-4[-._]([7-9]|\d{2,})/.test(modelId)
|
|
1763
|
+
];
|
|
1764
|
+
var LARGE_OUTPUT_MODEL_MATCHERS = [
|
|
1765
|
+
(modelId) => modelId.includes("claude-opus-4-6") || modelId.includes("claude-opus-4.6"),
|
|
1766
|
+
(modelId) => /claude-opus-4[-._]([7-9]|\d{2,})/.test(modelId)
|
|
1767
|
+
];
|
|
1768
|
+
var DEFAULT_MAX_OUTPUT_TOKENS = 64e3;
|
|
1769
|
+
var LARGE_MODEL_MAX_OUTPUT_TOKENS = 128e3;
|
|
1770
|
+
function normalizeModelId2(modelId) {
|
|
1771
|
+
return modelId.trim().toLowerCase();
|
|
1772
|
+
}
|
|
1773
|
+
function supportsAdaptiveThinking(modelId) {
|
|
1774
|
+
const runtimeCapability = getRuntimeModelCapability(modelId);
|
|
1775
|
+
if (typeof runtimeCapability?.supportsThinking === "boolean") {
|
|
1776
|
+
return runtimeCapability.supportsThinking;
|
|
1777
|
+
}
|
|
1778
|
+
const normalized = normalizeModelId2(modelId);
|
|
1779
|
+
if (normalized.includes("haiku")) {
|
|
1780
|
+
return false;
|
|
1781
|
+
}
|
|
1782
|
+
return ADAPTIVE_THINKING_MODEL_MATCHERS.some((matches) => matches(normalized));
|
|
1783
|
+
}
|
|
1784
|
+
function getModelMaxOutputTokens(modelId) {
|
|
1785
|
+
const runtimeCapability = getRuntimeModelCapability(modelId);
|
|
1786
|
+
if (typeof runtimeCapability?.maxOutputTokens === "number") {
|
|
1787
|
+
return runtimeCapability.maxOutputTokens;
|
|
1788
|
+
}
|
|
1789
|
+
const normalized = normalizeModelId2(modelId);
|
|
1790
|
+
return LARGE_OUTPUT_MODEL_MATCHERS.some((matches) => matches(normalized)) ? LARGE_MODEL_MAX_OUTPUT_TOKENS : DEFAULT_MAX_OUTPUT_TOKENS;
|
|
1791
|
+
}
|
|
1792
|
+
function resolveMaxTokens(modelId, requestedMaxTokens) {
|
|
1793
|
+
const modelCap = getModelMaxOutputTokens(modelId);
|
|
1794
|
+
if (typeof requestedMaxTokens !== "number" || !Number.isFinite(requestedMaxTokens)) {
|
|
1795
|
+
return modelCap;
|
|
1796
|
+
}
|
|
1797
|
+
const normalized = Math.floor(requestedMaxTokens);
|
|
1798
|
+
if (normalized <= 0) {
|
|
1799
|
+
return modelCap;
|
|
1800
|
+
}
|
|
1801
|
+
return Math.min(normalized, modelCap);
|
|
1802
|
+
}
|
|
1679
1803
|
function normalizeSystemTexts(system) {
|
|
1680
1804
|
if (typeof system === "string") {
|
|
1681
1805
|
const next = sanitizeAndScrubText(system);
|
|
@@ -1693,7 +1817,7 @@ function normalizeSystemTexts(system) {
|
|
|
1693
1817
|
}
|
|
1694
1818
|
continue;
|
|
1695
1819
|
}
|
|
1696
|
-
if (
|
|
1820
|
+
if (isRecord2(entry) && typeof entry.text === "string") {
|
|
1697
1821
|
const next = sanitizeAndScrubText(entry.text);
|
|
1698
1822
|
if (next) {
|
|
1699
1823
|
texts.push(next);
|
|
@@ -1727,8 +1851,29 @@ function extractFirstUserMessage(messages) {
|
|
|
1727
1851
|
function hasCompleteToolSchemas(tools) {
|
|
1728
1852
|
return tools.length > 0 && tools.every((tool2) => typeof tool2 === "object" && tool2 !== null && "input_schema" in tool2);
|
|
1729
1853
|
}
|
|
1854
|
+
function enrichIncomingToolsWithTemplateSchemas(incomingTools, templateTools) {
|
|
1855
|
+
if (!hasCompleteToolSchemas(templateTools) || incomingTools.length !== templateTools.length) {
|
|
1856
|
+
return incomingTools;
|
|
1857
|
+
}
|
|
1858
|
+
return incomingTools.map((tool2, index) => {
|
|
1859
|
+
if ("input_schema" in tool2) {
|
|
1860
|
+
return tool2;
|
|
1861
|
+
}
|
|
1862
|
+
const templateTool = templateTools[index];
|
|
1863
|
+
return templateTool && "input_schema" in templateTool ? { ...tool2, input_schema: templateTool.input_schema } : tool2;
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
function buildOutboundTools(incomingTools, templateTools) {
|
|
1867
|
+
if (incomingTools.length > 0) {
|
|
1868
|
+
return enrichIncomingToolsWithTemplateSchemas(incomingTools, templateTools);
|
|
1869
|
+
}
|
|
1870
|
+
if (!hasCompleteToolSchemas(templateTools)) {
|
|
1871
|
+
return incomingTools;
|
|
1872
|
+
}
|
|
1873
|
+
return templateTools.map((tool2) => ({ ...tool2 }));
|
|
1874
|
+
}
|
|
1730
1875
|
function getCcVersion(template) {
|
|
1731
|
-
return template.cc_version ??
|
|
1876
|
+
return template.cc_version ?? detectCliVersion();
|
|
1732
1877
|
}
|
|
1733
1878
|
function buildBillingHeader(firstUserMessage, template) {
|
|
1734
1879
|
const version = getCcVersion(template);
|
|
@@ -1754,7 +1899,7 @@ function reverseMapToolUseNames(value, reverseLookup) {
|
|
|
1754
1899
|
if (Array.isArray(value)) {
|
|
1755
1900
|
return value.map((item) => reverseMapToolUseNames(item, reverseLookup));
|
|
1756
1901
|
}
|
|
1757
|
-
if (!
|
|
1902
|
+
if (!isRecord2(value)) {
|
|
1758
1903
|
return value;
|
|
1759
1904
|
}
|
|
1760
1905
|
const cloned = {};
|
|
@@ -1787,7 +1932,7 @@ function sanitizeMessages(body) {
|
|
|
1787
1932
|
return;
|
|
1788
1933
|
}
|
|
1789
1934
|
for (const message of messages) {
|
|
1790
|
-
if (!
|
|
1935
|
+
if (!isRecord2(message)) {
|
|
1791
1936
|
continue;
|
|
1792
1937
|
}
|
|
1793
1938
|
if (typeof message.content === "string") {
|
|
@@ -1798,7 +1943,7 @@ function sanitizeMessages(body) {
|
|
|
1798
1943
|
continue;
|
|
1799
1944
|
}
|
|
1800
1945
|
for (const block of message.content) {
|
|
1801
|
-
if (
|
|
1946
|
+
if (isRecord2(block) && typeof block.text === "string") {
|
|
1802
1947
|
block.text = sanitizeContent(block.text);
|
|
1803
1948
|
}
|
|
1804
1949
|
}
|
|
@@ -1850,6 +1995,7 @@ function buildUpstreamRequest(inputBody, identity, template, options) {
|
|
|
1850
1995
|
sanitizeMessageBlock(block);
|
|
1851
1996
|
}
|
|
1852
1997
|
}
|
|
1998
|
+
compactMessageContent(messages);
|
|
1853
1999
|
trimTrailingEmptyTurns(messages);
|
|
1854
2000
|
const firstUserMessage = extractFirstUserMessage(messages);
|
|
1855
2001
|
const billingHeader = buildBillingHeader(firstUserMessage, template);
|
|
@@ -1859,8 +2005,10 @@ function buildUpstreamRequest(inputBody, identity, template, options) {
|
|
|
1859
2005
|
].map((entry) => sanitizeAndScrubText(entry)).filter(Boolean).join("\n\n");
|
|
1860
2006
|
const activeSessionId = options?.sessionId ?? getActiveSessionId();
|
|
1861
2007
|
body.messages = messages;
|
|
2008
|
+
stripUnsupportedSamplingFields(body);
|
|
2009
|
+
stripThinkingControlFields(body);
|
|
1862
2010
|
const incomingTools = Array.isArray(body.tools) ? body.tools : [];
|
|
1863
|
-
body.tools =
|
|
2011
|
+
body.tools = buildOutboundTools(incomingTools, template.tools);
|
|
1864
2012
|
body.system = [
|
|
1865
2013
|
{
|
|
1866
2014
|
type: "text",
|
|
@@ -1878,17 +2026,20 @@ function buildUpstreamRequest(inputBody, identity, template, options) {
|
|
|
1878
2026
|
}
|
|
1879
2027
|
];
|
|
1880
2028
|
body.metadata = {
|
|
1881
|
-
...
|
|
2029
|
+
...isRecord2(body.metadata) ? body.metadata : {},
|
|
1882
2030
|
user_id: JSON.stringify({
|
|
1883
2031
|
device_id: identity.deviceId,
|
|
1884
2032
|
account_uuid: identity.accountUuid,
|
|
1885
2033
|
session_id: activeSessionId
|
|
1886
2034
|
})
|
|
1887
2035
|
};
|
|
1888
|
-
body.
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
2036
|
+
const modelId = typeof body.model === "string" ? body.model : "";
|
|
2037
|
+
if (supportsAdaptiveThinking(modelId)) {
|
|
2038
|
+
body.thinking = { type: "adaptive" };
|
|
2039
|
+
body.context_management = DEFAULT_CONTEXT_MANAGEMENT;
|
|
2040
|
+
body.output_config = DEFAULT_OUTPUT_CONFIG;
|
|
2041
|
+
}
|
|
2042
|
+
body.max_tokens = resolveMaxTokens(modelId, body.max_tokens);
|
|
1892
2043
|
return orderBodyForOutbound(body, template.body_field_order);
|
|
1893
2044
|
}
|
|
1894
2045
|
function orderBodyForOutbound(body, overrideOrder) {
|
|
@@ -1962,6 +2113,149 @@ function createStreamingReverseMapper(response, reverseLookup) {
|
|
|
1962
2113
|
});
|
|
1963
2114
|
}
|
|
1964
2115
|
|
|
2116
|
+
// src/tool-flow.ts
|
|
2117
|
+
import { createHash as createHash3 } from "crypto";
|
|
2118
|
+
var TOOL_MASK_PREFIX = "tool_";
|
|
2119
|
+
function isRecord3(value) {
|
|
2120
|
+
return typeof value === "object" && value !== null;
|
|
2121
|
+
}
|
|
2122
|
+
function shouldMaskToolName(name, claudeToolNames) {
|
|
2123
|
+
if (!name) {
|
|
2124
|
+
return false;
|
|
2125
|
+
}
|
|
2126
|
+
return !claudeToolNames.has(name) && !name.startsWith("mcp__") && !name.startsWith(TOOL_MASK_PREFIX);
|
|
2127
|
+
}
|
|
2128
|
+
function extractFirstUserText(parsed) {
|
|
2129
|
+
if (!Array.isArray(parsed.messages)) {
|
|
2130
|
+
return "";
|
|
2131
|
+
}
|
|
2132
|
+
const firstUser = parsed.messages.find((message) => message.role === "user");
|
|
2133
|
+
if (!isRecord3(firstUser)) {
|
|
2134
|
+
return "";
|
|
2135
|
+
}
|
|
2136
|
+
const content = firstUser.content;
|
|
2137
|
+
if (typeof content === "string") {
|
|
2138
|
+
return content.trim();
|
|
2139
|
+
}
|
|
2140
|
+
if (!Array.isArray(content)) {
|
|
2141
|
+
return "";
|
|
2142
|
+
}
|
|
2143
|
+
return content.filter((block) => isRecord3(block) && block.type === "text" && typeof block.text === "string").map((block) => String(block.text)).join("\n\n").trim();
|
|
2144
|
+
}
|
|
2145
|
+
function buildMaskedToolName(seed, toolName, length = 8) {
|
|
2146
|
+
const digest = createHash3("sha256").update(`tool-mask:${seed}:${toolName}`).digest("hex").slice(0, length);
|
|
2147
|
+
return `${TOOL_MASK_PREFIX}${digest}`;
|
|
2148
|
+
}
|
|
2149
|
+
function collectToolNames(parsed) {
|
|
2150
|
+
const names = /* @__PURE__ */ new Set();
|
|
2151
|
+
if (Array.isArray(parsed.tools)) {
|
|
2152
|
+
for (const tool2 of parsed.tools) {
|
|
2153
|
+
if (isRecord3(tool2) && typeof tool2.name === "string") {
|
|
2154
|
+
names.add(tool2.name);
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
if (Array.isArray(parsed.messages)) {
|
|
2159
|
+
for (const message of parsed.messages) {
|
|
2160
|
+
if (!isRecord3(message) || !Array.isArray(message.content)) {
|
|
2161
|
+
continue;
|
|
2162
|
+
}
|
|
2163
|
+
for (const block of message.content) {
|
|
2164
|
+
if (isRecord3(block) && block.type === "tool_use" && typeof block.name === "string") {
|
|
2165
|
+
names.add(block.name);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
if (isRecord3(parsed.tool_choice) && parsed.tool_choice.type === "tool" && typeof parsed.tool_choice.name === "string") {
|
|
2171
|
+
names.add(parsed.tool_choice.name);
|
|
2172
|
+
}
|
|
2173
|
+
return [...names];
|
|
2174
|
+
}
|
|
2175
|
+
function buildClaudeToolNameSet(claudeToolNames) {
|
|
2176
|
+
return new Set(claudeToolNames.filter((name) => typeof name === "string" && name.length > 0));
|
|
2177
|
+
}
|
|
2178
|
+
function buildRequestScopedToolLookup(parsed, claudeToolNames) {
|
|
2179
|
+
const lookup = /* @__PURE__ */ new Map();
|
|
2180
|
+
const usedOutgoing = /* @__PURE__ */ new Set();
|
|
2181
|
+
const seed = extractFirstUserText(parsed);
|
|
2182
|
+
const claudeToolSet = buildClaudeToolNameSet(claudeToolNames);
|
|
2183
|
+
for (const originalName of collectToolNames(parsed)) {
|
|
2184
|
+
if (!shouldMaskToolName(originalName, claudeToolSet)) {
|
|
2185
|
+
lookup.set(originalName, originalName);
|
|
2186
|
+
usedOutgoing.add(originalName);
|
|
2187
|
+
continue;
|
|
2188
|
+
}
|
|
2189
|
+
let length = 8;
|
|
2190
|
+
let masked = buildMaskedToolName(seed, originalName, length);
|
|
2191
|
+
while (usedOutgoing.has(masked)) {
|
|
2192
|
+
length += 2;
|
|
2193
|
+
masked = buildMaskedToolName(seed, originalName, length);
|
|
2194
|
+
}
|
|
2195
|
+
lookup.set(masked, originalName);
|
|
2196
|
+
usedOutgoing.add(masked);
|
|
2197
|
+
}
|
|
2198
|
+
return lookup;
|
|
2199
|
+
}
|
|
2200
|
+
function getOutgoingName(name, reverseLookup) {
|
|
2201
|
+
if (!name) {
|
|
2202
|
+
return name;
|
|
2203
|
+
}
|
|
2204
|
+
for (const [outgoing, original] of reverseLookup) {
|
|
2205
|
+
if (original === name) {
|
|
2206
|
+
return outgoing;
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
return name;
|
|
2210
|
+
}
|
|
2211
|
+
function rewriteToolUseNames(value, reverseLookup) {
|
|
2212
|
+
if (Array.isArray(value)) {
|
|
2213
|
+
return value.map((item) => rewriteToolUseNames(item, reverseLookup));
|
|
2214
|
+
}
|
|
2215
|
+
if (!isRecord3(value)) {
|
|
2216
|
+
return value;
|
|
2217
|
+
}
|
|
2218
|
+
const cloned = {};
|
|
2219
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
2220
|
+
cloned[key] = rewriteToolUseNames(nested, reverseLookup);
|
|
2221
|
+
}
|
|
2222
|
+
if (cloned.type === "tool_use" && typeof cloned.name === "string") {
|
|
2223
|
+
cloned.name = getOutgoingName(cloned.name, reverseLookup);
|
|
2224
|
+
}
|
|
2225
|
+
return cloned;
|
|
2226
|
+
}
|
|
2227
|
+
function applyOutboundToolFlow(parsed, claudeToolNames) {
|
|
2228
|
+
const reverseLookup = buildRequestScopedToolLookup(parsed, claudeToolNames);
|
|
2229
|
+
const next = { ...parsed };
|
|
2230
|
+
if (Array.isArray(parsed.tools)) {
|
|
2231
|
+
next.tools = parsed.tools.map((tool2) => ({
|
|
2232
|
+
...tool2,
|
|
2233
|
+
name: getOutgoingName(tool2.name, reverseLookup)
|
|
2234
|
+
}));
|
|
2235
|
+
}
|
|
2236
|
+
if (Array.isArray(parsed.messages)) {
|
|
2237
|
+
next.messages = parsed.messages.map((message) => {
|
|
2238
|
+
if (!isRecord3(message) || !Array.isArray(message.content)) {
|
|
2239
|
+
return message;
|
|
2240
|
+
}
|
|
2241
|
+
return {
|
|
2242
|
+
...message,
|
|
2243
|
+
content: rewriteToolUseNames(message.content, reverseLookup)
|
|
2244
|
+
};
|
|
2245
|
+
});
|
|
2246
|
+
}
|
|
2247
|
+
if (isRecord3(parsed.tool_choice) && parsed.tool_choice.type === "tool") {
|
|
2248
|
+
next.tool_choice = {
|
|
2249
|
+
...parsed.tool_choice,
|
|
2250
|
+
name: getOutgoingName(parsed.tool_choice.name, reverseLookup)
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
return {
|
|
2254
|
+
body: JSON.stringify(next),
|
|
2255
|
+
reverseLookup
|
|
2256
|
+
};
|
|
2257
|
+
}
|
|
2258
|
+
|
|
1965
2259
|
// src/upstream-headers.ts
|
|
1966
2260
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
1967
2261
|
var UPSTREAM_TIMEOUT_MS = 3e5;
|
|
@@ -2048,6 +2342,9 @@ function filterBillableBetas(betas) {
|
|
|
2048
2342
|
}
|
|
2049
2343
|
|
|
2050
2344
|
// src/request-transform.ts
|
|
2345
|
+
function applyRequestToolMasking(parsed, claudeToolNames) {
|
|
2346
|
+
return applyOutboundToolFlow(parsed, claudeToolNames);
|
|
2347
|
+
}
|
|
2051
2348
|
function extractModelIdFromBody(body) {
|
|
2052
2349
|
if (typeof body !== "string") {
|
|
2053
2350
|
return "unknown";
|
|
@@ -2258,18 +2555,38 @@ function transformBodyToUpstream(body, identity, sessionId2) {
|
|
|
2258
2555
|
try {
|
|
2259
2556
|
const parsed = JSON.parse(body);
|
|
2260
2557
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2261
|
-
return body;
|
|
2262
|
-
}
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
)
|
|
2558
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2559
|
+
}
|
|
2560
|
+
const template = loadTemplate();
|
|
2561
|
+
const upstreamRequest = buildUpstreamRequest(
|
|
2562
|
+
parsed,
|
|
2563
|
+
identity,
|
|
2564
|
+
template,
|
|
2565
|
+
{ sessionId: sessionId2 }
|
|
2270
2566
|
);
|
|
2567
|
+
return applyRequestToolMasking(upstreamRequest, template.tool_names);
|
|
2271
2568
|
} catch {
|
|
2272
|
-
return body;
|
|
2569
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
async function applyResponseReverseLookup(response, reverseLookup) {
|
|
2573
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
2574
|
+
if (contentType.includes("text/event-stream")) {
|
|
2575
|
+
return createStreamingReverseMapper(response, reverseLookup);
|
|
2576
|
+
}
|
|
2577
|
+
if (!contentType.includes("application/json") || reverseLookup.size === 0) {
|
|
2578
|
+
return response;
|
|
2579
|
+
}
|
|
2580
|
+
try {
|
|
2581
|
+
const payload = await response.clone().json();
|
|
2582
|
+
const remapped = reverseMapResponse(payload, reverseLookup);
|
|
2583
|
+
return new Response(JSON.stringify(remapped), {
|
|
2584
|
+
status: response.status,
|
|
2585
|
+
statusText: response.statusText,
|
|
2586
|
+
headers: new Headers(response.headers)
|
|
2587
|
+
});
|
|
2588
|
+
} catch {
|
|
2589
|
+
return response;
|
|
2273
2590
|
}
|
|
2274
2591
|
}
|
|
2275
2592
|
async function enrichRateLimitResponse(response) {
|
|
@@ -2393,7 +2710,7 @@ var AccountRuntimeFactory = class {
|
|
|
2393
2710
|
void recordObservedToolNames(extractToolNamesFromRequestBody(init.body)).catch(() => {
|
|
2394
2711
|
});
|
|
2395
2712
|
}
|
|
2396
|
-
const
|
|
2713
|
+
const transformedRequest = typeof init?.body === "string" ? transformBodyToUpstream(init.body, this.identity, sessionId2) : { body: init?.body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2397
2714
|
const pacingCfg = resolvePacingConfig();
|
|
2398
2715
|
const getNow = this.pacingTestOverrides.now ?? Date.now;
|
|
2399
2716
|
const sleepFn = this.pacingTestOverrides.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
@@ -2420,7 +2737,7 @@ var AccountRuntimeFactory = class {
|
|
|
2420
2737
|
const response2 = await fetch(transformedInput, {
|
|
2421
2738
|
...init,
|
|
2422
2739
|
headers: requestHeaders,
|
|
2423
|
-
body:
|
|
2740
|
+
body: transformedRequest.body
|
|
2424
2741
|
});
|
|
2425
2742
|
return await enrichRateLimitResponse(response2);
|
|
2426
2743
|
} catch (error) {
|
|
@@ -2453,7 +2770,7 @@ var AccountRuntimeFactory = class {
|
|
|
2453
2770
|
);
|
|
2454
2771
|
response = await performFetch(retryHeaders);
|
|
2455
2772
|
}
|
|
2456
|
-
return
|
|
2773
|
+
return applyResponseReverseLookup(response, transformedRequest.reverseLookup);
|
|
2457
2774
|
}
|
|
2458
2775
|
async createRuntime(uuid) {
|
|
2459
2776
|
const fetchWithAccount = async (input, init) => {
|
|
@@ -2463,9 +2780,8 @@ var AccountRuntimeFactory = class {
|
|
|
2463
2780
|
throw new Error(`No credentials found for account ${uuid}`);
|
|
2464
2781
|
}
|
|
2465
2782
|
let accessToken = storedAccount.accessToken;
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
({ accessToken, expiresAt } = await this.ensureFreshToken(storedAccount, uuid));
|
|
2783
|
+
if (!accessToken || !storedAccount.expiresAt || isTokenExpired({ accessToken, expiresAt: storedAccount.expiresAt })) {
|
|
2784
|
+
({ accessToken } = await this.ensureFreshToken(storedAccount, uuid));
|
|
2469
2785
|
}
|
|
2470
2786
|
if (!accessToken) {
|
|
2471
2787
|
throw new Error(`No access token available for account ${uuid}`);
|
|
@@ -2626,7 +2942,8 @@ var EMPTY_OAUTH_CREDENTIALS = {
|
|
|
2626
2942
|
access: "",
|
|
2627
2943
|
expires: 0
|
|
2628
2944
|
};
|
|
2629
|
-
|
|
2945
|
+
var providerModelsObserverForTest = null;
|
|
2946
|
+
function extractFirstUserText2(input) {
|
|
2630
2947
|
try {
|
|
2631
2948
|
const raw = input;
|
|
2632
2949
|
const messages = raw.messages ?? raw.request?.messages;
|
|
@@ -2819,7 +3136,7 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
2819
3136
|
});
|
|
2820
3137
|
return {
|
|
2821
3138
|
"experimental.chat.system.transform": (input, output) => {
|
|
2822
|
-
const billingHeader = composeBillingSystemEntry(
|
|
3139
|
+
const billingHeader = composeBillingSystemEntry(extractFirstUserText2(input), claudeCodeVersion);
|
|
2823
3140
|
prependMissingSystemEntries(output, [
|
|
2824
3141
|
billingHeader,
|
|
2825
3142
|
upstreamAgentIdentity,
|
|
@@ -2894,6 +3211,8 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
2894
3211
|
{ type: "api", label: "Manually enter API Key" }
|
|
2895
3212
|
],
|
|
2896
3213
|
async loader(getAuth, provider) {
|
|
3214
|
+
providerModelsObserverForTest?.(provider.models ?? {});
|
|
3215
|
+
ingestProviderModelsCapabilities(provider.models ?? {});
|
|
2897
3216
|
const auth = await getAuth();
|
|
2898
3217
|
if (auth.type !== "oauth") {
|
|
2899
3218
|
stopHeartbeat();
|
|
@@ -2979,7 +3298,15 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
2979
3298
|
}
|
|
2980
3299
|
};
|
|
2981
3300
|
};
|
|
3301
|
+
function setProviderModelsObserverForTest(observer) {
|
|
3302
|
+
providerModelsObserverForTest = observer;
|
|
3303
|
+
}
|
|
3304
|
+
function resetProviderModelsObserverForTest() {
|
|
3305
|
+
providerModelsObserverForTest = null;
|
|
3306
|
+
}
|
|
2982
3307
|
export {
|
|
2983
|
-
ClaudeMultiAuthPlugin
|
|
3308
|
+
ClaudeMultiAuthPlugin,
|
|
3309
|
+
resetProviderModelsObserverForTest,
|
|
3310
|
+
setProviderModelsObserverForTest
|
|
2984
3311
|
};
|
|
2985
3312
|
//# sourceMappingURL=index.js.map
|