opencode-anthropic-multi-account 0.2.22 → 0.2.23
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.js
CHANGED
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
showToast,
|
|
26
26
|
sleep,
|
|
27
27
|
updateConfigField
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-2SN3UVSM.js";
|
|
29
29
|
import "./chunk-RAX4SFCO.js";
|
|
30
30
|
|
|
31
31
|
// src/index.ts
|
|
@@ -1394,6 +1394,7 @@ function getModelOverride(modelId) {
|
|
|
1394
1394
|
|
|
1395
1395
|
// src/betas.ts
|
|
1396
1396
|
var LONG_CONTEXT_BETAS = config.longContextBetas;
|
|
1397
|
+
var OAUTH_BETA = "oauth-2025-04-20";
|
|
1397
1398
|
var excludedBetas = /* @__PURE__ */ new Map();
|
|
1398
1399
|
var lastBetaFlagsEnv = process.env.ANTHROPIC_BETA_FLAGS;
|
|
1399
1400
|
var lastModelId;
|
|
@@ -1417,6 +1418,19 @@ function addExcludedBeta(modelId, beta) {
|
|
|
1417
1418
|
function isLongContextError(responseBody) {
|
|
1418
1419
|
return responseBody.includes("Extra usage is required for long context requests") || responseBody.includes("long context beta is not yet available");
|
|
1419
1420
|
}
|
|
1421
|
+
function isUnexpectedBetaError(responseBody) {
|
|
1422
|
+
return responseBody.includes("Unexpected value") && responseBody.includes("anthropic-beta");
|
|
1423
|
+
}
|
|
1424
|
+
function extractRejectedBetas(responseBody) {
|
|
1425
|
+
const match = /Unexpected value\(s\):\s*([^\n]+?)\s*for the anthropic-beta header/i.exec(responseBody);
|
|
1426
|
+
if (!match?.[1]) {
|
|
1427
|
+
return [];
|
|
1428
|
+
}
|
|
1429
|
+
return match[1].split(",").map((value) => value.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
|
|
1430
|
+
}
|
|
1431
|
+
function ensureOauthBeta(betas) {
|
|
1432
|
+
return betas.includes(OAUTH_BETA) ? betas : [OAUTH_BETA, ...betas];
|
|
1433
|
+
}
|
|
1420
1434
|
function getNextBetaToExclude(modelId) {
|
|
1421
1435
|
const excluded = getExcludedBetas(modelId);
|
|
1422
1436
|
for (const beta of LONG_CONTEXT_BETAS) {
|
|
@@ -1703,7 +1717,7 @@ function hasMeaningfulContent(content) {
|
|
|
1703
1717
|
if (!isRecord2(block)) {
|
|
1704
1718
|
return false;
|
|
1705
1719
|
}
|
|
1706
|
-
if (block.type === "tool_use") {
|
|
1720
|
+
if (block.type === "tool_use" || block.type === "tool_result") {
|
|
1707
1721
|
return true;
|
|
1708
1722
|
}
|
|
1709
1723
|
if (typeof block.text === "string" && block.text.trim().length > 0) {
|
|
@@ -1736,13 +1750,46 @@ function compactMessageContent(messages) {
|
|
|
1736
1750
|
if (block.type === "text") {
|
|
1737
1751
|
return typeof block.text !== "string" || block.text.trim().length > 0;
|
|
1738
1752
|
}
|
|
1739
|
-
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
1740
|
-
return block.content.length > 0;
|
|
1741
|
-
}
|
|
1742
1753
|
return true;
|
|
1743
1754
|
});
|
|
1744
1755
|
}
|
|
1745
1756
|
}
|
|
1757
|
+
function collectToolUseIds(message) {
|
|
1758
|
+
if (!Array.isArray(message.content)) {
|
|
1759
|
+
return [];
|
|
1760
|
+
}
|
|
1761
|
+
return message.content.filter((block) => isRecord2(block) && block.type === "tool_use" && typeof block.id === "string").map((block) => String(block.id));
|
|
1762
|
+
}
|
|
1763
|
+
function collectToolResultIds(message) {
|
|
1764
|
+
if (!Array.isArray(message.content)) {
|
|
1765
|
+
return /* @__PURE__ */ new Set();
|
|
1766
|
+
}
|
|
1767
|
+
return new Set(
|
|
1768
|
+
message.content.filter((block) => isRecord2(block) && block.type === "tool_result" && typeof block.tool_use_id === "string").map((block) => String(block.tool_use_id))
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1771
|
+
function getDanglingToolUseError(messages) {
|
|
1772
|
+
for (let index = 0; index < messages.length; index += 1) {
|
|
1773
|
+
const current = messages[index];
|
|
1774
|
+
if (!current || current.role !== "assistant") {
|
|
1775
|
+
continue;
|
|
1776
|
+
}
|
|
1777
|
+
const toolUseIds = collectToolUseIds(current);
|
|
1778
|
+
if (toolUseIds.length === 0) {
|
|
1779
|
+
continue;
|
|
1780
|
+
}
|
|
1781
|
+
const next = messages[index + 1];
|
|
1782
|
+
if (!next || next.role !== "user") {
|
|
1783
|
+
return `Dangling tool_use after assistant turn ${index}: ${toolUseIds.join(", ")}`;
|
|
1784
|
+
}
|
|
1785
|
+
const toolResultIds = collectToolResultIds(next);
|
|
1786
|
+
const missing = toolUseIds.filter((toolUseId) => !toolResultIds.has(toolUseId));
|
|
1787
|
+
if (missing.length > 0) {
|
|
1788
|
+
return `Missing tool_result for assistant turn ${index}: ${missing.join(", ")}`;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
return null;
|
|
1792
|
+
}
|
|
1746
1793
|
function stripUnsupportedSamplingFields(body) {
|
|
1747
1794
|
delete body.temperature;
|
|
1748
1795
|
delete body.top_p;
|
|
@@ -2112,25 +2159,8 @@ function shouldMaskToolName(name, claudeToolNames) {
|
|
|
2112
2159
|
}
|
|
2113
2160
|
return !claudeToolNames.has(name) && !name.startsWith("mcp__") && !name.startsWith(TOOL_MASK_PREFIX);
|
|
2114
2161
|
}
|
|
2115
|
-
function
|
|
2116
|
-
|
|
2117
|
-
return "";
|
|
2118
|
-
}
|
|
2119
|
-
const firstUser = parsed.messages.find((message) => message.role === "user");
|
|
2120
|
-
if (!isRecord3(firstUser)) {
|
|
2121
|
-
return "";
|
|
2122
|
-
}
|
|
2123
|
-
const content = firstUser.content;
|
|
2124
|
-
if (typeof content === "string") {
|
|
2125
|
-
return content.trim();
|
|
2126
|
-
}
|
|
2127
|
-
if (!Array.isArray(content)) {
|
|
2128
|
-
return "";
|
|
2129
|
-
}
|
|
2130
|
-
return content.filter((block) => isRecord3(block) && block.type === "text" && typeof block.text === "string").map((block) => String(block.text)).join("\n\n").trim();
|
|
2131
|
-
}
|
|
2132
|
-
function buildMaskedToolName(seed, toolName, length = 8) {
|
|
2133
|
-
const digest = createHash3("sha256").update(`tool-mask:${seed}:${toolName}`).digest("hex").slice(0, length);
|
|
2162
|
+
function buildMaskedToolName(toolName, length = 8) {
|
|
2163
|
+
const digest = createHash3("sha256").update(`tool-mask:${toolName}`).digest("hex").slice(0, length);
|
|
2134
2164
|
return `${TOOL_MASK_PREFIX}${digest}`;
|
|
2135
2165
|
}
|
|
2136
2166
|
function collectToolNames(parsed) {
|
|
@@ -2165,7 +2195,6 @@ function buildClaudeToolNameSet(claudeToolNames) {
|
|
|
2165
2195
|
function buildRequestScopedToolLookup(parsed, claudeToolNames) {
|
|
2166
2196
|
const lookup = /* @__PURE__ */ new Map();
|
|
2167
2197
|
const usedOutgoing = /* @__PURE__ */ new Set();
|
|
2168
|
-
const seed = extractFirstUserText(parsed);
|
|
2169
2198
|
const claudeToolSet = buildClaudeToolNameSet(claudeToolNames);
|
|
2170
2199
|
for (const originalName of collectToolNames(parsed)) {
|
|
2171
2200
|
if (!shouldMaskToolName(originalName, claudeToolSet)) {
|
|
@@ -2174,10 +2203,10 @@ function buildRequestScopedToolLookup(parsed, claudeToolNames) {
|
|
|
2174
2203
|
continue;
|
|
2175
2204
|
}
|
|
2176
2205
|
let length = 8;
|
|
2177
|
-
let masked = buildMaskedToolName(
|
|
2206
|
+
let masked = buildMaskedToolName(originalName, length);
|
|
2178
2207
|
while (usedOutgoing.has(masked)) {
|
|
2179
2208
|
length += 2;
|
|
2180
|
-
masked = buildMaskedToolName(
|
|
2209
|
+
masked = buildMaskedToolName(originalName, length);
|
|
2181
2210
|
}
|
|
2182
2211
|
lookup.set(masked, originalName);
|
|
2183
2212
|
usedOutgoing.add(masked);
|
|
@@ -2542,7 +2571,7 @@ function transformBodyToUpstream(body, identity, sessionId2) {
|
|
|
2542
2571
|
try {
|
|
2543
2572
|
const parsed = JSON.parse(body);
|
|
2544
2573
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2545
|
-
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2574
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map(), validationError: null };
|
|
2546
2575
|
}
|
|
2547
2576
|
const template = loadTemplate();
|
|
2548
2577
|
const upstreamRequest = buildUpstreamRequest(
|
|
@@ -2551,9 +2580,16 @@ function transformBodyToUpstream(body, identity, sessionId2) {
|
|
|
2551
2580
|
template,
|
|
2552
2581
|
{ sessionId: sessionId2 }
|
|
2553
2582
|
);
|
|
2554
|
-
|
|
2583
|
+
const validationError = getDanglingToolUseError(
|
|
2584
|
+
Array.isArray(upstreamRequest.messages) ? upstreamRequest.messages : []
|
|
2585
|
+
);
|
|
2586
|
+
const maskedRequest = applyRequestToolMasking(upstreamRequest, template.tool_names);
|
|
2587
|
+
return {
|
|
2588
|
+
...maskedRequest,
|
|
2589
|
+
validationError
|
|
2590
|
+
};
|
|
2555
2591
|
} catch {
|
|
2556
|
-
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2592
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map(), validationError: null };
|
|
2557
2593
|
}
|
|
2558
2594
|
}
|
|
2559
2595
|
async function applyResponseReverseLookup(response, reverseLookup) {
|
|
@@ -2665,11 +2701,11 @@ var AccountRuntimeFactory = class {
|
|
|
2665
2701
|
return { accessToken: refreshed.patch.accessToken, expiresAt: refreshed.patch.expiresAt };
|
|
2666
2702
|
}
|
|
2667
2703
|
buildOutboundHeaders(incomingHeaders, sessionId2, accessToken, modelId, excludedBetas2) {
|
|
2668
|
-
const mergedBetas = deduplicateBetas([
|
|
2704
|
+
const mergedBetas = deduplicateBetas(ensureOauthBeta([
|
|
2669
2705
|
...excludeBetas(splitBetaValues(getBetaHeader()), excludedBetas2),
|
|
2670
2706
|
...getModelBetas(modelId, excludedBetas2),
|
|
2671
2707
|
...excludeBetas(splitBetaValues(incomingHeaders["anthropic-beta"]), excludedBetas2)
|
|
2672
|
-
]).join(",");
|
|
2708
|
+
])).join(",");
|
|
2673
2709
|
const outbound = {
|
|
2674
2710
|
...incomingHeaders,
|
|
2675
2711
|
...getStaticHeaders(),
|
|
@@ -2697,7 +2733,18 @@ var AccountRuntimeFactory = class {
|
|
|
2697
2733
|
void recordObservedToolNames(extractToolNamesFromRequestBody(init.body)).catch(() => {
|
|
2698
2734
|
});
|
|
2699
2735
|
}
|
|
2700
|
-
const transformedRequest = typeof init?.body === "string" ? transformBodyToUpstream(init.body, this.identity, sessionId2) : { body: init?.body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2736
|
+
const transformedRequest = typeof init?.body === "string" ? transformBodyToUpstream(init.body, this.identity, sessionId2) : { body: init?.body, reverseLookup: /* @__PURE__ */ new Map(), validationError: null };
|
|
2737
|
+
if (transformedRequest.validationError) {
|
|
2738
|
+
return new Response(JSON.stringify({
|
|
2739
|
+
error: {
|
|
2740
|
+
message: transformedRequest.validationError,
|
|
2741
|
+
type: "invalid_request_error"
|
|
2742
|
+
}
|
|
2743
|
+
}), {
|
|
2744
|
+
status: 400,
|
|
2745
|
+
headers: { "content-type": "application/json" }
|
|
2746
|
+
});
|
|
2747
|
+
}
|
|
2701
2748
|
const pacingCfg = resolvePacingConfig();
|
|
2702
2749
|
const getNow = this.pacingTestOverrides.now ?? Date.now;
|
|
2703
2750
|
const sleepFn = this.pacingTestOverrides.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
@@ -2740,14 +2787,24 @@ var AccountRuntimeFactory = class {
|
|
|
2740
2787
|
break;
|
|
2741
2788
|
}
|
|
2742
2789
|
const responseBody = await response.clone().text();
|
|
2743
|
-
if (!isLongContextError(responseBody)) {
|
|
2790
|
+
if (!isLongContextError(responseBody) && !isUnexpectedBetaError(responseBody)) {
|
|
2744
2791
|
break;
|
|
2745
2792
|
}
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2793
|
+
if (isUnexpectedBetaError(responseBody)) {
|
|
2794
|
+
const rejectedBetas = extractRejectedBetas(responseBody);
|
|
2795
|
+
if (rejectedBetas.length === 0) {
|
|
2796
|
+
break;
|
|
2797
|
+
}
|
|
2798
|
+
for (const rejectedBeta of rejectedBetas) {
|
|
2799
|
+
addExcludedBeta(modelId, rejectedBeta);
|
|
2800
|
+
}
|
|
2801
|
+
} else {
|
|
2802
|
+
const betaToExclude = getNextBetaToExclude(modelId);
|
|
2803
|
+
if (!betaToExclude) {
|
|
2804
|
+
break;
|
|
2805
|
+
}
|
|
2806
|
+
addExcludedBeta(modelId, betaToExclude);
|
|
2749
2807
|
}
|
|
2750
|
-
addExcludedBeta(modelId, betaToExclude);
|
|
2751
2808
|
const retryHeaders = this.buildOutboundHeaders(
|
|
2752
2809
|
incomingHeaders,
|
|
2753
2810
|
sessionId2,
|
|
@@ -2932,7 +2989,7 @@ var EMPTY_OAUTH_CREDENTIALS = {
|
|
|
2932
2989
|
if (process.env.CLAUDE_MULTI_ACCOUNT_TRACE_PLUGIN === "1") {
|
|
2933
2990
|
console.error("[anthropic-multi-account] module loaded");
|
|
2934
2991
|
}
|
|
2935
|
-
function
|
|
2992
|
+
function extractFirstUserText(input) {
|
|
2936
2993
|
try {
|
|
2937
2994
|
const raw = input;
|
|
2938
2995
|
const messages = raw.messages ?? raw.request?.messages;
|
|
@@ -3141,7 +3198,7 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
3141
3198
|
});
|
|
3142
3199
|
return {
|
|
3143
3200
|
"experimental.chat.system.transform": (input, output) => {
|
|
3144
|
-
const billingHeader = composeBillingSystemEntry(
|
|
3201
|
+
const billingHeader = composeBillingSystemEntry(extractFirstUserText(input), claudeCodeVersion);
|
|
3145
3202
|
prependMissingSystemEntries(output, [
|
|
3146
3203
|
billingHeader,
|
|
3147
3204
|
upstreamAgentIdentity,
|