opencode-anthropic-multi-account 0.2.21 → 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/chunk-2SN3UVSM.js +2439 -0
- package/dist/chunk-2SN3UVSM.js.map +1 -0
- package/dist/{chunk-IETVH43F.js → chunk-RAX4SFCO.js} +14 -2
- package/dist/chunk-RAX4SFCO.js.map +1 -0
- package/dist/fingerprint-capture.d.ts +3 -2
- package/dist/fingerprint-capture.js +4 -2
- package/dist/index.js +210 -63
- package/dist/index.js.map +1 -1
- package/dist/scrub-template.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-IETVH43F.js.map +0 -1
- package/dist/chunk-RVXWLAVK.js +0 -1130
- package/dist/chunk-RVXWLAVK.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -25,8 +25,8 @@ import {
|
|
|
25
25
|
showToast,
|
|
26
26
|
sleep,
|
|
27
27
|
updateConfigField
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-2SN3UVSM.js";
|
|
29
|
+
import "./chunk-RAX4SFCO.js";
|
|
30
30
|
|
|
31
31
|
// src/index.ts
|
|
32
32
|
import { tool } from "@opencode-ai/plugin";
|
|
@@ -719,7 +719,7 @@ function buildCascadePrompt(input, init) {
|
|
|
719
719
|
}
|
|
720
720
|
function createQueueAwareManager(manager, queue, cascadeStateManager) {
|
|
721
721
|
return Object.create(manager, {
|
|
722
|
-
selectAccount: { value: async function selectAccount() {
|
|
722
|
+
selectAccount: { value: async function selectAccount(stickyKey) {
|
|
723
723
|
await manager.refresh();
|
|
724
724
|
while (queue.length > 0) {
|
|
725
725
|
const next = queue.shift();
|
|
@@ -734,7 +734,7 @@ function createQueueAwareManager(manager, queue, cascadeStateManager) {
|
|
|
734
734
|
}
|
|
735
735
|
return account;
|
|
736
736
|
}
|
|
737
|
-
return manager.selectAccount();
|
|
737
|
+
return manager.selectAccount(stickyKey);
|
|
738
738
|
} }
|
|
739
739
|
});
|
|
740
740
|
}
|
|
@@ -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;
|
|
@@ -1758,12 +1805,7 @@ var ADAPTIVE_THINKING_MODEL_MATCHERS = [
|
|
|
1758
1805
|
(modelId) => modelId.includes("claude-opus-4-6") || modelId.includes("claude-opus-4.6"),
|
|
1759
1806
|
(modelId) => /claude-opus-4[-._]([7-9]|\d{2,})/.test(modelId)
|
|
1760
1807
|
];
|
|
1761
|
-
var LARGE_OUTPUT_MODEL_MATCHERS = [
|
|
1762
|
-
(modelId) => modelId.includes("claude-opus-4-6") || modelId.includes("claude-opus-4.6"),
|
|
1763
|
-
(modelId) => /claude-opus-4[-._]([7-9]|\d{2,})/.test(modelId)
|
|
1764
|
-
];
|
|
1765
1808
|
var DEFAULT_MAX_OUTPUT_TOKENS = 64e3;
|
|
1766
|
-
var LARGE_MODEL_MAX_OUTPUT_TOKENS = 128e3;
|
|
1767
1809
|
function normalizeModelId2(modelId) {
|
|
1768
1810
|
return modelId.trim().toLowerCase();
|
|
1769
1811
|
}
|
|
@@ -1778,16 +1820,11 @@ function supportsAdaptiveThinking(modelId) {
|
|
|
1778
1820
|
}
|
|
1779
1821
|
return ADAPTIVE_THINKING_MODEL_MATCHERS.some((matches) => matches(normalized));
|
|
1780
1822
|
}
|
|
1781
|
-
function getModelMaxOutputTokens(
|
|
1782
|
-
|
|
1783
|
-
if (typeof runtimeCapability?.maxOutputTokens === "number") {
|
|
1784
|
-
return runtimeCapability.maxOutputTokens;
|
|
1785
|
-
}
|
|
1786
|
-
const normalized = normalizeModelId2(modelId);
|
|
1787
|
-
return LARGE_OUTPUT_MODEL_MATCHERS.some((matches) => matches(normalized)) ? LARGE_MODEL_MAX_OUTPUT_TOKENS : DEFAULT_MAX_OUTPUT_TOKENS;
|
|
1823
|
+
function getModelMaxOutputTokens() {
|
|
1824
|
+
return DEFAULT_MAX_OUTPUT_TOKENS;
|
|
1788
1825
|
}
|
|
1789
|
-
function resolveMaxTokens(
|
|
1790
|
-
const modelCap = getModelMaxOutputTokens(
|
|
1826
|
+
function resolveMaxTokens(requestedMaxTokens) {
|
|
1827
|
+
const modelCap = getModelMaxOutputTokens();
|
|
1791
1828
|
if (typeof requestedMaxTokens !== "number" || !Number.isFinite(requestedMaxTokens)) {
|
|
1792
1829
|
return modelCap;
|
|
1793
1830
|
}
|
|
@@ -2036,7 +2073,7 @@ function buildUpstreamRequest(inputBody, identity, template, options) {
|
|
|
2036
2073
|
body.context_management = DEFAULT_CONTEXT_MANAGEMENT;
|
|
2037
2074
|
body.output_config = DEFAULT_OUTPUT_CONFIG;
|
|
2038
2075
|
}
|
|
2039
|
-
body.max_tokens = resolveMaxTokens(
|
|
2076
|
+
body.max_tokens = resolveMaxTokens(body.max_tokens);
|
|
2040
2077
|
return orderBodyForOutbound(body, template.body_field_order);
|
|
2041
2078
|
}
|
|
2042
2079
|
function orderBodyForOutbound(body, overrideOrder) {
|
|
@@ -2122,25 +2159,8 @@ function shouldMaskToolName(name, claudeToolNames) {
|
|
|
2122
2159
|
}
|
|
2123
2160
|
return !claudeToolNames.has(name) && !name.startsWith("mcp__") && !name.startsWith(TOOL_MASK_PREFIX);
|
|
2124
2161
|
}
|
|
2125
|
-
function
|
|
2126
|
-
|
|
2127
|
-
return "";
|
|
2128
|
-
}
|
|
2129
|
-
const firstUser = parsed.messages.find((message) => message.role === "user");
|
|
2130
|
-
if (!isRecord3(firstUser)) {
|
|
2131
|
-
return "";
|
|
2132
|
-
}
|
|
2133
|
-
const content = firstUser.content;
|
|
2134
|
-
if (typeof content === "string") {
|
|
2135
|
-
return content.trim();
|
|
2136
|
-
}
|
|
2137
|
-
if (!Array.isArray(content)) {
|
|
2138
|
-
return "";
|
|
2139
|
-
}
|
|
2140
|
-
return content.filter((block) => isRecord3(block) && block.type === "text" && typeof block.text === "string").map((block) => String(block.text)).join("\n\n").trim();
|
|
2141
|
-
}
|
|
2142
|
-
function buildMaskedToolName(seed, toolName, length = 8) {
|
|
2143
|
-
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);
|
|
2144
2164
|
return `${TOOL_MASK_PREFIX}${digest}`;
|
|
2145
2165
|
}
|
|
2146
2166
|
function collectToolNames(parsed) {
|
|
@@ -2175,7 +2195,6 @@ function buildClaudeToolNameSet(claudeToolNames) {
|
|
|
2175
2195
|
function buildRequestScopedToolLookup(parsed, claudeToolNames) {
|
|
2176
2196
|
const lookup = /* @__PURE__ */ new Map();
|
|
2177
2197
|
const usedOutgoing = /* @__PURE__ */ new Set();
|
|
2178
|
-
const seed = extractFirstUserText(parsed);
|
|
2179
2198
|
const claudeToolSet = buildClaudeToolNameSet(claudeToolNames);
|
|
2180
2199
|
for (const originalName of collectToolNames(parsed)) {
|
|
2181
2200
|
if (!shouldMaskToolName(originalName, claudeToolSet)) {
|
|
@@ -2184,10 +2203,10 @@ function buildRequestScopedToolLookup(parsed, claudeToolNames) {
|
|
|
2184
2203
|
continue;
|
|
2185
2204
|
}
|
|
2186
2205
|
let length = 8;
|
|
2187
|
-
let masked = buildMaskedToolName(
|
|
2206
|
+
let masked = buildMaskedToolName(originalName, length);
|
|
2188
2207
|
while (usedOutgoing.has(masked)) {
|
|
2189
2208
|
length += 2;
|
|
2190
|
-
masked = buildMaskedToolName(
|
|
2209
|
+
masked = buildMaskedToolName(originalName, length);
|
|
2191
2210
|
}
|
|
2192
2211
|
lookup.set(masked, originalName);
|
|
2193
2212
|
usedOutgoing.add(masked);
|
|
@@ -2552,7 +2571,7 @@ function transformBodyToUpstream(body, identity, sessionId2) {
|
|
|
2552
2571
|
try {
|
|
2553
2572
|
const parsed = JSON.parse(body);
|
|
2554
2573
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
2555
|
-
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2574
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map(), validationError: null };
|
|
2556
2575
|
}
|
|
2557
2576
|
const template = loadTemplate();
|
|
2558
2577
|
const upstreamRequest = buildUpstreamRequest(
|
|
@@ -2561,9 +2580,16 @@ function transformBodyToUpstream(body, identity, sessionId2) {
|
|
|
2561
2580
|
template,
|
|
2562
2581
|
{ sessionId: sessionId2 }
|
|
2563
2582
|
);
|
|
2564
|
-
|
|
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
|
+
};
|
|
2565
2591
|
} catch {
|
|
2566
|
-
return { body, reverseLookup: /* @__PURE__ */ new Map() };
|
|
2592
|
+
return { body, reverseLookup: /* @__PURE__ */ new Map(), validationError: null };
|
|
2567
2593
|
}
|
|
2568
2594
|
}
|
|
2569
2595
|
async function applyResponseReverseLookup(response, reverseLookup) {
|
|
@@ -2675,11 +2701,11 @@ var AccountRuntimeFactory = class {
|
|
|
2675
2701
|
return { accessToken: refreshed.patch.accessToken, expiresAt: refreshed.patch.expiresAt };
|
|
2676
2702
|
}
|
|
2677
2703
|
buildOutboundHeaders(incomingHeaders, sessionId2, accessToken, modelId, excludedBetas2) {
|
|
2678
|
-
const mergedBetas = deduplicateBetas([
|
|
2704
|
+
const mergedBetas = deduplicateBetas(ensureOauthBeta([
|
|
2679
2705
|
...excludeBetas(splitBetaValues(getBetaHeader()), excludedBetas2),
|
|
2680
2706
|
...getModelBetas(modelId, excludedBetas2),
|
|
2681
2707
|
...excludeBetas(splitBetaValues(incomingHeaders["anthropic-beta"]), excludedBetas2)
|
|
2682
|
-
]).join(",");
|
|
2708
|
+
])).join(",");
|
|
2683
2709
|
const outbound = {
|
|
2684
2710
|
...incomingHeaders,
|
|
2685
2711
|
...getStaticHeaders(),
|
|
@@ -2707,7 +2733,18 @@ var AccountRuntimeFactory = class {
|
|
|
2707
2733
|
void recordObservedToolNames(extractToolNamesFromRequestBody(init.body)).catch(() => {
|
|
2708
2734
|
});
|
|
2709
2735
|
}
|
|
2710
|
-
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
|
+
}
|
|
2711
2748
|
const pacingCfg = resolvePacingConfig();
|
|
2712
2749
|
const getNow = this.pacingTestOverrides.now ?? Date.now;
|
|
2713
2750
|
const sleepFn = this.pacingTestOverrides.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
@@ -2750,14 +2787,24 @@ var AccountRuntimeFactory = class {
|
|
|
2750
2787
|
break;
|
|
2751
2788
|
}
|
|
2752
2789
|
const responseBody = await response.clone().text();
|
|
2753
|
-
if (!isLongContextError(responseBody)) {
|
|
2790
|
+
if (!isLongContextError(responseBody) && !isUnexpectedBetaError(responseBody)) {
|
|
2754
2791
|
break;
|
|
2755
2792
|
}
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
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);
|
|
2759
2807
|
}
|
|
2760
|
-
addExcludedBeta(modelId, betaToExclude);
|
|
2761
2808
|
const retryHeaders = this.buildOutboundHeaders(
|
|
2762
2809
|
incomingHeaders,
|
|
2763
2810
|
sessionId2,
|
|
@@ -2939,7 +2986,10 @@ var EMPTY_OAUTH_CREDENTIALS = {
|
|
|
2939
2986
|
access: "",
|
|
2940
2987
|
expires: 0
|
|
2941
2988
|
};
|
|
2942
|
-
|
|
2989
|
+
if (process.env.CLAUDE_MULTI_ACCOUNT_TRACE_PLUGIN === "1") {
|
|
2990
|
+
console.error("[anthropic-multi-account] module loaded");
|
|
2991
|
+
}
|
|
2992
|
+
function extractFirstUserText(input) {
|
|
2943
2993
|
try {
|
|
2944
2994
|
const raw = input;
|
|
2945
2995
|
const messages = raw.messages ?? raw.request?.messages;
|
|
@@ -2974,6 +3024,9 @@ function applyOrderedHeaders(output, headers) {
|
|
|
2974
3024
|
output.headers = Array.isArray(orderedHeaders) ? Object.fromEntries(orderedHeaders) : orderedHeaders;
|
|
2975
3025
|
}
|
|
2976
3026
|
var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
3027
|
+
if (process.env.CLAUDE_MULTI_ACCOUNT_TRACE_PLUGIN === "1") {
|
|
3028
|
+
console.error("[anthropic-multi-account] plugin function called");
|
|
3029
|
+
}
|
|
2977
3030
|
const { client } = ctx;
|
|
2978
3031
|
await loadConfig();
|
|
2979
3032
|
const requestProfile = loadCCDerivedRequestProfile();
|
|
@@ -3070,7 +3123,20 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
3070
3123
|
});
|
|
3071
3124
|
});
|
|
3072
3125
|
const store = new AccountStore();
|
|
3073
|
-
await syncBootstrapAuth(client, store).
|
|
3126
|
+
await syncBootstrapAuth(client, store).then((synced) => {
|
|
3127
|
+
debugLog(client, "Bootstrap auth sync completed", { synced });
|
|
3128
|
+
}).catch((error) => {
|
|
3129
|
+
client.app.log({
|
|
3130
|
+
body: {
|
|
3131
|
+
service: ANTHROPIC_OAUTH_ADAPTER.serviceLogName,
|
|
3132
|
+
level: "debug",
|
|
3133
|
+
message: "bootstrap auth sync failed",
|
|
3134
|
+
extra: {
|
|
3135
|
+
error: sanitizeError(error)
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}).catch(() => {
|
|
3139
|
+
});
|
|
3074
3140
|
});
|
|
3075
3141
|
let manager = null;
|
|
3076
3142
|
let runtimeFactory = null;
|
|
@@ -3132,7 +3198,7 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
3132
3198
|
});
|
|
3133
3199
|
return {
|
|
3134
3200
|
"experimental.chat.system.transform": (input, output) => {
|
|
3135
|
-
const billingHeader = composeBillingSystemEntry(
|
|
3201
|
+
const billingHeader = composeBillingSystemEntry(extractFirstUserText(input), claudeCodeVersion);
|
|
3136
3202
|
prependMissingSystemEntries(output, [
|
|
3137
3203
|
billingHeader,
|
|
3138
3204
|
upstreamAgentIdentity,
|
|
@@ -3207,13 +3273,90 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
3207
3273
|
{ type: "api", label: "Manually enter API Key" }
|
|
3208
3274
|
],
|
|
3209
3275
|
async loader(getAuth, provider) {
|
|
3210
|
-
|
|
3276
|
+
const providerModels = provider.models ?? {};
|
|
3277
|
+
ingestProviderModelsCapabilities(providerModels);
|
|
3278
|
+
debugLog(client, "Auth loader received provider metadata", {
|
|
3279
|
+
providerId: typeof provider.id === "string" ? provider.id : void 0,
|
|
3280
|
+
providerName: typeof provider.name === "string" ? provider.name : void 0,
|
|
3281
|
+
modelCount: Object.keys(providerModels).length,
|
|
3282
|
+
modelIds: Object.keys(providerModels)
|
|
3283
|
+
});
|
|
3211
3284
|
const auth = await getAuth();
|
|
3285
|
+
debugLog(client, "Auth loader resolved auth payload", {
|
|
3286
|
+
authType: typeof auth.type === "string" ? auth.type : void 0,
|
|
3287
|
+
authKeys: Object.keys(auth)
|
|
3288
|
+
});
|
|
3212
3289
|
if (auth.type !== "oauth") {
|
|
3213
|
-
|
|
3214
|
-
|
|
3290
|
+
await syncBootstrapAuth(client, store).then((synced) => {
|
|
3291
|
+
debugLog(client, "Auth loader requested bootstrap auth sync", { synced });
|
|
3292
|
+
}).catch((error) => {
|
|
3293
|
+
client.app.log({
|
|
3294
|
+
body: {
|
|
3295
|
+
service: ANTHROPIC_OAUTH_ADAPTER.serviceLogName,
|
|
3296
|
+
level: "debug",
|
|
3297
|
+
message: "auth loader bootstrap sync failed",
|
|
3298
|
+
extra: {
|
|
3299
|
+
error: sanitizeError(error)
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
}).catch(() => {
|
|
3303
|
+
});
|
|
3304
|
+
});
|
|
3305
|
+
const recoveredFromStore = await initializeManagerFromStore();
|
|
3306
|
+
debugLog(client, "Auth loader attempted store recovery", {
|
|
3307
|
+
recoveredFromStore
|
|
3308
|
+
});
|
|
3309
|
+
if (!recoveredFromStore || !manager || !runtimeFactory) {
|
|
3310
|
+
stopHeartbeat();
|
|
3311
|
+
return { apiKey: "", fetch };
|
|
3312
|
+
}
|
|
3313
|
+
const authProfile2 = await loadCCDerivedAuthProfile();
|
|
3314
|
+
return {
|
|
3315
|
+
apiKey: "",
|
|
3316
|
+
baseURL: authProfile2.apiV1BaseUrl,
|
|
3317
|
+
"chat.headers": async (input, output) => {
|
|
3318
|
+
if (input.provider?.info?.id !== ANTHROPIC_OAUTH_ADAPTER.authProviderId) return;
|
|
3319
|
+
const sessionId2 = getUpstreamSessionId();
|
|
3320
|
+
applyOrderedHeaders(output, {
|
|
3321
|
+
...output.headers,
|
|
3322
|
+
...getStaticHeaders(),
|
|
3323
|
+
...getPerRequestHeaders(sessionId2),
|
|
3324
|
+
"anthropic-beta": getBetaHeader()
|
|
3325
|
+
});
|
|
3326
|
+
},
|
|
3327
|
+
async fetch(input, init) {
|
|
3328
|
+
if (!manager || !runtimeFactory) {
|
|
3329
|
+
stopHeartbeat();
|
|
3330
|
+
return fetch(input, init);
|
|
3331
|
+
}
|
|
3332
|
+
if (manager.getAccountCount() === 0) {
|
|
3333
|
+
stopHeartbeat();
|
|
3334
|
+
throw new Error(
|
|
3335
|
+
"No Anthropic accounts configured. Run `opencode auth login` to add an account."
|
|
3336
|
+
);
|
|
3337
|
+
}
|
|
3338
|
+
ensureHeartbeat(manager.getActiveAccount()?.accessToken);
|
|
3339
|
+
if (!poolManager || !cascadeStateManager) {
|
|
3340
|
+
poolManager = new PoolManager();
|
|
3341
|
+
poolManager.loadPools(poolChainConfig.pools);
|
|
3342
|
+
cascadeStateManager = new CascadeStateManager();
|
|
3343
|
+
}
|
|
3344
|
+
return executeWithAccountRotation(
|
|
3345
|
+
manager,
|
|
3346
|
+
runtimeFactory,
|
|
3347
|
+
client,
|
|
3348
|
+
input,
|
|
3349
|
+
init,
|
|
3350
|
+
{
|
|
3351
|
+
poolManager,
|
|
3352
|
+
cascadeStateManager,
|
|
3353
|
+
poolChainConfig
|
|
3354
|
+
}
|
|
3355
|
+
);
|
|
3356
|
+
}
|
|
3357
|
+
};
|
|
3215
3358
|
}
|
|
3216
|
-
for (const model of Object.values(
|
|
3359
|
+
for (const model of Object.values(providerModels)) {
|
|
3217
3360
|
if (model) {
|
|
3218
3361
|
model.cost = { input: 0, output: 0, cache: { read: 0, write: 0 } };
|
|
3219
3362
|
}
|
|
@@ -3226,6 +3369,10 @@ var ClaudeMultiAuthPlugin = async (ctx) => {
|
|
|
3226
3369
|
if (!initializedManager) {
|
|
3227
3370
|
return { apiKey: "", fetch };
|
|
3228
3371
|
}
|
|
3372
|
+
debugLog(client, "Auth loader initialized manager state", {
|
|
3373
|
+
accountCount: initializedManager.getAccountCount(),
|
|
3374
|
+
activeAccountUuid: initializedManager.getActiveAccount()?.uuid
|
|
3375
|
+
});
|
|
3229
3376
|
if (initializedManager.getAccountCount() > 0) {
|
|
3230
3377
|
const activeAccount = initializedManager.getActiveAccount();
|
|
3231
3378
|
const activeLabel = activeAccount ? getAccountLabel(activeAccount) : "none";
|