UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

583 lines (582 loc) 25.7 kB
import { a as normalizeLowercaseStringOrEmpty } from "./string-coerce-mnp54Vah.js"; import { C as resolveExpiresAtMsFromDurationMs } from "./number-coercion-CJQ8TR--.js"; import { t as formatCliCommand } from "./command-format-CKGmlpAQ.js"; import { c as resolveClaudeModelIdentity, d as supportsClaudeNativeMaxEffort, f as supportsClaudeNativeXhighEffort, s as resolveClaudeFable5ModelIdentity, u as supportsClaudeAdaptiveThinking } from "./src-M7TBQdDX.js"; import { n as resolveClaudeThinkingProfile } from "./provider-claude-thinking-s2PAP2Wu.js"; import { t as parseDurationMs } from "./parse-duration-oxu_S07c.js"; import { n as listProfilesForProvider } from "./profile-list-DI8_o0Rw.js"; import { s as upsertAuthProfileWithLock } from "./profiles-BMWtmBgj.js"; import { n as suggestOAuthProfileIdForLegacyDefault } from "./repair-ELDRMhgP.js"; import "./number-runtime-DBLVDypr.js"; import "./string-coerce-runtime-CEGJWkQ_.js"; import { n as NATIVE_ANTHROPIC_REPLAY_HOOKS, u as cloneFirstTemplateModel } from "./provider-model-shared-D-lyTLvb.js"; import { n as validateAnthropicSetupToken, t as buildTokenProfileId } from "./provider-auth-token-BA6tpOZK.js"; import { t as applyAuthProfileConfig } from "./provider-auth-helpers-BgLOn-Ws.js"; import { t as createProviderApiKeyAuthMethod } from "./provider-api-key-auth-VMMQYUA9.js"; import "./provider-auth-DAOC_qI9.js"; import "./cli-runtime-DmQcvRyD.js"; import { o as fetchClaudeUsage } from "./provider-usage-CoC__69_.js"; import { n as readClaudeCliCredentialsForSetup, r as readClaudeCliCredentialsForSetupNonInteractive, t as readClaudeCliCredentialsForRuntime } from "./cli-auth-seam-DfMpf6nf.js"; import { n as CLAUDE_CLI_DEFAULT_ALLOWLIST_REFS, r as CLAUDE_CLI_DEFAULT_MODEL_REF, t as CLAUDE_CLI_BACKEND_ID } from "./cli-constants-DrUvDt2r.js"; import { n as CLAUDE_CLI_OFF_THINKING_PROFILE } from "./cli-shared-DAX1Ew1m.js"; import { t as buildAnthropicCliBackend } from "./cli-backend-B0G5gyht.js"; import { t as buildClaudeCliCatalogEntries } from "./cli-catalog-DrFnMS-C.js"; import { t as buildAnthropicCliMigrationResult } from "./cli-migration-p84FraNN.js"; import { n as normalizeAnthropicProviderConfigForProvider, t as applyAnthropicConfigDefaults } from "./config-defaults-DuXs-l2o.js"; import { t as anthropicMediaUnderstandingProvider } from "./media-understanding-provider-DHJWvYYl.js"; import { l as wrapAnthropicProviderStream } from "./stream-wrappers-fq1_93z3.js"; //#region extensions/anthropic/register.runtime.ts /** * Anthropic provider runtime registration. It owns API-key/setup-token/Claude * CLI auth, dynamic model normalization, usage auth, media, and stream wrappers. */ const PROVIDER_ID = "anthropic"; const DEFAULT_ANTHROPIC_MODEL = "anthropic/claude-opus-4-8"; const ANTHROPIC_OPUS_48_MODEL_ID = "claude-opus-4-8"; const ANTHROPIC_OPUS_48_DOT_MODEL_ID = "claude-opus-4.8"; const ANTHROPIC_OPUS_47_MODEL_ID = "claude-opus-4-7"; const ANTHROPIC_OPUS_47_DOT_MODEL_ID = "claude-opus-4.7"; const ANTHROPIC_GA_1M_CONTEXT_TOKENS = 1048576; const ANTHROPIC_FABLE_CONTEXT_TOKENS = 1e6; const ANTHROPIC_MODERN_MAX_OUTPUT_TOKENS = 128e3; const ANTHROPIC_OPUS_46_MODEL_ID = "claude-opus-4-6"; const ANTHROPIC_OPUS_46_DOT_MODEL_ID = "claude-opus-4.6"; const ANTHROPIC_OPUS_47_TEMPLATE_MODEL_IDS = [ANTHROPIC_OPUS_46_MODEL_ID, ANTHROPIC_OPUS_46_DOT_MODEL_ID]; const ANTHROPIC_SONNET_46_MODEL_ID = "claude-sonnet-4-6"; const ANTHROPIC_SONNET_46_DOT_MODEL_ID = "claude-sonnet-4.6"; const ANTHROPIC_SETUP_TOKEN_NOTE_LINES = [ "Anthropic setup-token auth is supported in OpenClaw.", "OpenClaw prefers Claude CLI reuse when it is available on the host.", "Anthropic staff told us this OpenClaw path is allowed again.", `If you want a direct API billing path instead, use ${formatCliCommand("openclaw models auth login --provider anthropic --method api-key --set-default")} or ${formatCliCommand("openclaw models auth login --provider anthropic --method cli --set-default")}.` ]; const CLAUDE_CLI_CANONICAL_ALLOWLIST_REFS = CLAUDE_CLI_DEFAULT_ALLOWLIST_REFS.map((ref) => ref.startsWith(`claude-cli/`) ? `anthropic/${ref.slice(CLAUDE_CLI_BACKEND_ID.length + 1)}` : ref); async function upsertAuthProfileWithLockOrThrow(params) { if (!await upsertAuthProfileWithLock(params)) throw new Error("Failed to update auth profile store; the auth store lock may be busy. Wait a moment and retry."); } const CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_REF = CLAUDE_CLI_DEFAULT_MODEL_REF.startsWith(`claude-cli/`) ? `anthropic/${CLAUDE_CLI_DEFAULT_MODEL_REF.slice(CLAUDE_CLI_BACKEND_ID.length + 1)}` : CLAUDE_CLI_DEFAULT_MODEL_REF; function normalizeAnthropicSetupTokenInput(value) { return value.replaceAll(/\s+/g, "").trim(); } function resolveAnthropicSetupTokenProfileId(rawProfileId) { if (typeof rawProfileId === "string") { const trimmed = rawProfileId.trim(); if (trimmed.length > 0) { if (trimmed.startsWith(`${PROVIDER_ID}:`)) return trimmed; return buildTokenProfileId({ provider: PROVIDER_ID, name: trimmed }); } } return `${PROVIDER_ID}:default`; } function resolveAnthropicSetupTokenExpiry(rawExpiresIn) { if (typeof rawExpiresIn !== "string" || rawExpiresIn.trim().length === 0) return; return resolveExpiresAtMsFromDurationMs(parseDurationMs(rawExpiresIn.trim(), { defaultUnit: "d" })); } async function runAnthropicSetupTokenAuth(ctx) { const token = (typeof ctx.opts?.token === "string" && ctx.opts.token.trim().length > 0 ? normalizeAnthropicSetupTokenInput(ctx.opts.token) : void 0) ?? normalizeAnthropicSetupTokenInput(await ctx.prompter.text({ message: "Paste Anthropic setup-token", validate: (value) => validateAnthropicSetupToken(normalizeAnthropicSetupTokenInput(value)) })); const tokenError = validateAnthropicSetupToken(token); if (tokenError) throw new Error(tokenError); const profileId = resolveAnthropicSetupTokenProfileId(ctx.opts?.tokenProfileId); const expires = resolveAnthropicSetupTokenExpiry(ctx.opts?.tokenExpiresIn); return { profiles: [{ profileId, credential: { type: "token", provider: PROVIDER_ID, token, ...expires ? { expires } : {} } }], defaultModel: DEFAULT_ANTHROPIC_MODEL, notes: [...ANTHROPIC_SETUP_TOKEN_NOTE_LINES] }; } async function runAnthropicSetupTokenNonInteractive(ctx) { const rawToken = typeof ctx.opts.token === "string" ? normalizeAnthropicSetupTokenInput(ctx.opts.token) : ""; const tokenError = validateAnthropicSetupToken(rawToken); if (tokenError) { ctx.runtime.error(["Anthropic setup-token auth requires --token with a valid setup-token.", tokenError].join("\n")); ctx.runtime.exit(1); return null; } const profileId = resolveAnthropicSetupTokenProfileId(ctx.opts.tokenProfileId); const expires = resolveAnthropicSetupTokenExpiry(ctx.opts.tokenExpiresIn); await upsertAuthProfileWithLockOrThrow({ profileId, credential: { type: "token", provider: PROVIDER_ID, token: rawToken, ...expires ? { expires } : {} }, agentDir: ctx.agentDir }); ctx.runtime.log(ANTHROPIC_SETUP_TOKEN_NOTE_LINES[0]); ctx.runtime.log(ANTHROPIC_SETUP_TOKEN_NOTE_LINES[1]); const withProfile = applyAuthProfileConfig(ctx.config, { profileId, provider: PROVIDER_ID, mode: "token" }); const existingModelConfig = withProfile.agents?.defaults?.model && typeof withProfile.agents.defaults.model === "object" ? withProfile.agents.defaults.model : {}; return { ...withProfile, agents: { ...withProfile.agents, defaults: { ...withProfile.agents?.defaults, model: { ...existingModelConfig, primary: DEFAULT_ANTHROPIC_MODEL } } } }; } function resolveAnthropic46ForwardCompatModel(params) { const trimmedModelId = params.ctx.modelId.trim(); const lower = normalizeLowercaseStringOrEmpty(trimmedModelId); if (trimmedModelId !== lower) return; if (!(lower === params.dashModelId || lower === params.dotModelId || lower.startsWith(`${params.dashModelId}-`) || lower.startsWith(`${params.dotModelId}-`))) return; const templateIds = []; if (lower.startsWith(params.dashModelId)) templateIds.push(lower.replace(params.dashModelId, params.dashTemplateId)); if (lower.startsWith(params.dotModelId)) templateIds.push(lower.replace(params.dotModelId, params.dotTemplateId)); templateIds.push(...params.fallbackTemplateIds); return cloneFirstTemplateModel({ providerId: PROVIDER_ID, modelId: trimmedModelId, templateIds, ctx: params.ctx, patch: normalizeLowercaseStringOrEmpty(params.ctx.provider) === "claude-cli" ? { provider: CLAUDE_CLI_BACKEND_ID } : void 0 }); } function buildAnthropicForwardCompatModel(ctx) { const trimmedModelId = ctx.modelId.trim(); const lower = normalizeLowercaseStringOrEmpty(trimmedModelId); const normalizedProvider = normalizeLowercaseStringOrEmpty(ctx.provider); if (trimmedModelId !== lower || !matchesAnthropicModernModel(lower)) return; if (isAnthropicFable5Model(lower) && normalizedProvider !== PROVIDER_ID) return; return { id: trimmedModelId, name: trimmedModelId, provider: normalizedProvider === "claude-cli" ? CLAUDE_CLI_BACKEND_ID : PROVIDER_ID, api: "anthropic-messages", baseUrl: "https://api.anthropic.com", reasoning: true, input: ["text", "image"], cost: isAnthropicFable5Model(trimmedModelId) ? { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 } : { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: resolveAnthropicFixedContextWindow(trimmedModelId) ?? 2e5, maxTokens: isAnthropic128kOutputModel(trimmedModelId) ? ANTHROPIC_MODERN_MAX_OUTPUT_TOKENS : 64e3, ...supportsClaudeNativeXhighEffort({ id: trimmedModelId }) ? { thinkingLevelMap: { xhigh: "xhigh", max: "max" } } : supportsAnthropicNativeMaxEffort(trimmedModelId) ? { thinkingLevelMap: { max: "max" } } : {} }; } function resolveAnthropicForwardCompatModel(ctx) { return resolveAnthropic46ForwardCompatModel({ ctx, dashModelId: ANTHROPIC_OPUS_48_MODEL_ID, dotModelId: ANTHROPIC_OPUS_48_DOT_MODEL_ID, dashTemplateId: ANTHROPIC_OPUS_47_MODEL_ID, dotTemplateId: ANTHROPIC_OPUS_47_DOT_MODEL_ID, fallbackTemplateIds: ANTHROPIC_OPUS_47_TEMPLATE_MODEL_IDS }) ?? resolveAnthropic46ForwardCompatModel({ ctx, dashModelId: ANTHROPIC_OPUS_47_MODEL_ID, dotModelId: ANTHROPIC_OPUS_47_DOT_MODEL_ID, dashTemplateId: ANTHROPIC_OPUS_46_MODEL_ID, dotTemplateId: ANTHROPIC_OPUS_46_DOT_MODEL_ID, fallbackTemplateIds: ANTHROPIC_OPUS_47_TEMPLATE_MODEL_IDS }) ?? resolveAnthropic46ForwardCompatModel({ ctx, dashModelId: ANTHROPIC_OPUS_46_MODEL_ID, dotModelId: ANTHROPIC_OPUS_46_DOT_MODEL_ID, dashTemplateId: ANTHROPIC_OPUS_47_MODEL_ID, dotTemplateId: ANTHROPIC_OPUS_46_MODEL_ID, fallbackTemplateIds: ANTHROPIC_OPUS_47_TEMPLATE_MODEL_IDS }) ?? resolveAnthropic46ForwardCompatModel({ ctx, dashModelId: ANTHROPIC_SONNET_46_MODEL_ID, dotModelId: ANTHROPIC_SONNET_46_DOT_MODEL_ID, dashTemplateId: ANTHROPIC_SONNET_46_MODEL_ID, dotTemplateId: ANTHROPIC_SONNET_46_MODEL_ID, fallbackTemplateIds: [ANTHROPIC_SONNET_46_MODEL_ID, ANTHROPIC_SONNET_46_DOT_MODEL_ID] }) ?? buildAnthropicForwardCompatModel(ctx); } function isAnthropicGa1MModel(modelId) { return supportsClaudeAdaptiveThinking({ id: modelId }); } function isAnthropicFable5Model(modelId) { return resolveClaudeFable5ModelIdentity({ id: modelId }) !== void 0; } function resolveAnthropicFixedContextWindow(modelId) { if (isAnthropicFable5Model(modelId)) return ANTHROPIC_FABLE_CONTEXT_TOKENS; return isAnthropicGa1MModel(modelId) ? ANTHROPIC_GA_1M_CONTEXT_TOKENS : void 0; } function isAnthropic128kOutputModel(modelId) { if (isAnthropicFable5Model(modelId)) return true; return /^claude-opus-4-8(?=$|[^a-z0-9])/.test(resolveClaudeModelIdentity({ id: modelId })); } function isAnthropicOpus47OrNewerModel(modelId) { return supportsClaudeNativeXhighEffort({ id: modelId }) && !isAnthropicFable5Model(modelId); } function isAnthropicMythosPreviewModel(modelId) { return /(?:^|-)claude-mythos-preview(?=$|[^a-z0-9])/.test(resolveClaudeModelIdentity({ id: modelId })); } function supportsAnthropicNativeMaxEffort(modelId) { return supportsClaudeNativeMaxEffort({ id: modelId }) || isAnthropicMythosPreviewModel(modelId); } function hasConfiguredModelContextOverride(config, provider, modelId) { const providers = config?.models?.providers; if (!providers || typeof providers !== "object") return false; const normalizedProvider = normalizeLowercaseStringOrEmpty(provider); const normalizedModelId = normalizeLowercaseStringOrEmpty(modelId); for (const [providerId, providerConfig] of Object.entries(providers)) { if (normalizeLowercaseStringOrEmpty(providerId) !== normalizedProvider) continue; if (!Array.isArray(providerConfig?.models)) continue; for (const model of providerConfig.models) { if (normalizeLowercaseStringOrEmpty(typeof model?.id === "string" ? model.id : "") !== normalizedModelId) continue; if (typeof model?.contextTokens === "number" && model.contextTokens > 0 || typeof model?.contextWindow === "number" && model.contextWindow > 0) return true; } } return false; } function applyAnthropicFixedContextWindow(params) { const fixedContextWindow = resolveAnthropicFixedContextWindow(params.contractModelId); if (fixedContextWindow === void 0) return; if (hasConfiguredModelContextOverride(params.config, params.provider, params.modelId)) return; const exactContextWindow = isAnthropicFable5Model(params.contractModelId); const nextContextWindow = exactContextWindow ? fixedContextWindow : Math.max(params.model.contextWindow ?? 0, fixedContextWindow); const nextContextTokens = exactContextWindow ? fixedContextWindow : typeof params.model.contextTokens === "number" ? Math.max(params.model.contextTokens, fixedContextWindow) : fixedContextWindow; if (nextContextWindow === params.model.contextWindow && nextContextTokens === params.model.contextTokens) return; return { ...params.model, contextWindow: nextContextWindow, contextTokens: nextContextTokens }; } function applyAnthropicModernMaxTokens(params) { if (!isAnthropic128kOutputModel(params.modelId)) return; if ((params.model.maxTokens ?? 0) >= ANTHROPIC_MODERN_MAX_OUTPUT_TOKENS) return; return { ...params.model, maxTokens: ANTHROPIC_MODERN_MAX_OUTPUT_TOKENS }; } function applyAnthropicThinkingLevelMap(params) { const fable5 = isAnthropicFable5Model(params.modelId); const nativeXhigh = fable5 || isAnthropicOpus47OrNewerModel(params.modelId); if (!supportsAnthropicNativeMaxEffort(params.modelId)) return; const current = params.model.thinkingLevelMap; const nativeDefaults = isAnthropicMythosPreviewModel(params.modelId) ? { max: "max" } : { ...fable5 ? { off: "low", minimal: "low" } : {}, xhigh: nativeXhigh ? "xhigh" : null, max: "max" }; const currentEfforts = current; if (Object.keys(nativeDefaults).every((level) => currentEfforts?.[level] !== void 0)) return; return { ...params.model, thinkingLevelMap: { ...nativeDefaults, ...current } }; } function matchesAnthropicModernModel(modelId) { return supportsClaudeAdaptiveThinking({ id: modelId }) || isAnthropicMythosPreviewModel(modelId); } function hasImageInput(input) { return Array.isArray(input) && input.includes("image"); } function supportsAnthropicImageInput(modelId, modelName) { return [modelId, modelName].filter((value) => typeof value === "string").some((candidate) => matchesAnthropicModernModel(candidate)); } function resolveAnthropicImageMediaInput(modelId, modelName) { if (!supportsAnthropicImageInput(modelId, modelName)) return; const largeImageModel = [modelId, modelName].filter((value) => typeof value === "string").some((ref) => isAnthropicFable5Model(ref) || isAnthropicOpus47OrNewerModel(ref)); return { image: { maxSidePx: largeImageModel ? 2576 : 1568, preferredSidePx: largeImageModel ? 2576 : 1568, tokenMode: "provider" } }; } function applyAnthropicImageInputCapability(params) { if (hasImageInput(params.model.input)) return; if (!supportsAnthropicImageInput(params.modelId, params.model.name)) return; return { ...params.model, input: ["text", "image"] }; } function normalizeAnthropicResolvedModel(ctx) { const contractModelId = resolveClaudeModelIdentity({ id: ctx.modelId, params: ctx.model.params }); if (isAnthropicFable5Model(contractModelId) && normalizeLowercaseStringOrEmpty(ctx.provider) !== PROVIDER_ID) return; const contractModel = isAnthropicFable5Model(contractModelId) && !ctx.model.reasoning ? { ...ctx.model, reasoning: true } : ctx.model; const imageCapableModel = applyAnthropicImageInputCapability({ modelId: contractModelId, model: contractModel }) ?? contractModel; const mediaInput = resolveAnthropicImageMediaInput(contractModelId, imageCapableModel.name); const mediaInputModel = mediaInput ? { ...imageCapableModel, mediaInput: { ...mediaInput, ...imageCapableModel.mediaInput, image: { ...mediaInput.image, ...imageCapableModel.mediaInput?.image } } } : imageCapableModel; const outputModel = applyAnthropicModernMaxTokens({ modelId: contractModelId, model: mediaInputModel }) ?? mediaInputModel; const thinkingLevelModel = applyAnthropicThinkingLevelMap({ modelId: contractModelId, model: outputModel }) ?? outputModel; const contextWindowModel = applyAnthropicFixedContextWindow({ config: ctx.config, provider: ctx.provider, modelId: ctx.modelId, contractModelId, model: thinkingLevelModel }) ?? thinkingLevelModel; return contextWindowModel === ctx.model ? void 0 : contextWindowModel; } function buildAnthropicAuthDoctorHint(params) { const legacyProfileId = params.profileId ?? "anthropic:default"; const suggested = suggestOAuthProfileIdForLegacyDefault({ cfg: params.config, store: params.store, provider: PROVIDER_ID, legacyProfileId }); if (!suggested || suggested === legacyProfileId) return ""; const storeOauthProfiles = listProfilesForProvider(params.store, PROVIDER_ID).filter((id) => params.store.profiles[id]?.type === "oauth").join(", "); const cfgMode = params.config?.auth?.profiles?.[legacyProfileId]?.mode; const cfgProvider = params.config?.auth?.profiles?.[legacyProfileId]?.provider; return [ "Doctor hint (for GitHub issue):", `- provider: ${PROVIDER_ID}`, `- config: ${legacyProfileId}${cfgProvider || cfgMode ? ` (provider=${cfgProvider ?? "?"}, mode=${cfgMode ?? "?"})` : ""}`, `- auth store oauth profiles: ${storeOauthProfiles || "(none)"}`, `- suggested profile: ${suggested}`, `Fix: run "${formatCliCommand("openclaw doctor --yes")}"` ].join("\n"); } function resolveClaudeCliSyntheticAuth() { const credential = readClaudeCliCredentialsForRuntime(); if (!credential) return; return credential.type === "oauth" ? { apiKey: credential.access, source: "Claude CLI native auth", mode: "oauth", expiresAt: credential.expires } : { apiKey: credential.token, source: "Claude CLI native auth", mode: "token", expiresAt: credential.expires }; } async function runAnthropicCliMigration(ctx) { const credential = readClaudeCliCredentialsForSetup(); if (!credential) throw new Error(["Claude CLI is not authenticated on this host.", `Run ${formatCliCommand("claude auth login")} first, then re-run this setup.`].join("\n")); return buildAnthropicCliMigrationResult(ctx.config, credential); } async function runAnthropicCliMigrationNonInteractive(ctx) { const credential = readClaudeCliCredentialsForSetupNonInteractive(); if (!credential) { ctx.runtime.error(["Auth choice \"anthropic-cli\" requires Claude CLI auth on this host.", `Run ${formatCliCommand("claude auth login")} first.`].join("\n")); ctx.runtime.exit(1); return null; } const result = buildAnthropicCliMigrationResult(ctx.config, credential); const currentDefaults = ctx.config.agents?.defaults; const currentModel = currentDefaults?.model; const currentFallbacks = currentModel && typeof currentModel === "object" && "fallbacks" in currentModel ? currentModel.fallbacks : void 0; const migratedModel = result.configPatch?.agents?.defaults?.model; const migratedFallbacks = migratedModel && typeof migratedModel === "object" && "fallbacks" in migratedModel ? migratedModel.fallbacks : void 0; const nextFallbacks = Array.isArray(migratedFallbacks) ? migratedFallbacks : currentFallbacks; return { ...ctx.config, ...result.configPatch, agents: { ...ctx.config.agents, ...result.configPatch?.agents, defaults: { ...currentDefaults, ...result.configPatch?.agents?.defaults, model: { ...Array.isArray(nextFallbacks) ? { fallbacks: nextFallbacks } : {}, primary: result.defaultModel } } } }; } async function resolveAnthropicUsageAuth(ctx) { const oauthToken = await ctx.resolveOAuthToken(); if (oauthToken) return oauthToken; const apiKey = ctx.resolveApiKeyFromConfigAndStore(); if (apiKey && validateAnthropicSetupToken(apiKey) === void 0) return { token: apiKey }; return { handled: true }; } /** Build the full Anthropic provider descriptor used by runtime registration. */ function buildAnthropicProvider() { const providerId = "anthropic"; const defaultAnthropicModel = DEFAULT_ANTHROPIC_MODEL; return { id: providerId, label: "Anthropic", docsPath: "/providers/models", hookAliases: [CLAUDE_CLI_BACKEND_ID], envVars: ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"], oauthProfileIdRepairs: [{ legacyProfileId: "anthropic:default", promptLabel: "Anthropic" }], auth: [ { id: "cli", label: "Claude CLI", hint: "Reuse a local Claude CLI login and run Anthropic models through the Claude CLI runtime", kind: "custom", wizard: { choiceId: "anthropic-cli", choiceLabel: "Anthropic Claude CLI", choiceHint: "Reuse a local Claude CLI login on this host", assistantPriority: -20, groupId: "anthropic", groupLabel: "Anthropic", groupHint: "Claude CLI + API key", modelAllowlist: { allowedKeys: [...CLAUDE_CLI_CANONICAL_ALLOWLIST_REFS], initialSelections: [CLAUDE_CLI_CANONICAL_DEFAULT_MODEL_REF], message: "Claude CLI models" } }, run: async (ctx) => await runAnthropicCliMigration(ctx), runNonInteractive: async (ctx) => await runAnthropicCliMigrationNonInteractive({ config: ctx.config, runtime: ctx.runtime, agentDir: ctx.agentDir }) }, { id: "setup-token", label: "Anthropic setup-token", hint: "Manual bearer token path", kind: "token", wizard: { choiceId: "setup-token", choiceLabel: "Anthropic setup-token", choiceHint: "Manual token path", assistantPriority: 40, groupId: "anthropic", groupLabel: "Anthropic", groupHint: "Claude CLI + API key + token" }, run: async (ctx) => await runAnthropicSetupTokenAuth(ctx), runNonInteractive: async (ctx) => await runAnthropicSetupTokenNonInteractive(ctx) }, createProviderApiKeyAuthMethod({ providerId, methodId: "api-key", label: "Anthropic API key", hint: "Direct Anthropic API key", optionKey: "anthropicApiKey", flagName: "--anthropic-api-key", envVar: "ANTHROPIC_API_KEY", promptMessage: "Enter Anthropic API key", defaultModel: defaultAnthropicModel, expectedProviders: ["anthropic"], wizard: { choiceId: "apiKey", choiceLabel: "Anthropic API key", groupId: "anthropic", groupLabel: "Anthropic", groupHint: "Claude CLI + API key" } }) ], normalizeConfig: ({ provider, providerConfig }) => normalizeAnthropicProviderConfigForProvider({ provider, providerConfig }), applyConfigDefaults: ({ config, env }) => applyAnthropicConfigDefaults({ config, env }), resolveDynamicModel: (ctx) => { const model = resolveAnthropicForwardCompatModel(ctx); if (!model) return; return normalizeAnthropicResolvedModel({ config: ctx.config, provider: ctx.provider, modelId: ctx.modelId, model }) ?? model; }, normalizeResolvedModel: (ctx) => normalizeAnthropicResolvedModel(ctx), resolveSyntheticAuth: ({ provider }) => normalizeLowercaseStringOrEmpty(provider) === "claude-cli" ? resolveClaudeCliSyntheticAuth() : void 0, augmentModelCatalog: () => buildClaudeCliCatalogEntries(), ...NATIVE_ANTHROPIC_REPLAY_HOOKS, isModernModelRef: ({ provider, modelId }) => matchesAnthropicModernModel(modelId) && (!isAnthropicFable5Model(modelId) || normalizeLowercaseStringOrEmpty(provider) === PROVIDER_ID), resolveReasoningOutputMode: () => "native", resolveThinkingProfile: ({ provider, modelId, params }) => { const contractModelId = resolveClaudeModelIdentity({ id: modelId, params }); return isAnthropicFable5Model(contractModelId) && normalizeLowercaseStringOrEmpty(provider) !== PROVIDER_ID ? CLAUDE_CLI_OFF_THINKING_PROFILE : resolveClaudeThinkingProfile(contractModelId, void 0, { includeNativeMax: [PROVIDER_ID, CLAUDE_CLI_BACKEND_ID].includes(normalizeLowercaseStringOrEmpty(provider)) }); }, wrapStreamFn: wrapAnthropicProviderStream, resolveUsageAuth: resolveAnthropicUsageAuth, fetchUsageSnapshot: async (ctx) => await fetchClaudeUsage(ctx.token, ctx.timeoutMs, ctx.fetchFn), isCacheTtlEligible: () => true, buildAuthDoctorHint: (ctx) => buildAnthropicAuthDoctorHint({ config: ctx.config, store: ctx.store, profileId: ctx.profileId }) }; } /** Register Anthropic provider, Claude CLI backend, and media understanding provider. */ function registerAnthropicPlugin(api) { api.registerCliBackend(buildAnthropicCliBackend()); api.registerProvider(buildAnthropicProvider()); api.registerMediaUnderstandingProvider(anthropicMediaUnderstandingProvider); } //#endregion export { registerAnthropicPlugin as n, buildAnthropicProvider as t };