@iaforged/context-code 2.2.7 → 2.2.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.
@@ -1 +1 @@
1
- import{MACRO as e}from"../recovery/bunBundleShim.js";import r from"chalk";import{exec as t}from"child_process";import{execa as n}from"execa";import{mkdir as o,stat as s}from"fs/promises";import i from"lodash-es/memoize.js";import{CLAUDE_AI_PROFILE_SCOPE as c}from"../constants/oauth.js";import{logEvent as a}from"../services/analytics/index.js";import{GEMINI_CLI_OAUTH_CLIENT_ID as u,GEMINI_CLI_OAUTH_CLIENT_SECRET as p,GEMINI_CLI_OAUTH_SCOPES as l,GEMINI_CLI_OAUTH_TOKEN_URL as A}from"../constants/geminiOAuth.js";import{getModelStrings as d}from"./model/modelStrings.js";import{getAPIProvider as f,isOpenAICompatibleProvider as h}from"./model/providers.js";import{getResolvedProviderProfileId as _,ensureProviderProfile as g,isDefaultProfileId as O,isProfiledProvider as T,resolveProviderProfile as E}from"./model/providerProfiles.js";import{getIsNonInteractiveSession as m,preferThirdPartyAuthentication as y}from"../bootstrap/state.js";import{getMockSubscriptionType as k,shouldUseMockSubscription as C}from"../services/mockRateLimits.js";import{isOAuthTokenExpired as v,refreshOpenAIOAuthToken as I,refreshOAuthToken as K,shouldUseClaudeAIAuth as S}from"../services/oauth/client.js";import{getOauthProfileFromOauthToken as x}from"../services/oauth/getOauthProfile.js";import{getApiKeyFromFileDescriptor as w,getOAuthTokenFromFileDescriptor as P}from"./authFileDescriptor.js";import{maybeRemoveApiKeyFromMacOSKeychainThrows as N,normalizeApiKeyForConfig as R}from"./authPortable.js";import{checkStsCallerIdentity as D,clearAwsIniCache as H,isValidAwsStsOutput as U}from"./aws.js";import{AwsAuthStatusManager as b}from"./awsAuthStatusManager.js";import{clearBetasCaches as L}from"./betas.js";import{checkHasTrustDialogAccepted as G,getGlobalConfig as j,saveGlobalConfig as F}from"./config.js";import{logAntError as M,logForDebugging as $}from"./debug.js";import{getClaudeConfigHomeDir as Y,isBareMode as B,isEnvTruthy as X,isRunningOnHomespace as W}from"./envUtils.js";import{errorMessage as z}from"./errors.js";import{execSyncWithDefaults_DEPRECATED as q}from"./execFileNoThrow.js";import*as V from"./lockfile.js";import{logError as J}from"./log.js";import{memoizeWithTTLAsync as Z}from"./memoize.js";import{getSecureStorage as Q}from"./secureStorage/index.js";import{clearLegacyApiKeyPrefetch as ee,getLegacyApiKeyPrefetchResult as re}from"./secureStorage/keychainPrefetch.js";import{clearKeychainCache as te,getMacOsKeychainStorageServiceName as ne,getUsername as oe}from"./secureStorage/macOsKeychainHelpers.js";import{getLegacyCredentialsFilePath as se,getSecureStorageDbPath as ie}from"./secureStorage/sqliteStorage.js";import{getSettings_DEPRECATED as ce,getSettingsForSource as ae}from"./settings/settings.js";import{sleep as ue}from"./sleep.js";import{jsonParse as pe}from"./slowOperations.js";import{clearToolSchemaCache as le}from"./toolSchemaCache.js";function isManagedOAuthContext(){return X(process.env.CONTEXT_CODE_REMOTE)||X(process.env.CLAUDE_CODE_REMOTE)||"claude-desktop"===process.env.CLAUDE_CODE_ENTRYPOINT}export function isAnthropicAuthEnabled(){if(B())return!1;if(process.env.ANTHROPIC_UNIX_SOCKET)return!(!process.env.CONTEXT_CODE_OAUTH_TOKEN&&!process.env.CLAUDE_CODE_OAUTH_TOKEN);const e=f(),r=X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(e),t=(ce()||{}).apiKeyHelper,n=process.env.ANTHROPIC_AUTH_TOKEN||t||process.env.CONTEXT_CODE_API_KEY_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR,{source:o}=getAnthropicApiKeyWithSource({skipRetrievingKeyFromApiKeyHelper:!0}),s="ANTHROPIC_API_KEY"===o||"apiKeyHelper"===o;return!(r||n&&!isManagedOAuthContext()||s&&!isManagedOAuthContext())}export function getAuthTokenSource(){const e=f();if(h(e))return{source:e,hasToken:Boolean(getOpenAICompatibleAccessToken(e))};if(B())return getConfiguredApiKeyHelper()?{source:"apiKeyHelper",hasToken:!0}:{source:"none",hasToken:!1};if(process.env.ANTHROPIC_AUTH_TOKEN&&!isManagedOAuthContext())return{source:"ANTHROPIC_AUTH_TOKEN",hasToken:!0};if(isManagedOAuthContext()&&(process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN))return{source:"CLAUDE_CODE_OAUTH_TOKEN",hasToken:!0};if(isManagedOAuthContext()?P():null)return process.env.CONTEXT_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR?{source:"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR",hasToken:!0}:{source:"CCR_OAUTH_TOKEN_FILE",hasToken:!0};if(getConfiguredApiKeyHelper()&&!isManagedOAuthContext())return{source:"apiKeyHelper",hasToken:!0};const r=getClaudeAIOAuthTokens();return S(r?.scopes)&&r?.accessToken?{source:"claude.ai",hasToken:!0}:{source:"none",hasToken:!1}}function getProviderOauthStorageKey(e){return"claude"===e?"claudeAiOauth":"openAiOauth"}function shouldUseLegacyProviderOauthFallback(e){return"claude"!==e}export function getStoredProviderOAuthTokens(e,r){try{const t=Q().read();if(r){const n=t?.providerProfileOauth?.[r];if(n?.accessToken)return n;if(!O(e,r))return null}if("gemini-google"===e)return null;if(!shouldUseLegacyProviderOauthFallback(e))return null;const n=t?.[getProviderOauthStorageKey(e)];return n?.accessToken?n:null}catch{return null}}export function hasStoredProviderOAuthTokens(e,r){if(r)return Boolean(getStoredProviderOAuthTokens(e,r));try{const r=Q().read(),t=Object.entries(r?.providerProfileOauth??{}).some(([r,t])=>r.startsWith(`${e}/`)&&"object"==typeof t&&null!==t&&"string"==typeof t.accessToken&&t.accessToken.trim());return shouldUseLegacyProviderOauthFallback(e)?Boolean(t||r?.[getProviderOauthStorageKey(e)]?.accessToken):Boolean(t)}catch{return!1}}export async function renameProviderScopedCredentials(e,r){if(!e||!r||e===r)return;const t=Q(),n=t.read()||{},o={...n.providerProfileApiKeys??{}},s={...n.providerProfileOauth??{}};e in o&&(o[r]=o[e],delete o[e]),e in s&&(s[r]=s[e],delete s[e]);if(!t.update({...n,providerProfileApiKeys:o,providerProfileOauth:s}).success)throw new Error("No se pudieron mover las credenciales del perfil.")}export async function removeProviderScopedCredentials(e){if(!e)return;const r=Q(),t=r.read()||{},n={...t.providerProfileApiKeys??{}},o={...t.providerProfileOauth??{}};delete n[e],delete o[e];if(!r.update({...t,providerProfileApiKeys:n,providerProfileOauth:o}).success)throw new Error("No se pudieron eliminar las credenciales del perfil.")}export async function removeAllProviderScopedCredentials(){const e=Q(),r=e.read()||{};if(!e.update({...r,providerProfileApiKeys:{},providerProfileOauth:{}}).success)throw new Error("No se pudieron eliminar las credenciales scoped de perfiles.")}export function getAnthropicApiKey(){const{key:e}=getAnthropicApiKeyWithSource();return e}export function hasAnthropicApiKeyAuth(){const{key:e,source:r}=getAnthropicApiKeyWithSource({skipRetrievingKeyFromApiKeyHelper:!0});return null!==e&&"none"!==r}export function getAnthropicApiKeyWithSource(e={}){if(h(f()))return{key:null,source:"none"};if(B())return process.env.ANTHROPIC_API_KEY?{key:process.env.ANTHROPIC_API_KEY,source:"ANTHROPIC_API_KEY"}:getConfiguredApiKeyHelper()?{key:e.skipRetrievingKeyFromApiKeyHelper?null:getApiKeyFromApiKeyHelperCached(),source:"apiKeyHelper"}:{key:null,source:"none"};const r=W()?void 0:process.env.ANTHROPIC_API_KEY;if(y()&&r)return{key:r,source:"ANTHROPIC_API_KEY"};if(X(process.env.CI)||"test"===process.env.NODE_ENV){const e=w();if(e)return{key:e,source:"ANTHROPIC_API_KEY"};if(!(r||process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CONTEXT_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR))throw new Error("ANTHROPIC_API_KEY or CONTEXT_CODE_OAUTH_TOKEN (legacy: CLAUDE_CODE_OAUTH_TOKEN) env var is required");return r?{key:r,source:"ANTHROPIC_API_KEY"}:{key:null,source:"none"}}if(r&&j().customApiKeyResponses?.approved?.includes(R(r)))return{key:r,source:"ANTHROPIC_API_KEY"};const t=w();if(t)return{key:t,source:"ANTHROPIC_API_KEY"};if(getConfiguredApiKeyHelper())return e.skipRetrievingKeyFromApiKeyHelper?{key:null,source:"apiKeyHelper"}:{key:getApiKeyFromApiKeyHelperCached(),source:"apiKeyHelper"};const n=getApiKeyFromConfigOrMacOSKeychain();return n||{key:null,source:"none"}}export function getConfiguredApiKeyHelper(){if(B())return ae("flagSettings")?.apiKeyHelper;return(ce()||{}).apiKeyHelper}function isApiKeyHelperFromProjectOrLocalSettings(){const e=getConfiguredApiKeyHelper();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.apiKeyHelper===e||t?.apiKeyHelper===e}function getConfiguredAwsAuthRefresh(){return(ce()||{}).awsAuthRefresh}export function isAwsAuthRefreshFromProjectSettings(){const e=getConfiguredAwsAuthRefresh();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.awsAuthRefresh===e||t?.awsAuthRefresh===e}function getConfiguredAwsCredentialExport(){return(ce()||{}).awsCredentialExport}export function isAwsCredentialExportFromProjectSettings(){const e=getConfiguredAwsCredentialExport();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.awsCredentialExport===e||t?.awsCredentialExport===e}export function calculateApiKeyHelperTTL(){const e=process.env.CONTEXT_CODE_API_KEY_HELPER_TTL_MS??process.env.CLAUDE_CODE_API_KEY_HELPER_TTL_MS;if(e){const r=parseInt(e,10);if(!Number.isNaN(r)&&r>=0)return r;$(`Found CLAUDE_CODE_API_KEY_HELPER_TTL_MS env var, but it was not a valid number. Got ${e}`,{level:"error"})}return 3e5}let Ae=null,de=null,fe=0;export function getApiKeyHelperElapsedMs(){const e=de?.startedAt;return e?Date.now()-e:0}export async function getApiKeyFromApiKeyHelper(e){if(!getConfiguredApiKeyHelper())return null;const r=calculateApiKeyHelperTTL();return Ae?(Date.now()-Ae.timestamp<r||de||(de={promise:_runAndCache(e,!1,fe),startedAt:null}),Ae.value):(de||(de={promise:_runAndCache(e,!0,fe),startedAt:Date.now()}),de.promise)}async function _runAndCache(t,o,s){try{const r=await async function(r){const t=getConfiguredApiKeyHelper();if(!t)return null;if(isApiKeyHelperFromProjectOrLocalSettings()){if(!G()&&!r){const r=new Error(`Security: apiKeyHelper executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("apiKeyHelper invoked before trust check",r),a("tengu_apiKeyHelper_missing_trust11",{}),null}}const o=await n(t,{shell:!0,timeout:6e5,reject:!1});if(o.failed){const e=o.timedOut?"timed out":`exited ${o.exitCode}`,r=o.stderr?.trim();throw new Error(r?`${e}: ${r}`:e)}const s=o.stdout?.trim();if(!s)throw new Error("did not return a value");return s}(t);return s!==fe||null!==r&&(Ae={value:r,timestamp:Date.now()}),r}catch(e){if(s!==fe)return" ";const t=e instanceof Error?e.message:String(e);return console.error(r.red(`apiKeyHelper failed: ${t}`)),$(`Error getting API key from apiKeyHelper: ${t}`,{level:"error"}),!o&&Ae&&" "!==Ae.value?(Ae={...Ae,timestamp:Date.now()},Ae.value):(Ae={value:" ",timestamp:Date.now()}," ")}finally{s===fe&&(de=null)}}export function getApiKeyFromApiKeyHelperCached(){return Ae?.value??null}export function clearApiKeyHelperCache(){fe++,Ae=null,de=null}export function prefetchApiKeyFromApiKeyHelperIfSafe(e){isApiKeyHelperFromProjectOrLocalSettings()&&!G()||getApiKeyFromApiKeyHelper(e)}const he=18e4;export function refreshAwsAuth(e){$("Running AWS auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:he});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),$(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),$(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)$("AWS auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===t?r.red("AWS auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):r.red("Error running awsAuthRefresh (in settings or ~/.context.json):");console.error(e),n.endAuthentication(!1),o(!1)}})})}export const refreshAndGetAwsCredentials=Z(async()=>{const t=await async function(){const r=getConfiguredAwsAuthRefresh();if(!r)return!1;if(isAwsAuthRefreshFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: awsAuthRefresh executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("awsAuthRefresh invoked before trust check",r),a("tengu_awsAuthRefresh_missing_trust",{}),!1}try{return $("Fetching AWS caller identity for AWS auth refresh command"),await D(),$("Fetched AWS caller identity, skipping AWS auth refresh command"),!1}catch{return refreshAwsAuth(r)}}(),o=await async function(){const t=getConfiguredAwsCredentialExport();if(!t)return null;if(isAwsCredentialExportFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: awsCredentialExport executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("awsCredentialExport invoked before trust check",r),a("tengu_awsCredentialExport_missing_trust",{}),null}try{return $("Fetching AWS caller identity for credential export command"),await D(),$("Fetched AWS caller identity, skipping AWS credential export command"),null}catch{try{$("Running AWS credential export command");const e=await n(t,{shell:!0,reject:!1});if(0!==e.exitCode||!e.stdout)throw new Error("awsCredentialExport did not return a valid value");const r=pe(e.stdout.trim());if(!U(r))throw new Error("awsCredentialExport did not return valid AWS STS output structure");return $("AWS credentials retrieved from awsCredentialExport"),{accessKeyId:r.Credentials.AccessKeyId,secretAccessKey:r.Credentials.SecretAccessKey,sessionToken:r.Credentials.SessionToken}}catch(e){const t=r.red("Error getting AWS credentials from awsCredentialExport (in settings or ~/.context.json):");return e instanceof Error?console.error(t,e.message):console.error(t,e),null}}}();return(t||o)&&await H(),o},36e5);export function clearAwsCredentialsCache(){refreshAndGetAwsCredentials.cache.clear()}function getConfiguredGcpAuthRefresh(){return(ce()||{}).gcpAuthRefresh}export function isGcpAuthRefreshFromProjectSettings(){const e=getConfiguredGcpAuthRefresh();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.gcpAuthRefresh===e||t?.gcpAuthRefresh===e}const _e=l;export async function checkGcpCredentialsValid(){try{const{GoogleAuth:e}=await import("google-auth-library"),r=new e({scopes:["https://www.googleapis.com/auth/cloud-platform"]}),t=(async()=>{const e=await r.getClient();await e.getAccessToken()})(),n=ue(5e3).then(()=>{throw new GcpCredentialsTimeoutError("GCP credentials check timed out")});return await Promise.race([t,n]),!0}catch{return!1}}const ge=18e4;export function refreshGcpAuth(e){$("Running GCP auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:ge});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),$(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),$(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)$("GCP auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===t?r.red("GCP auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):r.red("Error running gcpAuthRefresh (in settings or ~/.context.json):");console.error(e),n.endAuthentication(!1),o(!1)}})})}export const refreshGcpCredentialsIfNeeded=Z(async()=>await async function(){const r=getConfiguredGcpAuthRefresh();if(!r)return!1;if(isGcpAuthRefreshFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: gcpAuthRefresh executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("gcpAuthRefresh invoked before trust check",r),a("tengu_gcpAuthRefresh_missing_trust",{}),!1}try{if($("Checking GCP credentials validity for auth refresh"),await checkGcpCredentialsValid())return $("GCP credentials are valid, skipping auth refresh command"),!1}catch{}return refreshGcpAuth(r)}(),36e5);export function clearGcpCredentialsCache(){refreshGcpCredentialsIfNeeded.cache.clear()}export function prefetchGcpCredentialsIfSafe(){if(getConfiguredGcpAuthRefresh()){if(isGcpAuthRefreshFromProjectSettings()){if(!G()&&!m())return}refreshGcpCredentialsIfNeeded()}}export function prefetchAwsCredentialsAndBedRockInfoIfSafe(){const e=getConfiguredAwsAuthRefresh(),r=getConfiguredAwsCredentialExport();if(e||r){if(isAwsAuthRefreshFromProjectSettings()||isAwsCredentialExportFromProjectSettings()){if(!G()&&!m())return}refreshAndGetAwsCredentials(),d()}}export const getApiKeyFromConfigOrMacOSKeychain=i(()=>{if("darwin"===process.platform){const e=re();if(e){if(e.stdout)return{key:e.stdout,source:"/login managed key"}}else{const e=ne();try{const r=q(`security find-generic-password -a $USER -w -s "${e}"`);if(r)return{key:r,source:"/login managed key"}}catch(e){J(e)}}}const e=j();return e.primaryApiKey?{key:e.primaryApiKey,source:"/login managed key"}:null});function isValidApiKey(e){return/^[a-zA-Z0-9-_\.]+$/.test(e)}function getStoredProviderApiKey(e,r){try{const t=Q().read();if(r){const n=t?.providerProfileApiKeys?.[r];if("string"==typeof n&&n.trim())return n;if(!O(e,r))return null}return t?.providerApiKeys?.[e]??null}catch{return null}}export function hasStoredProviderApiKey(e,r){return Boolean(getStoredProviderApiKey(e,r))}export async function saveProviderApiKey(e,r){if(!isValidApiKey(r))throw new Error("Formato de clave API inválido. La clave API solo debe contener caracteres alfanuméricos, guiones, guiones bajos y puntos.");const t=Q(),n=t.read()||{},o=T(e)?E(e,{createIfMissing:!0})?.id??null:null;if(!t.update({...n,providerApiKeys:{...n.providerApiKeys??{},[e]:r},...o?{providerProfileApiKeys:{...n.providerProfileApiKeys??{},[o]:r}}:{}}).success)throw new Error(`Failed to save ${e} API key`)}export async function removeProviderApiKey(e){const r=Q(),t=r.read()||{},n={...t.providerApiKeys??{}};delete n[e];const o={...t.providerProfileApiKeys??{}};if(T(e)){const r=_(e);r&&delete o[r]}if(!r.update({...t,providerApiKeys:n,providerProfileApiKeys:o}).success)throw new Error(`Failed to remove ${e} API key`)}export async function saveApiKey(e){if(!isValidApiKey(e))throw new Error("Formato de clave API inválido. La clave API solo debe contener caracteres alfanuméricos, guiones, guiones bajos y puntos.");await maybeRemoveApiKeyFromMacOSKeychain();let r=!1;if("darwin"===process.platform)try{const t=ne(),o=oe(),s=`add-generic-password -U -a "${o}" -s "${t}" -X "${Buffer.from(e,"utf-8").toString("hex")}"\n`;await n("security",["-i"],{input:s,reject:!1}),a("tengu_api_key_saved_to_keychain",{}),r=!0}catch(e){J(e),a("tengu_api_key_keychain_error",{error:z(e)}),a("tengu_api_key_saved_to_config",{})}else a("tengu_api_key_saved_to_config",{});const t=R(e);F(n=>{const o=n.customApiKeyResponses?.approved??[];return{...n,primaryApiKey:r?n.primaryApiKey:e,customApiKeyResponses:{...n.customApiKeyResponses,approved:o.includes(t)?o:[...o,t],rejected:n.customApiKeyResponses?.rejected??[]}}}),getApiKeyFromConfigOrMacOSKeychain.cache.clear?.(),ee()}export function isCustomApiKeyApproved(e){const r=j(),t=R(e);return r.customApiKeyResponses?.approved?.includes(t)??!1}export async function removeApiKey(){await maybeRemoveApiKeyFromMacOSKeychain(),F(e=>({...e,primaryApiKey:void 0})),getApiKeyFromConfigOrMacOSKeychain.cache.clear?.(),ee()}async function maybeRemoveApiKeyFromMacOSKeychain(){try{await N()}catch(e){J(e)}}export function saveOAuthTokensIfNeeded(e,r){if(!S(e.scopes))return a("tengu_oauth_tokens_not_claude_ai",{}),{success:!0};if(!e.refreshToken||!e.expiresAt)return a("tengu_oauth_tokens_inference_only",{}),{success:!0};const t=Q(),n=t.name;try{const o=t.read()||{},s=o.claudeAiOauth,i=r??_("claude"),c={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:e.subscriptionType??s?.subscriptionType??null,rateLimitTier:e.rateLimitTier??s?.rateLimitTier??null};i&&(o.providerProfileOauth={...o.providerProfileOauth??{},[i]:c});const u=t.update(o);return u.success?a("tengu_oauth_tokens_saved",{storageBackend:n}):a("tengu_oauth_tokens_save_failed",{storageBackend:n}),getClaudeAIOAuthTokens.cache?.clear?.(),L(),le(),u}catch(e){return J(e),a("tengu_oauth_tokens_save_exception",{storageBackend:n,error:z(e)}),{success:!1,warning:"Failed to save OAuth tokens"}}}export function saveOpenAIOAuthTokens(e,r){const t=Q(),n=t.name;try{const o=t.read()||{},s=r??_("openai"),i={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:e.subscriptionType??null,rateLimitTier:e.rateLimitTier??null};o.openAiOauth=i,s&&(o.providerProfileOauth={...o.providerProfileOauth??{},[s]:i});const c=t.update(o);return c.success?a("tengu_openai_oauth_tokens_saved",{storageBackend:n}):a("tengu_openai_oauth_tokens_save_failed",{storageBackend:n}),getOpenAIOAuthTokens.cache?.clear?.(),L(),le(),c}catch(e){return J(e),a("tengu_openai_oauth_tokens_save_exception",{storageBackend:n,error:z(e)}),{success:!1,warning:"Failed to save OpenAI OAuth tokens"}}}export function getClaudeAIOAuthTokens(){if(B())return null;const e=process.env.CONTEXT_CODE_OAUTH_TOKEN??process.env.CLAUDE_CODE_OAUTH_TOKEN;if(isManagedOAuthContext()&&e)return{accessToken:e,refreshToken:null,expiresAt:null,scopes:["user:inference"],subscriptionType:null,rateLimitTier:null};const r=isManagedOAuthContext()?P():null;if(r)return{accessToken:r,refreshToken:null,expiresAt:null,scopes:["user:inference"],subscriptionType:null,rateLimitTier:null};try{const e=getStoredProviderOAuthTokens("claude",_("claude"));return e?.accessToken?e:null}catch(e){return J(e),null}}export function getOpenAIOAuthTokens(){if(B())return null;if(process.env.OPENAI_OAUTH_TOKEN)return{accessToken:process.env.OPENAI_OAUTH_TOKEN,refreshToken:null,expiresAt:null,scopes:["responses:inference"],subscriptionType:null,rateLimitTier:null};try{const e=getStoredProviderOAuthTokens("openai",_("openai"));return e?.accessToken?e:null}catch(e){return J(e),null}}export function getOpenAIAccessToken(){return process.env.OPENAI_API_KEY||process.env.OPENAI_API_TOKEN||getOpenAIOAuthTokens()?.accessToken||null}export function getOpenRouterAccessToken(){return process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||getStoredProviderApiKey("openrouter",_("openrouter"))||null}export async function checkGeminiGoogleCredentialsValid(){try{const e=await getGeminiGoogleAuthHeaders(),r=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0,t=fetch("https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",{method:"POST",headers:e,body:JSON.stringify({cloudaicompanionProject:r,metadata:{ideType:"IDE_UNSPECIFIED",platform:"PLATFORM_UNSPECIFIED",pluginType:"GEMINI",duetProject:r},mode:"HEALTH_CHECK"})}).then(e=>{if(!e.ok)throw new Error(`Gemini credentials check failed: ${e.status}`)}),n=ue(5e3).then(()=>{throw new GcpCredentialsTimeoutError("Gemini credentials check timed out")});return await Promise.race([t,n]),!0}catch{return!1}}export function getGeminiGoogleOAuthTokens(){try{const e=_("gemini-google"),r=Q().read(),t=e?r?.providerProfileOauth?.[e]:null;if(t?.accessToken)return t;const n=Object.entries(r?.providerProfileOauth??{}).find(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())?.[1];return n?.accessToken?n:null}catch{return null}}export function saveGeminiGoogleOAuthTokens(e){const r=Q(),t=r.name;try{const n=r.read()||{},o=_("gemini-google")??g("gemini-google").id,s={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:null,rateLimitTier:null,projectId:e.projectId};o&&(n.providerProfileOauth={...n.providerProfileOauth??{},[o]:s});const i=r.update(n);return a(i.success?"tengu_gemini_google_oauth_tokens_saved":"tengu_gemini_google_oauth_tokens_save_failed",{storageBackend:t}),i}catch(e){return J(e),a("tengu_gemini_google_oauth_tokens_save_exception",{storageBackend:t,error:z(e)}),{success:!1,warning:"Failed to save Gemini OAuth tokens"}}}function quoteShellArg(e){return`"${e.replace(/"/g,'\\"')}"`}export function getGeminiGoogleAuthCommand(){const e=process.env.GEMINI_OAUTH_CLIENT_SECRET_FILE||process.env.GOOGLE_OAUTH_CLIENT_SECRET_FILE,r=_e.join(",");return`gcloud auth application-default login${e?` --client-id-file=${quoteShellArg(e)}`:""} --scopes=${quoteShellArg(r)}`}export async function refreshGeminiGoogleAuth(){return refreshGcpAuth(getGeminiGoogleAuthCommand())}export function getGeminiApiAccessToken(){return process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||getStoredProviderApiKey("gemini-api",_("gemini-api"))||null}export async function getGeminiGoogleAuthHeaders(){const e=process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN,r={"Content-Type":"application/json"};if(e)r.Authorization=`Bearer ${e}`;else{const e=await async function(){const e=getGeminiGoogleOAuthTokens();if(!e?.refreshToken)return e;if(e.expiresAt&&e.expiresAt>Date.now()+6e4)return e;const r=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refreshToken,client_id:u,client_secret:p})});if(!r.ok)return e;const t=await r.json(),n={...e,accessToken:t.access_token,expiresAt:t.expires_in?Date.now()+1e3*t.expires_in:e.expiresAt,scopes:t.scope?.split(/\s+/).filter(Boolean)??e.scopes};return saveGeminiGoogleOAuthTokens(n),n}();if(e?.accessToken){r.Authorization=`Bearer ${e.accessToken}`;const t=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim();t&&(r["x-goog-user-project"]=t)}else{const{GoogleAuth:e}=await import("google-auth-library"),t=new e({scopes:_e}),n=await t.getClient(),o=await n.getRequestHeaders();if("function"==typeof o.forEach)o.forEach((e,t)=>{r[t]=e});else for(const[e,t]of Object.entries(o))Array.isArray(t)?r[e]=t.map(String).join(", "):null!=t&&(r[e]=String(t))}}const t=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0;return t&&(r["x-goog-user-project"]=t),r}export function getZAIAccessToken(){return process.env.ZAI_API_KEY||getStoredProviderApiKey("zai",_("zai"))||null}export function getMiniMaxAccessToken(){return process.env.MINIMAX_API_KEY||getStoredProviderApiKey("minimax",_("minimax"))||null}export function getNvidiaAccessToken(){return process.env.NVIDIA_API_KEY||getStoredProviderApiKey("nvidia",_("nvidia"))||null}export function getDeepSeekAccessToken(){return process.env.DEEPSEEK_API_KEY||getStoredProviderApiKey("deepseek",_("deepseek"))||null}export function getOllamaAccessToken(){return"ollama"}export function getOllamaCloudAccessToken(){return process.env.OLLAMA_API_KEY||getStoredProviderApiKey("ollama-cloud",_("ollama-cloud"))||null}export function getOpenAICompatibleAccessToken(e=f()){switch(e){case"openrouter":return getOpenRouterAccessToken();case"gemini-api":return getGeminiApiAccessToken();case"gemini-google":return process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||null;case"zai":return getZAIAccessToken();case"minimax":return getMiniMaxAccessToken();case"nvidia":return getNvidiaAccessToken();case"deepseek":return getDeepSeekAccessToken();case"ollama":return getOllamaAccessToken();case"ollama-cloud":return getOllamaCloudAccessToken();default:return getOpenAIAccessToken()}}export async function getOpenAIOAuthTokensAsync(){if(B())return null;if(process.env.OPENAI_OAUTH_TOKEN)return getOpenAIOAuthTokens();try{const e=Q(),r=await e.readAsync(),t=_("openai"),n=t&&r?.providerProfileOauth?.[t]||(t&&!O("openai",t)?null:r?.openAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}export function clearOAuthTokenCache(){getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.(),te()}let Oe=0;async function invalidateOAuthCacheIfDiskChanged(){try{const e="sqlite"===Q().name?ie():se(),{mtimeMs:r}=await s(e);r!==Oe&&(Oe=r,clearOAuthTokenCache())}catch{getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.()}}const Te=new Map;export function handleOAuth401Error(e){const r=Te.get(e);if(r)return r;const t=async function(e){clearOAuthTokenCache();const r=await getClaudeAIOAuthTokensAsync();if(!r?.refreshToken)return!1;if(r.accessToken!==e)return a("tengu_oauth_401_recovered_from_keychain",{}),!0;return checkAndRefreshOAuthTokenIfNeeded(0,!0)}(e).finally(()=>{Te.delete(e)});return Te.set(e,t),t}export async function handleOpenAIOAuth401Error(e){clearOAuthTokenCache();const r=await getOpenAIOAuthTokensAsync();return!!r?.refreshToken&&(r.accessToken!==e?(a("tengu_openai_oauth_401_recovered_from_keychain",{}),!0):checkAndRefreshOpenAIOAuthTokenIfNeeded(0,!0))}export async function getClaudeAIOAuthTokensAsync(){if(B())return null;if(isManagedOAuthContext()&&(process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN||P()))return getClaudeAIOAuthTokens();try{const e=Q(),r=await e.readAsync(),t=_("claude"),n=t&&r?.providerProfileOauth?.[t]||(t&&!O("claude",t)?null:r?.claudeAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}let Ee=null,me=null;export function checkAndRefreshOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(Ee)return Ee;const t=checkAndRefreshOAuthTokenIfNeededImpl(e,r);return Ee=t.finally(()=>{Ee=null}),Ee}return checkAndRefreshOAuthTokenIfNeededImpl(e,r)}export function checkAndRefreshOpenAIOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(me)return me;const t=checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r);return me=t.finally(()=>{me=null}),me}return checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r)}async function checkAndRefreshOAuthTokenIfNeededImpl(e,r){await invalidateOAuthCacheIfDiskChanged();const t=getClaudeAIOAuthTokens();if(!(r||t?.refreshToken&&v(t.expiresAt)))return!1;if(!t?.refreshToken)return!1;if(!S(t.scopes))return!1;getClaudeAIOAuthTokens.cache?.clear?.(),te();const n=await getClaudeAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=Y();let i;await o(s,{recursive:!0});try{a("tengu_oauth_token_refresh_lock_acquiring",{}),i=await V.lock(s),a("tengu_oauth_token_refresh_lock_acquired",{})}catch(t){return"ELOCKED"===t.code?e<5?(a("tengu_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOAuthTokenIfNeededImpl(e+1,r)):(a("tengu_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(t),a("tengu_oauth_token_refresh_lock_error",{error:z(t)}),!1)}try{getClaudeAIOAuthTokens.cache?.clear?.(),te();const e=await getClaudeAIOAuthTokensAsync();if(!e?.refreshToken||!v(e.expiresAt))return a("tengu_oauth_token_refresh_race_resolved",{}),!1;a("tengu_oauth_token_refresh_starting",{});return saveOAuthTokensIfNeeded(await K(e.refreshToken,{scopes:S(e.scopes)?void 0:e.scopes})),getClaudeAIOAuthTokens.cache?.clear?.(),te(),!0}catch(e){J(e),getClaudeAIOAuthTokens.cache?.clear?.(),te();const r=await getClaudeAIOAuthTokensAsync();return!(!r||v(r.expiresAt))&&(a("tengu_oauth_token_refresh_race_recovered",{}),!0)}finally{a("tengu_oauth_token_refresh_lock_releasing",{}),await i(),a("tengu_oauth_token_refresh_lock_released",{})}}async function checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r){await invalidateOAuthCacheIfDiskChanged();const t=getOpenAIOAuthTokens();if(!(r||t?.refreshToken&&v(t.expiresAt)))return!1;if(!t?.refreshToken)return!1;getOpenAIOAuthTokens.cache?.clear?.(),te();const n=await getOpenAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=Y();let i;await o(s,{recursive:!0});try{a("tengu_openai_oauth_token_refresh_lock_acquiring",{}),i=await V.lock(s),a("tengu_openai_oauth_token_refresh_lock_acquired",{})}catch(t){return"ELOCKED"===t.code?e<5?(a("tengu_openai_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e+1,r)):(a("tengu_openai_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(t),!1)}try{getOpenAIOAuthTokens.cache?.clear?.(),te();const e=await getOpenAIOAuthTokensAsync();if(!e?.refreshToken||!v(e.expiresAt))return a("tengu_openai_oauth_token_refresh_race_resolved",{}),!1;a("tengu_openai_oauth_token_refresh_starting",{});return saveOpenAIOAuthTokens(await I(e.refreshToken,{scopes:e.scopes})),getOpenAIOAuthTokens.cache?.clear?.(),te(),!0}catch(e){J(e),getOpenAIOAuthTokens.cache?.clear?.(),te();const r=await getOpenAIOAuthTokensAsync();return!(!r||v(r.expiresAt))&&(a("tengu_openai_oauth_token_refresh_race_recovered",{}),!0)}finally{a("tengu_openai_oauth_token_refresh_lock_releasing",{}),await i(),a("tengu_openai_oauth_token_refresh_lock_released",{})}}export function isClaudeAISubscriber(){return!!isAnthropicAuthEnabled()&&S(getClaudeAIOAuthTokens()?.scopes)}export function hasProfileScope(){return getClaudeAIOAuthTokens()?.scopes?.includes(c)??!1}export function is1PApiCustomer(){return!(X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(f()))&&!isClaudeAISubscriber()}export function getOauthAccountInfo(){return isAnthropicAuthEnabled()?j().oauthAccount:void 0}export function isOverageProvisioningAllowed(){const e=getOauthAccountInfo(),r=e?.billingType;return!(!isClaudeAISubscriber()||!r)&&("stripe_subscription"===r||"stripe_subscription_contracted"===r||"apple_subscription"===r||"google_play_subscription"===r)}export function hasOpusAccess(){const e=getSubscriptionType();return"max"===e||"enterprise"===e||"team"===e||"pro"===e||null===e}export function getSubscriptionType(){if(C())return k();if(!isAnthropicAuthEnabled())return null;const e=getClaudeAIOAuthTokens();return e?e.subscriptionType??null:null}export function isMaxSubscriber(){return"max"===getSubscriptionType()}export function isTeamSubscriber(){return"team"===getSubscriptionType()}export function isTeamPremiumSubscriber(){return"team"===getSubscriptionType()&&"default_claude_max_5x"===getRateLimitTier()}export function isEnterpriseSubscriber(){return"enterprise"===getSubscriptionType()}export function isProSubscriber(){return"pro"===getSubscriptionType()}export function getRateLimitTier(){if(!isAnthropicAuthEnabled())return null;const e=getClaudeAIOAuthTokens();return e?e.rateLimitTier??null:null}export function getSubscriptionName(){switch(getSubscriptionType()){case"enterprise":return"Context Empresarial";case"team":return"Context Equipo";case"max":return"Context Max";case"pro":return"Context Pro";default:return"Context API"}}export function isUsing3PServices(){return!!(X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(f()))}function getConfiguredOtelHeadersHelper(){return(ce()||{}).otelHeadersHelper}export function isOtelHeadersHelperFromProjectOrLocalSettings(){const e=getConfiguredOtelHeadersHelper();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.otelHeadersHelper===e||t?.otelHeadersHelper===e}let ye=null,ke=0;const Ce=174e4;export function getOtelHeadersFromHelper(){const e=getConfiguredOtelHeadersHelper();if(!e)return{};const r=parseInt(process.env.CONTEXT_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||process.env.CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||Ce.toString());if(ye&&Date.now()-ke<r)return ye;if(isOtelHeadersHelperFromProjectOrLocalSettings()){if(!G())return{}}try{const r=q(e,{timeout:3e4})?.toString().trim();if(!r)throw new Error("otelHeadersHelper did not return a valid value");const t=pe(r);if("object"!=typeof t||null===t||Array.isArray(t))throw new Error("otelHeadersHelper must return a JSON object with string key-value pairs");for(const[e,r]of Object.entries(t))if("string"!=typeof r)throw new Error(`otelHeadersHelper returned non-string value for key "${e}": ${typeof r}`);return ye=t,ke=Date.now(),ye}catch(e){throw J(new Error(`Error getting OpenTelemetry headers from otelHeadersHelper (in settings): ${z(e)}`)),e}}export function isConsumerSubscriber(){const e=getSubscriptionType();return isClaudeAISubscriber()&&null!==e&&("max"===(r=e)||"pro"===r);var r}export function getAccountInformation(){if("firstParty"!==f())return;const{source:e}=getAuthTokenSource(),r={};"CLAUDE_CODE_OAUTH_TOKEN"===e||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===e?r.tokenSource=e:isClaudeAISubscriber()?r.subscription=getSubscriptionName():r.tokenSource=e;const{key:t,source:n}=getAnthropicApiKeyWithSource();if(t&&(r.apiKeySource=n),"claude.ai"===e||"/login managed key"===n){const e=getOauthAccountInfo()?.organizationName;e&&(r.organization=e)}const o=getOauthAccountInfo()?.emailAddress;return"claude.ai"!==e&&"/login managed key"!==n||!o||(r.email=o),r}export async function validateForceLoginOrg(){if(process.env.ANTHROPIC_UNIX_SOCKET)return{valid:!0};if(!isAnthropicAuthEnabled())return{valid:!0};const e=ae("policySettings")?.forceLoginOrgUUID;if(!e)return{valid:!0};await checkAndRefreshOAuthTokenIfNeeded();const r=getClaudeAIOAuthTokens();if(!r)return{valid:!0};const{source:t}=getAuthTokenSource(),n="CLAUDE_CODE_OAUTH_TOKEN"===t||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===t,o=await x(r.accessToken);if(!o)return{valid:!1,message:`Unable to verify organization for the current authentication token.\nThis machine requires organization ${e} but the profile could not be fetched.\nThis may be a network error, or the token may lack the user:profile scope required for\nverification (tokens from 'context setup-token' do not include this scope).\nTry again, or obtain a full-scope token via 'context auth login'.`};const s=o.organization.uuid;if(s===e)return{valid:!0};if(n){return{valid:!1,message:`The ${"CLAUDE_CODE_OAUTH_TOKEN"===t?"CLAUDE_CODE_OAUTH_TOKEN":"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"} environment variable provides a token for a\ndifferent organization than required by this machine's managed settings.\n\nRequired organization: ${e}\nToken organization: ${s}\n\nRemove the environment variable or obtain a token for the correct organization.`}}return{valid:!1,message:`Your authentication token belongs to organization ${s},\nbut this machine requires organization ${e}.\n\nPlease log in with the correct organization: context auth login`}}class GcpCredentialsTimeoutError extends Error{}
1
+ import{MACRO as e}from"../recovery/bunBundleShim.js";import r from"chalk";import{exec as t}from"child_process";import{execa as n}from"execa";import{mkdir as o,stat as s}from"fs/promises";import i from"lodash-es/memoize.js";import{CLAUDE_AI_PROFILE_SCOPE as c}from"../constants/oauth.js";import{logEvent as a}from"../services/analytics/index.js";import{GEMINI_CLI_OAUTH_CLIENT_ID as u,GEMINI_CLI_OAUTH_CLIENT_SECRET as p,GEMINI_CLI_OAUTH_SCOPES as l,GEMINI_CLI_OAUTH_TOKEN_URL as A}from"../constants/geminiOAuth.js";import{getModelStrings as d}from"./model/modelStrings.js";import{getAPIProvider as f,isOpenAICompatibleProvider as h}from"./model/providers.js";import{getResolvedProviderProfileId as _,ensureProviderProfile as g,isDefaultProfileId as O,isProfiledProvider as T,resolveProviderProfile as E}from"./model/providerProfiles.js";import{getIsNonInteractiveSession as m,preferThirdPartyAuthentication as y}from"../bootstrap/state.js";import{getMockSubscriptionType as k,shouldUseMockSubscription as C}from"../services/mockRateLimits.js";import{isOAuthTokenExpired as v,refreshOpenAIOAuthToken as I,refreshOAuthToken as K,shouldUseClaudeAIAuth as S}from"../services/oauth/client.js";import{getOauthProfileFromOauthToken as x}from"../services/oauth/getOauthProfile.js";import{getApiKeyFromFileDescriptor as P,getOAuthTokenFromFileDescriptor as w}from"./authFileDescriptor.js";import{maybeRemoveApiKeyFromMacOSKeychainThrows as N,normalizeApiKeyForConfig as R}from"./authPortable.js";import{checkStsCallerIdentity as D,clearAwsIniCache as H,isValidAwsStsOutput as U}from"./aws.js";import{AwsAuthStatusManager as b}from"./awsAuthStatusManager.js";import{clearBetasCaches as L}from"./betas.js";import{checkHasTrustDialogAccepted as G,getGlobalConfig as j,saveGlobalConfig as F}from"./config.js";import{logAntError as M,logForDebugging as $}from"./debug.js";import{getClaudeConfigHomeDir as Y,isBareMode as B,isEnvTruthy as X,isRunningOnHomespace as W}from"./envUtils.js";import{errorMessage as z}from"./errors.js";import{execSyncWithDefaults_DEPRECATED as q}from"./execFileNoThrow.js";import*as V from"./lockfile.js";import{logError as J}from"./log.js";import{memoizeWithTTLAsync as Z}from"./memoize.js";import{getSecureStorage as Q}from"./secureStorage/index.js";import{clearLegacyApiKeyPrefetch as ee,getLegacyApiKeyPrefetchResult as re}from"./secureStorage/keychainPrefetch.js";import{clearKeychainCache as te,getMacOsKeychainStorageServiceName as ne,getUsername as oe}from"./secureStorage/macOsKeychainHelpers.js";import{getLegacyCredentialsFilePath as se,getSecureStorageDbPath as ie}from"./secureStorage/sqliteStorage.js";import{getSettings_DEPRECATED as ce,getSettingsForSource as ae}from"./settings/settings.js";import{sleep as ue}from"./sleep.js";import{jsonParse as pe}from"./slowOperations.js";import{clearToolSchemaCache as le}from"./toolSchemaCache.js";function isManagedOAuthContext(){return X(process.env.CONTEXT_CODE_REMOTE)||X(process.env.CLAUDE_CODE_REMOTE)||"claude-desktop"===process.env.CLAUDE_CODE_ENTRYPOINT}export function isAnthropicAuthEnabled(){if(B())return!1;if(process.env.ANTHROPIC_UNIX_SOCKET)return!(!process.env.CONTEXT_CODE_OAUTH_TOKEN&&!process.env.CLAUDE_CODE_OAUTH_TOKEN);const e=f(),r=X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(e),t=(ce()||{}).apiKeyHelper,n=process.env.ANTHROPIC_AUTH_TOKEN||t||process.env.CONTEXT_CODE_API_KEY_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_API_KEY_FILE_DESCRIPTOR,{source:o}=getAnthropicApiKeyWithSource({skipRetrievingKeyFromApiKeyHelper:!0}),s="ANTHROPIC_API_KEY"===o||"apiKeyHelper"===o;return!(r||n&&!isManagedOAuthContext()||s&&!isManagedOAuthContext())}export function getAuthTokenSource(){const e=f();if(h(e))return{source:e,hasToken:Boolean(getOpenAICompatibleAccessToken(e))};if(B())return getConfiguredApiKeyHelper()?{source:"apiKeyHelper",hasToken:!0}:{source:"none",hasToken:!1};if(process.env.ANTHROPIC_AUTH_TOKEN&&!isManagedOAuthContext())return{source:"ANTHROPIC_AUTH_TOKEN",hasToken:!0};if(isManagedOAuthContext()&&(process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN))return{source:"CLAUDE_CODE_OAUTH_TOKEN",hasToken:!0};if(isManagedOAuthContext()?w():null)return process.env.CONTEXT_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR?{source:"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR",hasToken:!0}:{source:"CCR_OAUTH_TOKEN_FILE",hasToken:!0};if(getConfiguredApiKeyHelper()&&!isManagedOAuthContext())return{source:"apiKeyHelper",hasToken:!0};const r=getClaudeAIOAuthTokens();return S(r?.scopes)&&r?.accessToken?{source:"claude.ai",hasToken:!0}:{source:"none",hasToken:!1}}function getProviderOauthStorageKey(e){return"claude"===e?"claudeAiOauth":"openAiOauth"}function shouldUseLegacyProviderOauthFallback(e){return"claude"!==e}export function getStoredProviderOAuthTokens(e,r){try{const t=Q().read();if(r){const n=t?.providerProfileOauth?.[r];if(n?.accessToken)return n;if(!O(e,r))return null}if("gemini-google"===e)return null;if(!shouldUseLegacyProviderOauthFallback(e))return null;const n=t?.[getProviderOauthStorageKey(e)];return n?.accessToken?n:null}catch{return null}}export function hasStoredProviderOAuthTokens(e,r){if(r)return Boolean(getStoredProviderOAuthTokens(e,r));try{const r=Q().read(),t=Object.entries(r?.providerProfileOauth??{}).some(([r,t])=>r.startsWith(`${e}/`)&&"object"==typeof t&&null!==t&&"string"==typeof t.accessToken&&t.accessToken.trim());return shouldUseLegacyProviderOauthFallback(e)?Boolean(t||r?.[getProviderOauthStorageKey(e)]?.accessToken):Boolean(t)}catch{return!1}}export async function renameProviderScopedCredentials(e,r){if(!e||!r||e===r)return;const t=Q(),n=t.read()||{},o={...n.providerProfileApiKeys??{}},s={...n.providerProfileOauth??{}};e in o&&(o[r]=o[e],delete o[e]),e in s&&(s[r]=s[e],delete s[e]);if(!t.update({...n,providerProfileApiKeys:o,providerProfileOauth:s}).success)throw new Error("No se pudieron mover las credenciales del perfil.")}export async function removeProviderScopedCredentials(e){if(!e)return;const r=Q(),t=r.read()||{},n={...t.providerProfileApiKeys??{}},o={...t.providerProfileOauth??{}};delete n[e],delete o[e];if(!r.update({...t,providerProfileApiKeys:n,providerProfileOauth:o}).success)throw new Error("No se pudieron eliminar las credenciales del perfil.")}export async function removeAllProviderScopedCredentials(){const e=Q(),r=e.read()||{};if(!e.update({...r,providerProfileApiKeys:{},providerProfileOauth:{}}).success)throw new Error("No se pudieron eliminar las credenciales scoped de perfiles.")}export function getAnthropicApiKey(){const{key:e}=getAnthropicApiKeyWithSource();return e}export function hasAnthropicApiKeyAuth(){const{key:e,source:r}=getAnthropicApiKeyWithSource({skipRetrievingKeyFromApiKeyHelper:!0});return null!==e&&"none"!==r}export function getAnthropicApiKeyWithSource(e={}){if(h(f()))return{key:null,source:"none"};if(B())return process.env.ANTHROPIC_API_KEY?{key:process.env.ANTHROPIC_API_KEY,source:"ANTHROPIC_API_KEY"}:getConfiguredApiKeyHelper()?{key:e.skipRetrievingKeyFromApiKeyHelper?null:getApiKeyFromApiKeyHelperCached(),source:"apiKeyHelper"}:{key:null,source:"none"};const r=W()?void 0:process.env.ANTHROPIC_API_KEY;if(y()&&r)return{key:r,source:"ANTHROPIC_API_KEY"};if(X(process.env.CI)||"test"===process.env.NODE_ENV){const e=P();if(e)return{key:e,source:"ANTHROPIC_API_KEY"};if(!(r||process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN||process.env.CONTEXT_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR||process.env.CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR))throw new Error("ANTHROPIC_API_KEY or CONTEXT_CODE_OAUTH_TOKEN (legacy: CLAUDE_CODE_OAUTH_TOKEN) env var is required");return r?{key:r,source:"ANTHROPIC_API_KEY"}:{key:null,source:"none"}}if(r&&j().customApiKeyResponses?.approved?.includes(R(r)))return{key:r,source:"ANTHROPIC_API_KEY"};const t=P();if(t)return{key:t,source:"ANTHROPIC_API_KEY"};if(getConfiguredApiKeyHelper())return e.skipRetrievingKeyFromApiKeyHelper?{key:null,source:"apiKeyHelper"}:{key:getApiKeyFromApiKeyHelperCached(),source:"apiKeyHelper"};const n=getApiKeyFromConfigOrMacOSKeychain();return n||{key:null,source:"none"}}export function getConfiguredApiKeyHelper(){if(B())return ae("flagSettings")?.apiKeyHelper;return(ce()||{}).apiKeyHelper}function isApiKeyHelperFromProjectOrLocalSettings(){const e=getConfiguredApiKeyHelper();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.apiKeyHelper===e||t?.apiKeyHelper===e}function getConfiguredAwsAuthRefresh(){return(ce()||{}).awsAuthRefresh}export function isAwsAuthRefreshFromProjectSettings(){const e=getConfiguredAwsAuthRefresh();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.awsAuthRefresh===e||t?.awsAuthRefresh===e}function getConfiguredAwsCredentialExport(){return(ce()||{}).awsCredentialExport}export function isAwsCredentialExportFromProjectSettings(){const e=getConfiguredAwsCredentialExport();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.awsCredentialExport===e||t?.awsCredentialExport===e}export function calculateApiKeyHelperTTL(){const e=process.env.CONTEXT_CODE_API_KEY_HELPER_TTL_MS??process.env.CLAUDE_CODE_API_KEY_HELPER_TTL_MS;if(e){const r=parseInt(e,10);if(!Number.isNaN(r)&&r>=0)return r;$(`Found CLAUDE_CODE_API_KEY_HELPER_TTL_MS env var, but it was not a valid number. Got ${e}`,{level:"error"})}return 3e5}let Ae=null,de=null,fe=0;export function getApiKeyHelperElapsedMs(){const e=de?.startedAt;return e?Date.now()-e:0}export async function getApiKeyFromApiKeyHelper(e){if(!getConfiguredApiKeyHelper())return null;const r=calculateApiKeyHelperTTL();return Ae?(Date.now()-Ae.timestamp<r||de||(de={promise:_runAndCache(e,!1,fe),startedAt:null}),Ae.value):(de||(de={promise:_runAndCache(e,!0,fe),startedAt:Date.now()}),de.promise)}async function _runAndCache(t,o,s){try{const r=await async function(r){const t=getConfiguredApiKeyHelper();if(!t)return null;if(isApiKeyHelperFromProjectOrLocalSettings()){if(!G()&&!r){const r=new Error(`Security: apiKeyHelper executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("apiKeyHelper invoked before trust check",r),a("tengu_apiKeyHelper_missing_trust11",{}),null}}const o=await n(t,{shell:!0,timeout:6e5,reject:!1});if(o.failed){const e=o.timedOut?"timed out":`exited ${o.exitCode}`,r=o.stderr?.trim();throw new Error(r?`${e}: ${r}`:e)}const s=o.stdout?.trim();if(!s)throw new Error("did not return a value");return s}(t);return s!==fe||null!==r&&(Ae={value:r,timestamp:Date.now()}),r}catch(e){if(s!==fe)return" ";const t=e instanceof Error?e.message:String(e);return console.error(r.red(`apiKeyHelper failed: ${t}`)),$(`Error getting API key from apiKeyHelper: ${t}`,{level:"error"}),!o&&Ae&&" "!==Ae.value?(Ae={...Ae,timestamp:Date.now()},Ae.value):(Ae={value:" ",timestamp:Date.now()}," ")}finally{s===fe&&(de=null)}}export function getApiKeyFromApiKeyHelperCached(){return Ae?.value??null}export function clearApiKeyHelperCache(){fe++,Ae=null,de=null}export function prefetchApiKeyFromApiKeyHelperIfSafe(e){isApiKeyHelperFromProjectOrLocalSettings()&&!G()||getApiKeyFromApiKeyHelper(e)}const he=18e4;export function refreshAwsAuth(e){$("Running AWS auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:he});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),$(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),$(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)$("AWS auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===t?r.red("AWS auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):r.red("Error running awsAuthRefresh (in settings or ~/.context.json):");console.error(e),n.endAuthentication(!1),o(!1)}})})}export const refreshAndGetAwsCredentials=Z(async()=>{const t=await async function(){const r=getConfiguredAwsAuthRefresh();if(!r)return!1;if(isAwsAuthRefreshFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: awsAuthRefresh executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("awsAuthRefresh invoked before trust check",r),a("tengu_awsAuthRefresh_missing_trust",{}),!1}try{return $("Fetching AWS caller identity for AWS auth refresh command"),await D(),$("Fetched AWS caller identity, skipping AWS auth refresh command"),!1}catch{return refreshAwsAuth(r)}}(),o=await async function(){const t=getConfiguredAwsCredentialExport();if(!t)return null;if(isAwsCredentialExportFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: awsCredentialExport executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("awsCredentialExport invoked before trust check",r),a("tengu_awsCredentialExport_missing_trust",{}),null}try{return $("Fetching AWS caller identity for credential export command"),await D(),$("Fetched AWS caller identity, skipping AWS credential export command"),null}catch{try{$("Running AWS credential export command");const e=await n(t,{shell:!0,reject:!1});if(0!==e.exitCode||!e.stdout)throw new Error("awsCredentialExport did not return a valid value");const r=pe(e.stdout.trim());if(!U(r))throw new Error("awsCredentialExport did not return valid AWS STS output structure");return $("AWS credentials retrieved from awsCredentialExport"),{accessKeyId:r.Credentials.AccessKeyId,secretAccessKey:r.Credentials.SecretAccessKey,sessionToken:r.Credentials.SessionToken}}catch(e){const t=r.red("Error getting AWS credentials from awsCredentialExport (in settings or ~/.context.json):");return e instanceof Error?console.error(t,e.message):console.error(t,e),null}}}();return(t||o)&&await H(),o},36e5);export function clearAwsCredentialsCache(){refreshAndGetAwsCredentials.cache.clear()}function getConfiguredGcpAuthRefresh(){return(ce()||{}).gcpAuthRefresh}export function isGcpAuthRefreshFromProjectSettings(){const e=getConfiguredGcpAuthRefresh();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.gcpAuthRefresh===e||t?.gcpAuthRefresh===e}const _e=l;export async function checkGcpCredentialsValid(){try{const{GoogleAuth:e}=await import("google-auth-library"),r=new e({scopes:["https://www.googleapis.com/auth/cloud-platform"]}),t=(async()=>{const e=await r.getClient();await e.getAccessToken()})(),n=ue(5e3).then(()=>{throw new GcpCredentialsTimeoutError("GCP credentials check timed out")});return await Promise.race([t,n]),!0}catch{return!1}}const ge=18e4;export function refreshGcpAuth(e){$("Running GCP auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:ge});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),$(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),$(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)$("GCP auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===t?r.red("GCP auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):r.red("Error running gcpAuthRefresh (in settings or ~/.context.json):");console.error(e),n.endAuthentication(!1),o(!1)}})})}export const refreshGcpCredentialsIfNeeded=Z(async()=>await async function(){const r=getConfiguredGcpAuthRefresh();if(!r)return!1;if(isGcpAuthRefreshFromProjectSettings()&&!G()&&!m()){const r=new Error(`Security: gcpAuthRefresh executed before workspace trust is confirmed. If you see this message, post in ${e.FEEDBACK_CHANNEL}.`);return M("gcpAuthRefresh invoked before trust check",r),a("tengu_gcpAuthRefresh_missing_trust",{}),!1}try{if($("Checking GCP credentials validity for auth refresh"),await checkGcpCredentialsValid())return $("GCP credentials are valid, skipping auth refresh command"),!1}catch{}return refreshGcpAuth(r)}(),36e5);export function clearGcpCredentialsCache(){refreshGcpCredentialsIfNeeded.cache.clear()}export function prefetchGcpCredentialsIfSafe(){if(getConfiguredGcpAuthRefresh()){if(isGcpAuthRefreshFromProjectSettings()){if(!G()&&!m())return}refreshGcpCredentialsIfNeeded()}}export function prefetchAwsCredentialsAndBedRockInfoIfSafe(){const e=getConfiguredAwsAuthRefresh(),r=getConfiguredAwsCredentialExport();if(e||r){if(isAwsAuthRefreshFromProjectSettings()||isAwsCredentialExportFromProjectSettings()){if(!G()&&!m())return}refreshAndGetAwsCredentials(),d()}}export const getApiKeyFromConfigOrMacOSKeychain=i(()=>{if("darwin"===process.platform){const e=re();if(e){if(e.stdout)return{key:e.stdout,source:"/login managed key"}}else{const e=ne();try{const r=q(`security find-generic-password -a $USER -w -s "${e}"`);if(r)return{key:r,source:"/login managed key"}}catch(e){J(e)}}}const e=j();return e.primaryApiKey?{key:e.primaryApiKey,source:"/login managed key"}:null});function isValidApiKey(e){return/^[a-zA-Z0-9-_\.]+$/.test(e)}function getStoredProviderApiKey(e,r){try{const t=Q().read();if(r){const n=t?.providerProfileApiKeys?.[r];if("string"==typeof n&&n.trim())return n;if(!O(e,r))return null}return t?.providerApiKeys?.[e]??null}catch{return null}}export function hasStoredProviderApiKey(e,r){return Boolean(getStoredProviderApiKey(e,r))}export async function saveProviderApiKey(e,r){if(!isValidApiKey(r))throw new Error("Formato de clave API inválido. La clave API solo debe contener caracteres alfanuméricos, guiones, guiones bajos y puntos.");const t=Q(),n=t.read()||{},o=T(e)?E(e,{createIfMissing:!0})?.id??null:null;if(!t.update({...n,providerApiKeys:{...n.providerApiKeys??{},[e]:r},...o?{providerProfileApiKeys:{...n.providerProfileApiKeys??{},[o]:r}}:{}}).success)throw new Error(`Failed to save ${e} API key`)}export async function removeProviderApiKey(e){const r=Q(),t=r.read()||{},n={...t.providerApiKeys??{}};delete n[e];const o={...t.providerProfileApiKeys??{}};if(T(e)){const r=_(e);r&&delete o[r]}if(!r.update({...t,providerApiKeys:n,providerProfileApiKeys:o}).success)throw new Error(`Failed to remove ${e} API key`)}export async function saveApiKey(e){if(!isValidApiKey(e))throw new Error("Formato de clave API inválido. La clave API solo debe contener caracteres alfanuméricos, guiones, guiones bajos y puntos.");await maybeRemoveApiKeyFromMacOSKeychain();let r=!1;if("darwin"===process.platform)try{const t=ne(),o=oe(),s=`add-generic-password -U -a "${o}" -s "${t}" -X "${Buffer.from(e,"utf-8").toString("hex")}"\n`;await n("security",["-i"],{input:s,reject:!1}),a("tengu_api_key_saved_to_keychain",{}),r=!0}catch(e){J(e),a("tengu_api_key_keychain_error",{error:z(e)}),a("tengu_api_key_saved_to_config",{})}else a("tengu_api_key_saved_to_config",{});const t=R(e);F(n=>{const o=n.customApiKeyResponses?.approved??[];return{...n,primaryApiKey:r?n.primaryApiKey:e,customApiKeyResponses:{...n.customApiKeyResponses,approved:o.includes(t)?o:[...o,t],rejected:n.customApiKeyResponses?.rejected??[]}}}),getApiKeyFromConfigOrMacOSKeychain.cache.clear?.(),ee()}export function isCustomApiKeyApproved(e){const r=j(),t=R(e);return r.customApiKeyResponses?.approved?.includes(t)??!1}export async function removeApiKey(){await maybeRemoveApiKeyFromMacOSKeychain(),F(e=>({...e,primaryApiKey:void 0})),getApiKeyFromConfigOrMacOSKeychain.cache.clear?.(),ee()}async function maybeRemoveApiKeyFromMacOSKeychain(){try{await N()}catch(e){J(e)}}export function saveOAuthTokensIfNeeded(e,r){if(!S(e.scopes))return a("tengu_oauth_tokens_not_claude_ai",{}),{success:!0};if(!e.refreshToken||!e.expiresAt)return a("tengu_oauth_tokens_inference_only",{}),{success:!0};const t=Q(),n=t.name;try{const o=t.read()||{},s=o.claudeAiOauth,i=r??_("claude"),c={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:e.subscriptionType??s?.subscriptionType??null,rateLimitTier:e.rateLimitTier??s?.rateLimitTier??null};i&&(o.providerProfileOauth={...o.providerProfileOauth??{},[i]:c});const u=t.update(o);return u.success?a("tengu_oauth_tokens_saved",{storageBackend:n}):a("tengu_oauth_tokens_save_failed",{storageBackend:n}),getClaudeAIOAuthTokens.cache?.clear?.(),L(),le(),u}catch(e){return J(e),a("tengu_oauth_tokens_save_exception",{storageBackend:n,error:z(e)}),{success:!1,warning:"Failed to save OAuth tokens"}}}export function saveOpenAIOAuthTokens(e,r){const t=Q(),n=t.name;try{const o=t.read()||{},s=r??_("openai"),i={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:e.subscriptionType??null,rateLimitTier:e.rateLimitTier??null};o.openAiOauth=i,s&&(o.providerProfileOauth={...o.providerProfileOauth??{},[s]:i});const c=t.update(o);return c.success?a("tengu_openai_oauth_tokens_saved",{storageBackend:n}):a("tengu_openai_oauth_tokens_save_failed",{storageBackend:n}),getOpenAIOAuthTokens.cache?.clear?.(),L(),le(),c}catch(e){return J(e),a("tengu_openai_oauth_tokens_save_exception",{storageBackend:n,error:z(e)}),{success:!1,warning:"Failed to save OpenAI OAuth tokens"}}}export function getClaudeAIOAuthTokens(){if(B())return null;const e=process.env.CONTEXT_CODE_OAUTH_TOKEN??process.env.CLAUDE_CODE_OAUTH_TOKEN;if(isManagedOAuthContext()&&e)return{accessToken:e,refreshToken:null,expiresAt:null,scopes:["user:inference"],subscriptionType:null,rateLimitTier:null};const r=isManagedOAuthContext()?w():null;if(r)return{accessToken:r,refreshToken:null,expiresAt:null,scopes:["user:inference"],subscriptionType:null,rateLimitTier:null};try{const e=getStoredProviderOAuthTokens("claude",_("claude"));return e?.accessToken?e:null}catch(e){return J(e),null}}export function getOpenAIOAuthTokens(){if(B())return null;if(process.env.OPENAI_OAUTH_TOKEN)return{accessToken:process.env.OPENAI_OAUTH_TOKEN,refreshToken:null,expiresAt:null,scopes:["responses:inference"],subscriptionType:null,rateLimitTier:null};try{const e=getStoredProviderOAuthTokens("openai",_("openai"));return e?.accessToken?e:null}catch(e){return J(e),null}}export function getOpenAIAccessToken(){return process.env.OPENAI_API_KEY||process.env.OPENAI_API_TOKEN||getOpenAIOAuthTokens()?.accessToken||null}export function getOpenRouterAccessToken(){return process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||getStoredProviderApiKey("openrouter",_("openrouter"))||null}export async function checkGeminiGoogleCredentialsValid(){try{const e=await getGeminiGoogleAuthHeaders(),r=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0,t=fetch("https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",{method:"POST",headers:e,body:JSON.stringify({cloudaicompanionProject:r,metadata:{ideType:"IDE_UNSPECIFIED",platform:"PLATFORM_UNSPECIFIED",pluginType:"GEMINI",duetProject:r},mode:"HEALTH_CHECK"})}).then(e=>{if(!e.ok)throw new Error(`Gemini credentials check failed: ${e.status}`)}),n=ue(5e3).then(()=>{throw new GcpCredentialsTimeoutError("Gemini credentials check timed out")});return await Promise.race([t,n]),!0}catch{return!1}}export function getGeminiGoogleOAuthTokens(){try{const e=_("gemini-google"),r=Q().read(),t=e?r?.providerProfileOauth?.[e]:null;if(t?.accessToken)return t;const n=Object.entries(r?.providerProfileOauth??{}).find(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())?.[1];return n?.accessToken?n:null}catch{return null}}export function saveGeminiGoogleOAuthTokens(e){const r=Q(),t=r.name;try{const n=r.read()||{},o=_("gemini-google")??g("gemini-google").id,s={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:null,rateLimitTier:null,projectId:e.projectId};o&&(n.providerProfileOauth={...n.providerProfileOauth??{},[o]:s});const i=r.update(n);return a(i.success?"tengu_gemini_google_oauth_tokens_saved":"tengu_gemini_google_oauth_tokens_save_failed",{storageBackend:t}),i}catch(e){return J(e),a("tengu_gemini_google_oauth_tokens_save_exception",{storageBackend:t,error:z(e)}),{success:!1,warning:"Failed to save Gemini OAuth tokens"}}}function quoteShellArg(e){return`"${e.replace(/"/g,'\\"')}"`}export function getGeminiGoogleAuthCommand(){const e=process.env.GEMINI_OAUTH_CLIENT_SECRET_FILE||process.env.GOOGLE_OAUTH_CLIENT_SECRET_FILE,r=_e.join(",");return`gcloud auth application-default login${e?` --client-id-file=${quoteShellArg(e)}`:""} --scopes=${quoteShellArg(r)}`}export async function refreshGeminiGoogleAuth(){return refreshGcpAuth(getGeminiGoogleAuthCommand())}export function getGeminiApiAccessToken(){return process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||getStoredProviderApiKey("gemini-api",_("gemini-api"))||null}export async function getGeminiGoogleAuthHeaders(){const e=process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN,r={"Content-Type":"application/json"};if(e)r.Authorization=`Bearer ${e}`;else{const e=await async function(){const e=getGeminiGoogleOAuthTokens();if(!e?.refreshToken)return e;if(e.expiresAt&&e.expiresAt>Date.now()+6e4)return e;const r=await fetch(A,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refreshToken,client_id:u,client_secret:p})});if(!r.ok)return e;const t=await r.json(),n={...e,accessToken:t.access_token,expiresAt:t.expires_in?Date.now()+1e3*t.expires_in:e.expiresAt,scopes:t.scope?.split(/\s+/).filter(Boolean)??e.scopes};return saveGeminiGoogleOAuthTokens(n),n}();if(e?.accessToken){r.Authorization=`Bearer ${e.accessToken}`;const t=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim();t&&(r["x-goog-user-project"]=t)}else{const{GoogleAuth:e}=await import("google-auth-library"),t=new e({scopes:_e}),n=await t.getClient(),o=await n.getRequestHeaders();if("function"==typeof o.forEach)o.forEach((e,t)=>{r[t]=e});else for(const[e,t]of Object.entries(o))Array.isArray(t)?r[e]=t.map(String).join(", "):null!=t&&(r[e]=String(t))}}const t=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0;return t&&(r["x-goog-user-project"]=t),r}export function getZAIAccessToken(){return process.env.ZAI_API_KEY||getStoredProviderApiKey("zai",_("zai"))||null}export function getMiniMaxAccessToken(){return process.env.MINIMAX_API_KEY||getStoredProviderApiKey("minimax",_("minimax"))||null}export function getNvidiaAccessToken(){return process.env.NVIDIA_API_KEY||getStoredProviderApiKey("nvidia",_("nvidia"))||null}export function getDeepSeekAccessToken(){return process.env.DEEPSEEK_API_KEY||getStoredProviderApiKey("deepseek",_("deepseek"))||null}export function getOllamaAccessToken(){return"ollama"}export function getOllamaCloudAccessToken(){return process.env.OLLAMA_API_KEY||getStoredProviderApiKey("ollama-cloud",_("ollama-cloud"))||null}export function getOpenAICompatibleAccessToken(e=f()){switch(e){case"openrouter":return getOpenRouterAccessToken();case"gemini-api":return getGeminiApiAccessToken();case"gemini-google":return process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||null;case"zai":return getZAIAccessToken();case"minimax":return getMiniMaxAccessToken();case"nvidia":return getNvidiaAccessToken();case"deepseek":return getDeepSeekAccessToken();case"ollama":return getOllamaAccessToken();case"ollama-cloud":return getOllamaCloudAccessToken();case"custom-openai":return getStoredProviderApiKey("custom-openai");default:return getOpenAIAccessToken()}}export async function getOpenAIOAuthTokensAsync(){if(B())return null;if(process.env.OPENAI_OAUTH_TOKEN)return getOpenAIOAuthTokens();try{const e=Q(),r=await e.readAsync(),t=_("openai"),n=t&&r?.providerProfileOauth?.[t]||(t&&!O("openai",t)?null:r?.openAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}export function clearOAuthTokenCache(){getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.(),te()}let Oe=0;async function invalidateOAuthCacheIfDiskChanged(){try{const e="sqlite"===Q().name?ie():se(),{mtimeMs:r}=await s(e);r!==Oe&&(Oe=r,clearOAuthTokenCache())}catch{getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.()}}const Te=new Map;export function handleOAuth401Error(e){const r=Te.get(e);if(r)return r;const t=async function(e){clearOAuthTokenCache();const r=await getClaudeAIOAuthTokensAsync();if(!r?.refreshToken)return!1;if(r.accessToken!==e)return a("tengu_oauth_401_recovered_from_keychain",{}),!0;return checkAndRefreshOAuthTokenIfNeeded(0,!0)}(e).finally(()=>{Te.delete(e)});return Te.set(e,t),t}export async function handleOpenAIOAuth401Error(e){clearOAuthTokenCache();const r=await getOpenAIOAuthTokensAsync();return!!r?.refreshToken&&(r.accessToken!==e?(a("tengu_openai_oauth_401_recovered_from_keychain",{}),!0):checkAndRefreshOpenAIOAuthTokenIfNeeded(0,!0))}export async function getClaudeAIOAuthTokensAsync(){if(B())return null;if(isManagedOAuthContext()&&(process.env.CONTEXT_CODE_OAUTH_TOKEN||process.env.CLAUDE_CODE_OAUTH_TOKEN||w()))return getClaudeAIOAuthTokens();try{const e=Q(),r=await e.readAsync(),t=_("claude"),n=t&&r?.providerProfileOauth?.[t]||(t&&!O("claude",t)?null:r?.claudeAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}let Ee=null,me=null;export function checkAndRefreshOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(Ee)return Ee;const t=checkAndRefreshOAuthTokenIfNeededImpl(e,r);return Ee=t.finally(()=>{Ee=null}),Ee}return checkAndRefreshOAuthTokenIfNeededImpl(e,r)}export function checkAndRefreshOpenAIOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(me)return me;const t=checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r);return me=t.finally(()=>{me=null}),me}return checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r)}async function checkAndRefreshOAuthTokenIfNeededImpl(e,r){await invalidateOAuthCacheIfDiskChanged();const t=getClaudeAIOAuthTokens();if(!(r||t?.refreshToken&&v(t.expiresAt)))return!1;if(!t?.refreshToken)return!1;if(!S(t.scopes))return!1;getClaudeAIOAuthTokens.cache?.clear?.(),te();const n=await getClaudeAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=Y();let i;await o(s,{recursive:!0});try{a("tengu_oauth_token_refresh_lock_acquiring",{}),i=await V.lock(s),a("tengu_oauth_token_refresh_lock_acquired",{})}catch(t){return"ELOCKED"===t.code?e<5?(a("tengu_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOAuthTokenIfNeededImpl(e+1,r)):(a("tengu_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(t),a("tengu_oauth_token_refresh_lock_error",{error:z(t)}),!1)}try{getClaudeAIOAuthTokens.cache?.clear?.(),te();const e=await getClaudeAIOAuthTokensAsync();if(!e?.refreshToken||!v(e.expiresAt))return a("tengu_oauth_token_refresh_race_resolved",{}),!1;a("tengu_oauth_token_refresh_starting",{});return saveOAuthTokensIfNeeded(await K(e.refreshToken,{scopes:S(e.scopes)?void 0:e.scopes})),getClaudeAIOAuthTokens.cache?.clear?.(),te(),!0}catch(e){J(e),getClaudeAIOAuthTokens.cache?.clear?.(),te();const r=await getClaudeAIOAuthTokensAsync();return!(!r||v(r.expiresAt))&&(a("tengu_oauth_token_refresh_race_recovered",{}),!0)}finally{a("tengu_oauth_token_refresh_lock_releasing",{}),await i(),a("tengu_oauth_token_refresh_lock_released",{})}}async function checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r){await invalidateOAuthCacheIfDiskChanged();const t=getOpenAIOAuthTokens();if(!(r||t?.refreshToken&&v(t.expiresAt)))return!1;if(!t?.refreshToken)return!1;getOpenAIOAuthTokens.cache?.clear?.(),te();const n=await getOpenAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=Y();let i;await o(s,{recursive:!0});try{a("tengu_openai_oauth_token_refresh_lock_acquiring",{}),i=await V.lock(s),a("tengu_openai_oauth_token_refresh_lock_acquired",{})}catch(t){return"ELOCKED"===t.code?e<5?(a("tengu_openai_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e+1,r)):(a("tengu_openai_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(t),!1)}try{getOpenAIOAuthTokens.cache?.clear?.(),te();const e=await getOpenAIOAuthTokensAsync();if(!e?.refreshToken||!v(e.expiresAt))return a("tengu_openai_oauth_token_refresh_race_resolved",{}),!1;a("tengu_openai_oauth_token_refresh_starting",{});return saveOpenAIOAuthTokens(await I(e.refreshToken,{scopes:e.scopes})),getOpenAIOAuthTokens.cache?.clear?.(),te(),!0}catch(e){J(e),getOpenAIOAuthTokens.cache?.clear?.(),te();const r=await getOpenAIOAuthTokensAsync();return!(!r||v(r.expiresAt))&&(a("tengu_openai_oauth_token_refresh_race_recovered",{}),!0)}finally{a("tengu_openai_oauth_token_refresh_lock_releasing",{}),await i(),a("tengu_openai_oauth_token_refresh_lock_released",{})}}export function isClaudeAISubscriber(){return!!isAnthropicAuthEnabled()&&S(getClaudeAIOAuthTokens()?.scopes)}export function hasProfileScope(){return getClaudeAIOAuthTokens()?.scopes?.includes(c)??!1}export function is1PApiCustomer(){return!(X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(f()))&&!isClaudeAISubscriber()}export function getOauthAccountInfo(){return isAnthropicAuthEnabled()?j().oauthAccount:void 0}export function isOverageProvisioningAllowed(){const e=getOauthAccountInfo(),r=e?.billingType;return!(!isClaudeAISubscriber()||!r)&&("stripe_subscription"===r||"stripe_subscription_contracted"===r||"apple_subscription"===r||"google_play_subscription"===r)}export function hasOpusAccess(){const e=getSubscriptionType();return"max"===e||"enterprise"===e||"team"===e||"pro"===e||null===e}export function getSubscriptionType(){if(C())return k();if(!isAnthropicAuthEnabled())return null;const e=getClaudeAIOAuthTokens();return e?e.subscriptionType??null:null}export function isMaxSubscriber(){return"max"===getSubscriptionType()}export function isTeamSubscriber(){return"team"===getSubscriptionType()}export function isTeamPremiumSubscriber(){return"team"===getSubscriptionType()&&"default_claude_max_5x"===getRateLimitTier()}export function isEnterpriseSubscriber(){return"enterprise"===getSubscriptionType()}export function isProSubscriber(){return"pro"===getSubscriptionType()}export function getRateLimitTier(){if(!isAnthropicAuthEnabled())return null;const e=getClaudeAIOAuthTokens();return e?e.rateLimitTier??null:null}export function getSubscriptionName(){switch(getSubscriptionType()){case"enterprise":return"Context Empresarial";case"team":return"Context Equipo";case"max":return"Context Max";case"pro":return"Context Pro";default:return"Context API"}}export function isUsing3PServices(){return!!(X(process.env.CONTEXT_CODE_USE_BEDROCK)||X(process.env.CLAUDE_CODE_USE_BEDROCK)||X(process.env.CONTEXT_CODE_USE_VERTEX)||X(process.env.CLAUDE_CODE_USE_VERTEX)||X(process.env.CONTEXT_CODE_USE_FOUNDRY)||X(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(f()))}function getConfiguredOtelHeadersHelper(){return(ce()||{}).otelHeadersHelper}export function isOtelHeadersHelperFromProjectOrLocalSettings(){const e=getConfiguredOtelHeadersHelper();if(!e)return!1;const r=ae("projectSettings"),t=ae("localSettings");return r?.otelHeadersHelper===e||t?.otelHeadersHelper===e}let ye=null,ke=0;const Ce=174e4;export function getOtelHeadersFromHelper(){const e=getConfiguredOtelHeadersHelper();if(!e)return{};const r=parseInt(process.env.CONTEXT_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||process.env.CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||Ce.toString());if(ye&&Date.now()-ke<r)return ye;if(isOtelHeadersHelperFromProjectOrLocalSettings()){if(!G())return{}}try{const r=q(e,{timeout:3e4})?.toString().trim();if(!r)throw new Error("otelHeadersHelper did not return a valid value");const t=pe(r);if("object"!=typeof t||null===t||Array.isArray(t))throw new Error("otelHeadersHelper must return a JSON object with string key-value pairs");for(const[e,r]of Object.entries(t))if("string"!=typeof r)throw new Error(`otelHeadersHelper returned non-string value for key "${e}": ${typeof r}`);return ye=t,ke=Date.now(),ye}catch(e){throw J(new Error(`Error getting OpenTelemetry headers from otelHeadersHelper (in settings): ${z(e)}`)),e}}export function isConsumerSubscriber(){const e=getSubscriptionType();return isClaudeAISubscriber()&&null!==e&&("max"===(r=e)||"pro"===r);var r}export function getAccountInformation(){if("firstParty"!==f())return;const{source:e}=getAuthTokenSource(),r={};"CLAUDE_CODE_OAUTH_TOKEN"===e||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===e?r.tokenSource=e:isClaudeAISubscriber()?r.subscription=getSubscriptionName():r.tokenSource=e;const{key:t,source:n}=getAnthropicApiKeyWithSource();if(t&&(r.apiKeySource=n),"claude.ai"===e||"/login managed key"===n){const e=getOauthAccountInfo()?.organizationName;e&&(r.organization=e)}const o=getOauthAccountInfo()?.emailAddress;return"claude.ai"!==e&&"/login managed key"!==n||!o||(r.email=o),r}export async function validateForceLoginOrg(){if(process.env.ANTHROPIC_UNIX_SOCKET)return{valid:!0};if(!isAnthropicAuthEnabled())return{valid:!0};const e=ae("policySettings")?.forceLoginOrgUUID;if(!e)return{valid:!0};await checkAndRefreshOAuthTokenIfNeeded();const r=getClaudeAIOAuthTokens();if(!r)return{valid:!0};const{source:t}=getAuthTokenSource(),n="CLAUDE_CODE_OAUTH_TOKEN"===t||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===t,o=await x(r.accessToken);if(!o)return{valid:!1,message:`Unable to verify organization for the current authentication token.\nThis machine requires organization ${e} but the profile could not be fetched.\nThis may be a network error, or the token may lack the user:profile scope required for\nverification (tokens from 'context setup-token' do not include this scope).\nTry again, or obtain a full-scope token via 'context auth login'.`};const s=o.organization.uuid;if(s===e)return{valid:!0};if(n){return{valid:!1,message:`The ${"CLAUDE_CODE_OAUTH_TOKEN"===t?"CLAUDE_CODE_OAUTH_TOKEN":"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"} environment variable provides a token for a\ndifferent organization than required by this machine's managed settings.\n\nRequired organization: ${e}\nToken organization: ${s}\n\nRemove the environment variable or obtain a token for the correct organization.`}}return{valid:!1,message:`Your authentication token belongs to organization ${s},\nbut this machine requires organization ${e}.\n\nPlease log in with the correct organization: context auth login`}}class GcpCredentialsTimeoutError extends Error{}
@@ -1 +1 @@
1
- import{feature as e}from"../recovery/bunBundleShim.js";import{createRequire as t}from"module";const o=t(import.meta.url);import{randomBytes as n}from"crypto";import{unwatchFile as r,watchFile as s}from"fs";import i from"lodash-es/memoize.js";import a from"lodash-es/pickBy.js";import{basename as c,dirname as l,join as u,resolve as d}from"path";import{getOriginalCwd as f,getSessionTrustAccepted as p}from"../bootstrap/state.js";import{getAutoMemEntrypoint as g}from"../memdir/paths.js";import{logEvent as m}from"../services/analytics/index.js";import{getCwd as h}from"./cwd.js";import{registerCleanup as C}from"./cleanupRegistry.js";import{logForDebugging as b}from"./debug.js";import{logForDiagnosticsNoPII as y}from"./diagLogs.js";import{getGlobalClaudeFile as v}from"./env.js";import{getClaudeConfigHomeDir as E,isEnvTruthy as S}from"./envUtils.js";import{ConfigParseError as T,getErrnoCode as D}from"./errors.js";import{writeFileSyncAndFlush_DEPRECATED as _}from"./file.js";import{getFsImplementation as w}from"./fsOperations.js";import{findCanonicalGitRoot as k}from"./git.js";import{safeParseJSON as j}from"./json.js";import{stripBOM as A}from"./jsonRead.js";import*as G from"./lockfile.js";import{logError as N}from"./log.js";import{normalizePathForConfigKey as U}from"./path.js";import{getEssentialTrafficOnlyReason as O}from"./privacyLevel.js";import{getManagedFilePath as F}from"./settings/managedPath.js";const M=e("TEAMMEM")?o("../memdir/teamMemPaths.js"):null,x=e("CCR_AUTO_CONNECT")?o("../bridge/bridgeEnabled.js"):null;import{jsonParse as I,jsonStringify as L}from"./slowOperations.js";let P=!1;const R={allowedTools:[],mcpContextUris:[],mcpServers:{},enabledMcpjsonServers:[],disabledMcpjsonServers:[],hasTrustDialogAccepted:!1,projectOnboardingSeenCount:0,hasClaudeMdExternalIncludesApproved:!1,hasClaudeMdExternalIncludesWarningShown:!1};export{EDITOR_MODES,NOTIFICATION_CHANNELS}from"./configConstants.js";function createDefaultGlobalConfig(){return{numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1}}export const DEFAULT_GLOBAL_CONFIG={numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1};export const GLOBAL_CONFIG_KEYS=["apiKeyHelper","installMethod","autoUpdates","autoUpdatesProtectedForNative","theme","verbose","preferredNotifChannel","shiftEnterKeyBindingInstalled","editorMode","hasUsedBackslashReturn","autoCompactEnabled","showTurnDuration","diffTool","env","tipsHistory","todoFeatureEnabled","showExpandedTodos","messageIdleNotifThresholdMs","awaySummaryBlurDelayMs","autoConnectIde","autoInstallIdeExtension","fileCheckpointingEnabled","terminalProgressBarEnabled","showStatusInTerminalTab","taskCompleteNotifEnabled","inputNeededNotifEnabled","agentPushNotifEnabled","respectGitignore","claudeInChromeDefaultEnabled","hasCompletedContextInChromeOnboarding","lspRecommendationDisabled","lspRecommendationNeverPlugins","lspRecommendationIgnoredCount","copyFullResponse","copyOnSelect","permissionExplainerEnabled","prStatusFooterEnabled","remoteControlAtStartup","remoteDialogSeen","lastClaudeModel","lastOpenAIModel","lastOpenRouterModel","lastModelByProvider"];export function isGlobalConfigKey(e){return GLOBAL_CONFIG_KEYS.includes(e)}export const PROJECT_CONFIG_KEYS=["allowedTools","hasTrustDialogAccepted","hasCompletedProjectOnboarding"];let B=!1;export function resetTrustDialogAcceptedCacheForTesting(){B=!1}export function checkHasTrustDialogAccepted(){return B||=function(){if(p())return!0;const e=getGlobalConfig(),t=getProjectPathForConfig(),o=e.projects?.[t];if(o?.hasTrustDialogAccepted)return!0;let n=U(h());for(;;){const t=e.projects?.[n];if(t?.hasTrustDialogAccepted)return!0;const o=U(d(n,".."));if(o===n)break;n=o}return!1}()}export function isPathTrusted(e){const t=getGlobalConfig();let o=U(d(e));for(;;){if(t.projects?.[o]?.hasTrustDialogAccepted)return!0;const e=U(d(o,".."));if(e===o)return!1;o=e}}const $={...DEFAULT_GLOBAL_CONFIG,autoUpdates:!1},H={...R};export function isProjectConfigKey(e){return PROJECT_CONFIG_KEYS.includes(e)}function wouldLoseAuthState(e){const t=K.config;if(!t)return!1;const o=void 0!==t.oauthAccount&&void 0===e.oauthAccount,n=!0===t.hasCompletedOnboarding&&!0!==e.hasCompletedOnboarding;return o||n}export function saveGlobalConfig(e){if("test"===process.env.NODE_ENV){const t=e($);if(t===$)return;return void Object.assign($,t)}let t=null;try{saveConfigWithLock(v(),createDefaultGlobalConfig,o=>{const n=e(o);return n===o?o:(t={...n,projects:removeProjectHistory(o.projects)},t)})&&t&&writeThroughGlobalConfigCache(t)}catch(o){b(`Failed to save config with lock: ${o}`,{level:"error"});const n=getConfig(v(),createDefaultGlobalConfig);if(wouldLoseAuthState(n))return b("saveGlobalConfig fallback: re-read config is missing auth that cache has; refusing to write. See GH #3117.",{level:"error"}),void m("tengu_config_auth_loss_prevented",{});const r=e(n);if(r===n)return;t={...r,projects:removeProjectHistory(n.projects)},saveConfig(v(),t,DEFAULT_GLOBAL_CONFIG),writeThroughGlobalConfigCache(t)}}let K={config:null,mtime:0},W=null,z=0,V=0,Y=0;export function getGlobalConfigWriteCount(){return Y}export const CONFIG_WRITE_DISPLAY_THRESHOLD=20;function migrateConfigFields(e){if(void 0!==e.installMethod)return e;const t=e;let o="unknown",n=e.autoUpdates??!0;switch(t.autoUpdaterStatus){case"migrated":o="local";break;case"installed":o="native";break;case"disabled":n=!1;break;case"enabled":case"no_permissions":case"not_configured":o="global"}return{...e,installMethod:o,autoUpdates:n}}function removeProjectHistory(e){if(!e)return e;const t={};let o=!1;for(const[n,r]of Object.entries(e)){const e=r;if(void 0!==e.history){o=!0;const{history:r,...s}=e;t[n]=s}else t[n]=r}return o?t:e}C(async()=>{!function(){const e=z+V;e>0&&m("tengu_config_cache_stats",{cache_hits:z,cache_misses:V,hit_rate:z/e}),z=0,V=0}()});const q=1e3;let Q=!1;function writeThroughGlobalConfigCache(e){K={config:e,mtime:Date.now()},W=null}export function getGlobalConfig(){if("test"===process.env.NODE_ENV)return $;if(K.config)return z++,K.config;V++;try{let e=null;try{e=w().statSync(v())}catch{}const t=migrateConfigFields(getConfig(v(),createDefaultGlobalConfig));return K={config:t,mtime:e?.mtimeMs??Date.now()},W=e?{mtime:e.mtimeMs,size:e.size}:null,function(){if(Q||"test"===process.env.NODE_ENV)return;Q=!0;const e=v();s(e,{interval:q,persistent:!1},t=>{t.mtimeMs<=K.mtime||w().readFile(e,{encoding:"utf-8"}).then(e=>{if(t.mtimeMs<=K.mtime)return;const o=j(A(e));null!==o&&"object"==typeof o&&(K={config:migrateConfigFields({numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1,...o}),mtime:t.mtimeMs},W={mtime:t.mtimeMs,size:t.size})}).catch(()=>{})}),C(async()=>{r(e),Q=!1})}(),t}catch{return migrateConfigFields(getConfig(v(),createDefaultGlobalConfig))}}export function getRemoteControlAtStartup(){const t=getGlobalConfig().remoteControlAtStartup;return void 0!==t?t:!(!e("CCR_AUTO_CONNECT")||!x?.getCcrAutoConnectDefault())}export function getCustomApiKeyStatus(e){const t=getGlobalConfig();return t.customApiKeyResponses?.approved?.includes(e)?"approved":t.customApiKeyResponses?.rejected?.includes(e)?"rejected":"new"}function saveConfig(e,t,o){const n=l(e);w().mkdirSync(n);const r=a(t,(e,t)=>L(e)!==L(o[t]));_(e,L(r,null,2),{encoding:"utf-8",mode:384}),e===v()&&Y++}function saveConfigWithLock(e,t,o){const n=t(),r=l(e),s=w();let i;s.mkdirSync(r);try{const r=`${e}.lock`,l=Date.now();i=G.lockSync(e,{lockfilePath:r,onCompromised:e=>{b(`Config lock compromised: ${e}`,{level:"error"})}});const d=Date.now()-l;if(d>100&&(b("Lock acquisition took longer than expected - another Claude instance may be running"),m("tengu_config_lock_contention",{lock_time_ms:d})),W&&e===v())try{const t=s.statSync(e);t.mtimeMs===W.mtime&&t.size===W.size||m("tengu_config_stale_write",{read_mtime:W.mtime,write_mtime:t.mtimeMs,read_size:W.size,write_size:t.size})}catch(e){if("ENOENT"!==D(e))throw e}const f=getConfig(e,t);if(e===v()&&wouldLoseAuthState(f))return b("saveConfigWithLock: re-read config is missing auth that cache has; refusing to write to avoid wiping ~/.context.json. See GH #3117.",{level:"error"}),m("tengu_config_auth_loss_prevented",{}),!1;const p=o(f);if(p===f)return!1;const g=a(p,(e,t)=>L(e)!==L(n[t]));try{const t=c(e),o=getConfigBackupDir();try{s.mkdirSync(o)}catch(e){if("EEXIST"!==D(e))throw e}const n=6e4,r=s.readdirStringSync(o).filter(e=>e.startsWith(`${t}.backup.`)).sort().reverse(),i=r[0],a=i?Number(i.split(".backup.").pop()):0,l=Number.isNaN(a)||Date.now()-a>=n;if(l){const n=u(o,`${t}.backup.${Date.now()}`);s.copyFileSync(e,n)}const d=5,f=l?s.readdirStringSync(o).filter(e=>e.startsWith(`${t}.backup.`)).sort().reverse():r;for(const e of f.slice(d))try{s.unlinkSync(u(o,e))}catch{}}catch(e){"ENOENT"!==D(e)&&b(`Failed to backup config: ${e}`,{level:"error"})}return _(e,L(g,null,2),{encoding:"utf-8",mode:384}),e===v()&&Y++,!0}finally{i&&i()}}let J=!1;export function enableConfigs(){if(J)return;const e=Date.now();y("info","enable_configs_started"),J=!0,getConfig(v(),createDefaultGlobalConfig,!0),y("info","enable_configs_completed",{duration_ms:Date.now()-e})}function getConfigBackupDir(){return u(E(),"backups")}function findMostRecentBackup(e){const t=w(),o=c(e),n=getConfigBackupDir();try{const e=t.readdirStringSync(n).filter(e=>e.startsWith(`${o}.backup.`)).sort().at(-1);if(e)return u(n,e)}catch{}const r=l(e);try{const n=t.readdirStringSync(r).filter(e=>e.startsWith(`${o}.backup.`)).sort().at(-1);if(n)return u(r,n);const s=`${e}.backup`;try{return t.statSync(s),s}catch{}}catch{}return null}function getConfig(e,t,o){if(!J&&"test"!==process.env.NODE_ENV)throw new Error("Config accessed before allowed.");const n=w();try{const o=n.readFileSync(e,{encoding:"utf-8"});try{const e=I(A(o));return{...t(),...e}}catch(o){const n=o instanceof Error?o.message:String(o);throw new T(n,e,t())}}catch(r){if("ENOENT"===D(r)){const o=findMostRecentBackup(e);return o&&process.stderr.write(`\nClaude configuration file not found at: ${e}\nA backup file exists at: ${o}\nYou can manually restore it by running: cp "${o}" "${e}"\n\n`),t()}if(r instanceof T&&o)throw r;if(r instanceof T){if(b(`Config file corrupted, resetting to defaults: ${r.message}`,{level:"error"}),!P){P=!0;try{N(r);let t=!1;try{n.statSync(`${e}.backup`),t=!0}catch{}m("tengu_config_parse_error",{has_backup:t})}finally{P=!1}}process.stderr.write(`\nClaude configuration file at ${e} is corrupted: ${r.message}\n`);const t=c(e),o=getConfigBackupDir();try{n.mkdirSync(o)}catch(e){if("EEXIST"!==D(e))throw e}const s=n.readdirStringSync(o).filter(e=>e.startsWith(`${t}.corrupted.`));let i,a=!1;const l=n.readFileSync(e,{encoding:"utf-8"});for(const e of s)try{if(l===n.readFileSync(u(o,e),{encoding:"utf-8"})){a=!0;break}}catch{}if(!a){i=u(o,`${t}.corrupted.${Date.now()}`);try{n.copyFileSync(e,i),b(`Corrupted config backed up to: ${i}`,{level:"error"})}catch{}}const d=findMostRecentBackup(e);i?process.stderr.write(`The corrupted file has been backed up to: ${i}\n`):a&&process.stderr.write("The corrupted file has already been backed up.\n"),d?process.stderr.write(`A backup file exists at: ${d}\nYou can manually restore it by running: cp "${d}" "${e}"\n\n`):process.stderr.write("\n")}return t()}}export const getProjectPathForConfig=i(()=>{const e=f(),t=k(e);return U(t||d(e))});export function getCurrentProjectConfig(){if("test"===process.env.NODE_ENV)return H;const e=getProjectPathForConfig(),t=getGlobalConfig();if(!t.projects)return R;const o=t.projects[e]??R;return"string"==typeof o.allowedTools&&(o.allowedTools=j(o.allowedTools)??[]),o}export function saveCurrentProjectConfig(e){if("test"===process.env.NODE_ENV){const t=e(H);if(t===H)return;return void Object.assign(H,t)}const t=getProjectPathForConfig();let o=null;try{saveConfigWithLock(v(),createDefaultGlobalConfig,n=>{const r=n.projects?.[t]??R,s=e(r);return s===r?n:(o={...n,projects:{...n.projects,[t]:s}},o)})&&o&&writeThroughGlobalConfigCache(o)}catch(n){b(`Failed to save config with lock: ${n}`,{level:"error"});const r=getConfig(v(),createDefaultGlobalConfig);if(wouldLoseAuthState(r))return b("saveCurrentProjectConfig fallback: re-read config is missing auth that cache has; refusing to write. See GH #3117.",{level:"error"}),void m("tengu_config_auth_loss_prevented",{});const s=r.projects?.[t]??R,i=e(s);if(i===s)return;o={...r,projects:{...r.projects,[t]:i}},saveConfig(v(),o,DEFAULT_GLOBAL_CONFIG),writeThroughGlobalConfigCache(o)}}export function isAutoUpdaterDisabled(){return null!==getAutoUpdaterDisabledReason()}export function shouldSkipPluginAutoupdate(){return isAutoUpdaterDisabled()&&!S(process.env.FORCE_AUTOUPDATE_PLUGINS)}export function formatAutoUpdaterDisabledReason(e){switch(e.type){case"development":return"development build";case"env":return`${e.envVar} set`;case"config":return"config"}}export function getAutoUpdaterDisabledReason(){if("development"===process.env.NODE_ENV)return{type:"development"};if(S(process.env.DISABLE_AUTOUPDATER))return{type:"env",envVar:"DISABLE_AUTOUPDATER"};const e=O();if(e)return{type:"env",envVar:e};const t=getGlobalConfig();return!1!==t.autoUpdates||"native"===t.installMethod&&!0===t.autoUpdatesProtectedForNative?null:{type:"config"}}export function getOrCreateUserID(){const e=getGlobalConfig();if(e.userID)return e.userID;const t=n(32).toString("hex");return saveGlobalConfig(e=>({...e,userID:t})),t}export function recordFirstStartTime(){if(!getGlobalConfig().firstStartTime){const e=(new Date).toISOString();saveGlobalConfig(t=>({...t,firstStartTime:t.firstStartTime??e}))}}export function getMemoryPath(t){const o=f();switch(t){case"User":return u(E(),"CLAUDE.md");case"Local":return u(o,"CLAUDE.local.md");case"Project":return u(o,"CLAUDE.md");case"Managed":return u(F(),"CLAUDE.md");case"AutoMem":return g()}return e("TEAMMEM")?M.getTeamMemEntrypoint():""}export function getManagedClaudeRulesDir(){return u(F(),".claude","rules")}export function getUserClaudeRulesDir(){return u(E(),"rules")}export const _getConfigForTesting=getConfig;export const _wouldLoseAuthStateForTesting=wouldLoseAuthState;export function _setGlobalConfigCacheForTesting(e){K.config=e,K.mtime=e?Date.now():0}
1
+ import{feature as e}from"../recovery/bunBundleShim.js";import{createRequire as t}from"module";const o=t(import.meta.url);import{randomBytes as r}from"crypto";import{unwatchFile as n,watchFile as s}from"fs";import i from"lodash-es/memoize.js";import a from"lodash-es/pickBy.js";import{basename as c,dirname as l,join as u,resolve as d}from"path";import{getOriginalCwd as f,getSessionTrustAccepted as p}from"../bootstrap/state.js";import{getAutoMemEntrypoint as g}from"../memdir/paths.js";import{logEvent as m}from"../services/analytics/index.js";import{getCwd as h}from"./cwd.js";import{registerCleanup as C}from"./cleanupRegistry.js";import{logForDebugging as b}from"./debug.js";import{logForDiagnosticsNoPII as y}from"./diagLogs.js";import{getGlobalClaudeFile as v}from"./env.js";import{getClaudeConfigHomeDir as E,isEnvTruthy as S}from"./envUtils.js";import{ConfigParseError as T,getErrnoCode as D}from"./errors.js";import{writeFileSyncAndFlush_DEPRECATED as _}from"./file.js";import{getFsImplementation as w}from"./fsOperations.js";import{findCanonicalGitRoot as k}from"./git.js";import{safeParseJSON as j}from"./json.js";import{stripBOM as A}from"./jsonRead.js";import*as G from"./lockfile.js";import{logError as M}from"./log.js";import{normalizePathForConfigKey as N}from"./path.js";import{getEssentialTrafficOnlyReason as U}from"./privacyLevel.js";import{getManagedFilePath as O}from"./settings/managedPath.js";const x=e("TEAMMEM")?o("../memdir/teamMemPaths.js"):null,F=e("CCR_AUTO_CONNECT")?o("../bridge/bridgeEnabled.js"):null;import{jsonParse as I,jsonStringify as P}from"./slowOperations.js";let L=!1;const R={allowedTools:[],mcpContextUris:[],mcpServers:{},enabledMcpjsonServers:[],disabledMcpjsonServers:[],hasTrustDialogAccepted:!1,projectOnboardingSeenCount:0,hasClaudeMdExternalIncludesApproved:!1,hasClaudeMdExternalIncludesWarningShown:!1};export{EDITOR_MODES,NOTIFICATION_CHANNELS}from"./configConstants.js";function createDefaultGlobalConfig(){return{numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1}}export const DEFAULT_GLOBAL_CONFIG={numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1};export const GLOBAL_CONFIG_KEYS=["apiKeyHelper","installMethod","autoUpdates","autoUpdatesProtectedForNative","theme","verbose","preferredNotifChannel","shiftEnterKeyBindingInstalled","editorMode","hasUsedBackslashReturn","autoCompactEnabled","showTurnDuration","diffTool","env","tipsHistory","todoFeatureEnabled","showExpandedTodos","messageIdleNotifThresholdMs","awaySummaryBlurDelayMs","autoConnectIde","autoInstallIdeExtension","fileCheckpointingEnabled","terminalProgressBarEnabled","showStatusInTerminalTab","taskCompleteNotifEnabled","inputNeededNotifEnabled","agentPushNotifEnabled","respectGitignore","claudeInChromeDefaultEnabled","hasCompletedContextInChromeOnboarding","lspRecommendationDisabled","lspRecommendationNeverPlugins","lspRecommendationIgnoredCount","copyFullResponse","copyOnSelect","permissionExplainerEnabled","prStatusFooterEnabled","remoteControlAtStartup","remoteDialogSeen","lastClaudeModel","lastOpenAIModel","lastOpenRouterModel","lastModelByProvider"];export function isGlobalConfigKey(e){return GLOBAL_CONFIG_KEYS.includes(e)}export const PROJECT_CONFIG_KEYS=["allowedTools","hasTrustDialogAccepted","hasCompletedProjectOnboarding"];let B=!1;export function resetTrustDialogAcceptedCacheForTesting(){B=!1}export function checkHasTrustDialogAccepted(){return B||=function(){if(p())return!0;const e=getGlobalConfig(),t=getProjectPathForConfig(),o=e.projects?.[t];if(o?.hasTrustDialogAccepted)return!0;let r=N(h());for(;;){const t=e.projects?.[r];if(t?.hasTrustDialogAccepted)return!0;const o=N(d(r,".."));if(o===r)break;r=o}return!1}()}export function isPathTrusted(e){const t=getGlobalConfig();let o=N(d(e));for(;;){if(t.projects?.[o]?.hasTrustDialogAccepted)return!0;const e=N(d(o,".."));if(e===o)return!1;o=e}}const $={...DEFAULT_GLOBAL_CONFIG,autoUpdates:!1},H={...R};export function isProjectConfigKey(e){return PROJECT_CONFIG_KEYS.includes(e)}function wouldLoseAuthState(e){const t=K.config;if(!t)return!1;const o=void 0!==t.oauthAccount&&void 0===e.oauthAccount,r=!0===t.hasCompletedOnboarding&&!0!==e.hasCompletedOnboarding;return o||r}export function saveGlobalConfig(e){if("test"===process.env.NODE_ENV){const t=e($);if(t===$)return;return void Object.assign($,t)}let t=null;try{saveConfigWithLock(v(),createDefaultGlobalConfig,o=>{const r=e(o);return r===o?o:(t={...r,projects:removeProjectHistory(o.projects)},t)})&&t&&writeThroughGlobalConfigCache(t)}catch(o){b(`Failed to save config with lock: ${o}`,{level:"error"});const r=getConfig(v(),createDefaultGlobalConfig);if(wouldLoseAuthState(r))return b("saveGlobalConfig fallback: re-read config is missing auth that cache has; refusing to write. See GH #3117.",{level:"error"}),void m("tengu_config_auth_loss_prevented",{});const n=e(r);if(n===r)return;t={...n,projects:removeProjectHistory(r.projects)},saveConfig(v(),t,DEFAULT_GLOBAL_CONFIG),writeThroughGlobalConfigCache(t)}}let K={config:null,mtime:0},W=null,z=0,V=0,Y=0;export function getGlobalConfigWriteCount(){return Y}export const CONFIG_WRITE_DISPLAY_THRESHOLD=20;function migrateConfigFields(e){if(void 0!==e.installMethod)return e;const t=e;let o="unknown",r=e.autoUpdates??!0;switch(t.autoUpdaterStatus){case"migrated":o="local";break;case"installed":o="native";break;case"disabled":r=!1;break;case"enabled":case"no_permissions":case"not_configured":o="global"}return{...e,installMethod:o,autoUpdates:r}}function removeProjectHistory(e){if(!e)return e;const t={};let o=!1;for(const[r,n]of Object.entries(e)){const e=n;if(void 0!==e.history){o=!0;const{history:n,...s}=e;t[r]=s}else t[r]=n}return o?t:e}C(async()=>{!function(){const e=z+V;e>0&&m("tengu_config_cache_stats",{cache_hits:z,cache_misses:V,hit_rate:z/e}),z=0,V=0}()});const q=1e3;let Q=!1;function writeThroughGlobalConfigCache(e){K={config:e,mtime:Date.now()},W=null}export function getGlobalConfig(){if("test"===process.env.NODE_ENV)return $;if(K.config)return z++,K.config;V++;try{let e=null;try{e=w().statSync(v())}catch{}const t=migrateConfigFields(getConfig(v(),createDefaultGlobalConfig));return K={config:t,mtime:e?.mtimeMs??Date.now()},W=e?{mtime:e.mtimeMs,size:e.size}:null,function(){if(Q||"test"===process.env.NODE_ENV)return;Q=!0;const e=v();s(e,{interval:q,persistent:!1},t=>{t.mtimeMs<=K.mtime||w().readFile(e,{encoding:"utf-8"}).then(e=>{if(t.mtimeMs<=K.mtime)return;const o=j(A(e));null!==o&&"object"==typeof o&&(K={config:migrateConfigFields({numStartups:0,installMethod:void 0,autoUpdates:void 0,theme:"dark",preferredNotifChannel:"auto",verbose:!1,editorMode:"normal",autoCompactEnabled:!0,showTurnDuration:!0,hasSeenTasksHint:!1,hasUsedStash:!1,hasUsedBackgroundTask:!1,queuedCommandUpHintCount:0,diffTool:"auto",customApiKeyResponses:{approved:[],rejected:[]},env:{},tipsHistory:{},memoryUsageCount:0,promptQueueUseCount:0,btwUseCount:0,todoFeatureEnabled:!0,showExpandedTodos:!1,messageIdleNotifThresholdMs:6e4,awaySummaryBlurDelayMs:3e5,autoConnectIde:!1,autoInstallIdeExtension:!0,fileCheckpointingEnabled:!0,terminalProgressBarEnabled:!0,cachedStatsigGates:{},cachedDynamicConfigs:{},cachedGrowthBookFeatures:{},respectGitignore:!0,copyFullResponse:!1,...o}),mtime:t.mtimeMs},W={mtime:t.mtimeMs,size:t.size})}).catch(()=>{})}),C(async()=>{n(e),Q=!1})}(),t}catch{return migrateConfigFields(getConfig(v(),createDefaultGlobalConfig))}}export function getRemoteControlAtStartup(){const t=getGlobalConfig().remoteControlAtStartup;return void 0!==t?t:!(!e("CCR_AUTO_CONNECT")||!F?.getCcrAutoConnectDefault())}export function getCustomApiKeyStatus(e){const t=getGlobalConfig();return t.customApiKeyResponses?.approved?.includes(e)?"approved":t.customApiKeyResponses?.rejected?.includes(e)?"rejected":"new"}function saveConfig(e,t,o){const r=l(e);w().mkdirSync(r);const n=a(t,(e,t)=>P(e)!==P(o[t]));_(e,P(n,null,2),{encoding:"utf-8",mode:384}),e===v()&&Y++}function saveConfigWithLock(e,t,o){const r=t(),n=l(e),s=w();let i;s.mkdirSync(n);try{const n=`${e}.lock`,l=Date.now();i=G.lockSync(e,{lockfilePath:n,onCompromised:e=>{b(`Config lock compromised: ${e}`,{level:"error"})}});const d=Date.now()-l;if(d>100&&(b("Lock acquisition took longer than expected - another Claude instance may be running"),m("tengu_config_lock_contention",{lock_time_ms:d})),W&&e===v())try{const t=s.statSync(e);t.mtimeMs===W.mtime&&t.size===W.size||m("tengu_config_stale_write",{read_mtime:W.mtime,write_mtime:t.mtimeMs,read_size:W.size,write_size:t.size})}catch(e){if("ENOENT"!==D(e))throw e}const f=getConfig(e,t);if(e===v()&&wouldLoseAuthState(f))return b("saveConfigWithLock: re-read config is missing auth that cache has; refusing to write to avoid wiping ~/.context.json. See GH #3117.",{level:"error"}),m("tengu_config_auth_loss_prevented",{}),!1;const p=o(f);if(p===f)return!1;const g=a(p,(e,t)=>P(e)!==P(r[t]));try{const t=c(e),o=getConfigBackupDir();try{s.mkdirSync(o)}catch(e){if("EEXIST"!==D(e))throw e}const r=6e4,n=s.readdirStringSync(o).filter(e=>e.startsWith(`${t}.backup.`)).sort().reverse(),i=n[0],a=i?Number(i.split(".backup.").pop()):0,l=Number.isNaN(a)||Date.now()-a>=r;if(l){const r=u(o,`${t}.backup.${Date.now()}`);s.copyFileSync(e,r)}const d=5,f=l?s.readdirStringSync(o).filter(e=>e.startsWith(`${t}.backup.`)).sort().reverse():n;for(const e of f.slice(d))try{s.unlinkSync(u(o,e))}catch{}}catch(e){"ENOENT"!==D(e)&&b(`Failed to backup config: ${e}`,{level:"error"})}return _(e,P(g,null,2),{encoding:"utf-8",mode:384}),e===v()&&Y++,!0}finally{i&&i()}}let J=!1;export function enableConfigs(){if(J)return;const e=Date.now();y("info","enable_configs_started"),J=!0,getConfig(v(),createDefaultGlobalConfig,!0),y("info","enable_configs_completed",{duration_ms:Date.now()-e})}function getConfigBackupDir(){return u(E(),"backups")}function findMostRecentBackup(e){const t=w(),o=c(e),r=getConfigBackupDir();try{const e=t.readdirStringSync(r).filter(e=>e.startsWith(`${o}.backup.`)).sort().at(-1);if(e)return u(r,e)}catch{}const n=l(e);try{const r=t.readdirStringSync(n).filter(e=>e.startsWith(`${o}.backup.`)).sort().at(-1);if(r)return u(n,r);const s=`${e}.backup`;try{return t.statSync(s),s}catch{}}catch{}return null}function getConfig(e,t,o){if(!J&&"test"!==process.env.NODE_ENV)throw new Error("Config accessed before allowed.");const r=w();try{const o=r.readFileSync(e,{encoding:"utf-8"});try{const e=I(A(o));return{...t(),...e}}catch(o){const r=o instanceof Error?o.message:String(o);throw new T(r,e,t())}}catch(n){if("ENOENT"===D(n)){const o=findMostRecentBackup(e);return o&&process.stderr.write(`\nClaude configuration file not found at: ${e}\nA backup file exists at: ${o}\nYou can manually restore it by running: cp "${o}" "${e}"\n\n`),t()}if(n instanceof T&&o)throw n;if(n instanceof T){if(b(`Config file corrupted, resetting to defaults: ${n.message}`,{level:"error"}),!L){L=!0;try{M(n);let t=!1;try{r.statSync(`${e}.backup`),t=!0}catch{}m("tengu_config_parse_error",{has_backup:t})}finally{L=!1}}process.stderr.write(`\nClaude configuration file at ${e} is corrupted: ${n.message}\n`);const t=c(e),o=getConfigBackupDir();try{r.mkdirSync(o)}catch(e){if("EEXIST"!==D(e))throw e}const s=r.readdirStringSync(o).filter(e=>e.startsWith(`${t}.corrupted.`));let i,a=!1;const l=r.readFileSync(e,{encoding:"utf-8"});for(const e of s)try{if(l===r.readFileSync(u(o,e),{encoding:"utf-8"})){a=!0;break}}catch{}if(!a){i=u(o,`${t}.corrupted.${Date.now()}`);try{r.copyFileSync(e,i),b(`Corrupted config backed up to: ${i}`,{level:"error"})}catch{}}const d=findMostRecentBackup(e);i?process.stderr.write(`The corrupted file has been backed up to: ${i}\n`):a&&process.stderr.write("The corrupted file has already been backed up.\n"),d?process.stderr.write(`A backup file exists at: ${d}\nYou can manually restore it by running: cp "${d}" "${e}"\n\n`):process.stderr.write("\n")}return t()}}export const getProjectPathForConfig=i(()=>{const e=f(),t=k(e);return N(t||d(e))});export function getCurrentProjectConfig(){if("test"===process.env.NODE_ENV)return H;const e=getProjectPathForConfig(),t=getGlobalConfig();if(!t.projects)return R;const o=t.projects[e]??R;return"string"==typeof o.allowedTools&&(o.allowedTools=j(o.allowedTools)??[]),o}export function saveCurrentProjectConfig(e){if("test"===process.env.NODE_ENV){const t=e(H);if(t===H)return;return void Object.assign(H,t)}const t=getProjectPathForConfig();let o=null;try{saveConfigWithLock(v(),createDefaultGlobalConfig,r=>{const n=r.projects?.[t]??R,s=e(n);return s===n?r:(o={...r,projects:{...r.projects,[t]:s}},o)})&&o&&writeThroughGlobalConfigCache(o)}catch(r){b(`Failed to save config with lock: ${r}`,{level:"error"});const n=getConfig(v(),createDefaultGlobalConfig);if(wouldLoseAuthState(n))return b("saveCurrentProjectConfig fallback: re-read config is missing auth that cache has; refusing to write. See GH #3117.",{level:"error"}),void m("tengu_config_auth_loss_prevented",{});const s=n.projects?.[t]??R,i=e(s);if(i===s)return;o={...n,projects:{...n.projects,[t]:i}},saveConfig(v(),o,DEFAULT_GLOBAL_CONFIG),writeThroughGlobalConfigCache(o)}}export function isAutoUpdaterDisabled(){return null!==getAutoUpdaterDisabledReason()}export function shouldSkipPluginAutoupdate(){return isAutoUpdaterDisabled()&&!S(process.env.FORCE_AUTOUPDATE_PLUGINS)}export function formatAutoUpdaterDisabledReason(e){switch(e.type){case"development":return"development build";case"env":return`${e.envVar} set`;case"config":return"config"}}export function getAutoUpdaterDisabledReason(){if("development"===process.env.NODE_ENV)return{type:"development"};if(S(process.env.DISABLE_AUTOUPDATER))return{type:"env",envVar:"DISABLE_AUTOUPDATER"};const e=U();if(e)return{type:"env",envVar:e};const t=getGlobalConfig();return!1!==t.autoUpdates||"native"===t.installMethod&&!0===t.autoUpdatesProtectedForNative?null:{type:"config"}}export function getOrCreateUserID(){const e=getGlobalConfig();if(e.userID)return e.userID;const t=r(32).toString("hex");return saveGlobalConfig(e=>({...e,userID:t})),t}export function recordFirstStartTime(){if(!getGlobalConfig().firstStartTime){const e=(new Date).toISOString();saveGlobalConfig(t=>({...t,firstStartTime:t.firstStartTime??e}))}}export function getMemoryPath(t){const o=f();switch(t){case"User":return u(E(),"CLAUDE.md");case"Local":return u(o,"CLAUDE.local.md");case"Project":return u(o,"CLAUDE.md");case"Managed":return u(O(),"CLAUDE.md");case"AutoMem":return g()}return e("TEAMMEM")?x.getTeamMemEntrypoint():""}export function getManagedClaudeRulesDir(){return u(O(),".claude","rules")}export function getUserClaudeRulesDir(){return u(E(),"rules")}function customProviderModelsCacheKey(e,t){return t&&t.trim()?t:e}export function setCustomProviderModels(e,t,o){const r=getGlobalConfig(),n={...r.customProviderModelsCache??{}};n[customProviderModelsCacheKey(e,o)]=t,saveGlobalConfig({...r,customProviderModelsCache:n})}export function getCustomProviderModels(e,t){const o=getGlobalConfig().customProviderModelsCache;if(!o)return[];const r=o[customProviderModelsCacheKey(e,t)];return r&&r.length>0?r:o[e]??[]}export const _getConfigForTesting=getConfig;export const _wouldLoseAuthStateForTesting=wouldLoseAuthState;export function _setGlobalConfigCacheForTesting(e){K.config=e,K.mtime=e?Date.now():0}
@@ -1 +1 @@
1
- import{getInitialMainLoopModel as e}from"../../bootstrap/state.js";import{isClaudeAISubscriber as o,isMaxSubscriber as t,isTeamPremiumSubscriber as i}from"../auth.js";import{getModelStrings as n}from"./modelStrings.js";import{COST_TIER_3_15 as s,COST_HAIKU_35 as r,COST_HAIKU_45 as l,formatModelPricing as p}from"../modelCost.js";import{getSettings_DEPRECATED as a}from"../settings/settings.js";import{checkOpus1mAccess as u,checkSonnet1mAccess as d}from"./check1mAccess.js";import{getAPIProvider as c}from"./providers.js";import{isModelAllowed as O}from"./modelAllowlist.js";import{getCanonicalName as m,getClaudeAiUserDefaultModelDescription as g,getDefaultOpenAIModel as f,getDefaultOpenAIFastModel as M,getDefaultGeminiModel as v,getDefaultGeminiFastModel as h,getDefaultSonnetModel as x,getDefaultOpusModel as _,getDefaultHaikuModel as b,getDefaultMainLoopModelSetting as P,getMarketingNameForModel as F,getUserSpecifiedModelSetting as T,isOpus1mMergeEnabled as w,getOpus46PricingSuffix as D,isOpenAIProvider as S,isGeminiProvider as C,renderDefaultModelSetting as E}from"./model.js";import{getAntModels as A}from"./antModels.js";import{has1mContext as N}from"../context.js";import{getGlobalConfig as y}from"../config.js";export function getDefaultOptionForUser(e=!1){if("ant"===process.env.USER_TYPE){const e=E(P());return{value:null,label:"Default (recommended)",description:`Use the default model for Ants (currently ${e})`,descriptionForModel:`Default model (currently ${e})`}}if(S())return{value:null,label:"Predeterminado (recomendado)",description:`Usa el modelo predeterminado (actualmente ${E(P())})`};if(o())return{value:null,label:"Default (recommended)",description:g(e)};const t="firstParty"!==c();return{value:null,label:"Default (recommended)",description:`Use the default model (currently ${E(P())})${t?"":` · ${p(s)}`}`}}function getSonnet46Option(){const e="firstParty"!==c();return{value:e?n().sonnet46:"sonnet",label:"Sonnet",description:"Sonnet 4.6 · Best for everyday tasks"+(e?"":` · ${p(s)}`),descriptionForModel:"Sonnet 4.6 - best for everyday tasks. Generally recommended for most coding tasks"}}function getOpus47Option(e=!1){c();return{value:n().opus47,label:"Opus",description:`Opus 4.7 · Most capable for complex work${D(e)}`,descriptionForModel:"Opus 4.7 - most capable for complex work"}}function getOpus46Option(e=!1){return{value:"firstParty"!==c()?n().opus46:"opus",label:"Opus 4.6",description:`Opus 4.6 · Previous generation${D(e)}`,descriptionForModel:"Opus 4.6 - previous generation"}}export function getSonnet46_1MOption(){const e="firstParty"!==c();return{value:e?n().sonnet46+"[1m]":"sonnet[1m]",label:"Sonnet (1M context)",description:"Sonnet 4.6 for long sessions"+(e?"":` · ${p(s)}`),descriptionForModel:"Sonnet 4.6 with 1M context window - for long sessions with large codebases"}}export function getOpus47_1MOption(e=!1){c();return{value:n().opus47+"[1m]",label:"Opus 4.7 (1M context)",description:`Opus 4.7 for long sessions${D(e)}`,descriptionForModel:"Opus 4.7 with 1M context window - for long sessions with large codebases"}}export function getOpus46_1MOption(e=!1){return{value:"firstParty"!==c()?n().opus46+"[1m]":"opus[1m]",label:"Opus 4.6 (1M context)",description:`Opus 4.6 for long sessions${D(e)}`,descriptionForModel:"Opus 4.6 with 1M context window - for long sessions with large codebases"}}function getHaiku45Option(){return{value:"haiku",label:"Haiku",description:"Haiku 4.5 · Fastest for quick answers"+("firstParty"!==c()?"":` · ${p(l)}`),descriptionForModel:"Haiku 4.5 - fastest for quick answers. Lower cost but less capable than Sonnet 4.6."}}function getHaikuOption(){return b()===n().haiku45?getHaiku45Option():{value:"haiku",label:"Haiku",description:"Haiku 3.5 for simple tasks"+("firstParty"!==c()?"":` · ${p(r)}`),descriptionForModel:"Haiku 3.5 - faster and lower cost, but less capable than Sonnet. Use for simple tasks."}}function getMaxOpus47Option(e=!1){return{value:n().opus47,label:"Opus",description:`Opus 4.7 · Most capable for complex work${e?D(!0):""}`}}function getMaxOpusOption(e=!1){return{value:"opus",label:"Opus 4.6",description:`Opus 4.6 · Previous generation${e?D(!0):""}`}}export function getMaxSonnet46_1MOption(){const e="firstParty"!==c();return{value:"sonnet[1m]",label:"Sonnet (1M context)",description:`Sonnet 4.6 with 1M context${o()?" · Billed as extra usage":""}${e?"":` · ${p(s)}`}`}}export function getMaxOpus47_1MOption(e=!1){const t=o()?" · Billed as extra usage":"";return{value:n().opus47+"[1m]",label:"Opus 4.7 (1M context)",description:`Opus 4.7 with 1M context${t}${D(e)}`}}export function getMaxOpus46_1MOption(e=!1){return{value:"opus[1m]",label:"Opus 4.6 (1M context)",description:`Opus 4.6 with 1M context${o()?" · Billed as extra usage":""}${D(e)}`}}function getMergedOpus1MOption(e=!1){const o="firstParty"!==c();return{value:n().opus47+"[1m]",label:"Opus (1M context)",description:`Opus 4.7 with 1M context · Most capable for complex work${!o&&e?D(e):""}`,descriptionForModel:"Opus 4.7 with 1M context - most capable for complex work"}}const k={value:"sonnet",label:"Sonnet",description:"Sonnet 4.6 · Best for everyday tasks"},U={value:"haiku",label:"Haiku",description:"Haiku 4.5 · Fastest for quick answers"};function getModelOptionsBase(e=!1){if("ant"===process.env.USER_TYPE){const o=A().map(e=>({value:e.alias,label:e.label,description:e.description??`[ANT-ONLY] ${e.label} (${e.model})`}));return[getDefaultOptionForUser(),...o,getMergedOpus1MOption(e),getSonnet46Option(),getSonnet46_1MOption(),getHaiku45Option()]}if("openai"===c())return[getDefaultOptionForUser(e),{value:"gpt-5.5",label:"GPT-5.5",description:"gpt-5.5 - Modelo flagship para razonamiento, coding y agentes",descriptionForModel:"gpt-5.5 - flagship model for complex reasoning, coding, and agentic work"},{value:"gpt-5.5-pro",label:"GPT-5.5 Pro",description:"gpt-5.5-pro - Mayor precision para tareas dificiles",descriptionForModel:"gpt-5.5-pro - higher-accuracy model for harder tasks"},{value:"gpt-5.4",label:"GPT-5.4",description:"gpt-5.4 - Modelo principal recomendado",descriptionForModel:"gpt-5.4 - recommended flagship model"},{value:"gpt-5.2-codex",label:"GPT-5.2-Codex",description:"gpt-5.2-codex - Codex moderno para programacion",descriptionForModel:"gpt-5.2-codex - modern Codex model"},{value:"gpt-5.1-codex-max",label:"GPT-5.1-Codex-Max",description:"gpt-5.1-codex-max - Codex de maxima capacidad",descriptionForModel:"gpt-5.1-codex-max - highest-capacity Codex model"},{value:"gpt-5.4-mini",label:"GPT-5.4-Mini",description:"gpt-5.4-mini - Variante ligera y rapida",descriptionForModel:"gpt-5.4-mini - fast lightweight model"},{value:"gpt-5.3-codex",label:"GPT-5.3-Codex",description:"gpt-5.3-codex - Codex frontier anterior",descriptionForModel:"gpt-5.3-codex - previous frontier Codex model"},{value:"gpt-5.2",label:"GPT-5.2",description:"gpt-5.2 - Modelo general estable",descriptionForModel:"gpt-5.2 - stable general-purpose model"},{value:"gpt-5.1-codex-mini",label:"GPT-5.1-Codex-Mini",description:"gpt-5.1-codex-mini - Codex mini de compatibilidad",descriptionForModel:"gpt-5.1-codex-mini - compatibility Codex mini model"}];if("openrouter"===c())return[getDefaultOptionForUser(e)];if(C())return[getDefaultOptionForUser(e),{value:v(),label:"Gemini 3.5 Pro",description:"gemini-3.5-pro - Modelo Gemini principal para razonamiento, codigo y agentes",descriptionForModel:"gemini-3.5-pro - flagship Gemini model"},{value:h(),label:"Gemini 3.5 Flash",description:"gemini-3.5-flash - Variante Gemini rapida para tareas multimodales y de codigo",descriptionForModel:"gemini-3.5-flash - fast Gemini model"},{value:"gemini-3.5-flash-lite",label:"Gemini 3.5 Flash-Lite",description:"gemini-3.5-flash-lite - Variante de bajo costo y baja latencia",descriptionForModel:"gemini-3.5-flash-lite - fast low-cost Gemini model"},{value:"gemini-3.1-pro-preview",label:"Gemini 3.1 Pro Preview",description:"gemini-3.1-pro-preview - Version anterior de Pro",descriptionForModel:"gemini-3.1-pro-preview - previous Pro preview model"},{value:"gemini-3-flash-preview",label:"Gemini 3 Flash Preview",description:"gemini-3-flash-preview - Version anterior de Flash",descriptionForModel:"gemini-3-flash-preview - previous Flash preview model"},{value:"gemini-2.5-pro",label:"Gemini 2.5 Pro",description:"gemini-2.5-pro - Modelo estable para razonamiento y codigo",descriptionForModel:"gemini-2.5-pro - stable Gemini model"},{value:"gemini-2.5-flash",label:"Gemini 2.5 Flash",description:"gemini-2.5-flash - Modelo estable rapido",descriptionForModel:"gemini-2.5-flash - stable fast Gemini model"}];if("ollama"===c()||"ollama-cloud"===c()||"zai"===c()||"minimax"===c()||"deepseek"===c())return[getDefaultOptionForUser(e)];if(o()){if(t()||i()){const o=[getDefaultOptionForUser(e)];return o.push(getMaxOpus47Option(e)),!w()&&u()&&o.push(getMaxOpus47_1MOption(e)),o.push(getMaxOpusOption(e)),!w()&&u()&&o.push(getMaxOpus46_1MOption(e)),o.push(k),d()&&o.push(getMaxSonnet46_1MOption()),o.push(U),o}const o=[getDefaultOptionForUser(e)];return o.push(k),d()&&o.push(getMaxSonnet46_1MOption()),o.push(getMaxOpus47Option(e)),u()&&o.push(getMaxOpus47_1MOption(e)),o.push(getMaxOpusOption(e)),u()&&o.push(getMaxOpus46_1MOption(e)),o.push(U),o}if("firstParty"===c()){const o=[getDefaultOptionForUser(e)];return o.push(getSonnet46Option()),d()&&o.push(getSonnet46_1MOption()),o.push(getOpus47Option(e)),u()&&o.push(getOpus47_1MOption(e)),o.push(getOpus46Option(e)),u()&&o.push(getOpus46_1MOption(e)),o.push(getHaiku45Option()),o}const n=[getDefaultOptionForUser(e)],s=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_SONNET_MODEL;if(e&&o){const e=N(o);return{value:"sonnet",label:process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION??"Custom Sonnet model"+(e?" (1M context)":""),descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION??"Custom Sonnet model"+(e?" with 1M context":"")} (${o})`}}}();void 0!==s?n.push(s):(n.push(getSonnet46Option()),d()&&n.push(getSonnet46_1MOption()));const r=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_OPUS_MODEL;if(e&&o){const e=N(o);return{value:"opus",label:process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION??"Custom Opus model"+(e?" (1M context)":""),descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION??"Custom Opus model"+(e?" with 1M context":"")} (${o})`}}}();void 0!==r?n.push(r):(n.push(getOpus47Option(e)),u()&&n.push(getOpus47_1MOption(e)),n.push(getOpus46Option(e)),u()&&n.push(getOpus46_1MOption(e)),n.push({value:"opus",label:"Opus 4.1",description:"Opus 4.1 · Legacy",descriptionForModel:"Opus 4.1 - legacy version"}));const l=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL;if(e&&o)return{value:"haiku",label:process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION??"Custom Haiku model",descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION??"Custom Haiku model"} (${o})`}}();return void 0!==l?n.push(l):n.push(getHaikuOption()),n}function getKnownModelOption(e){const o=F(e);if(!o)return null;const t=function(e){const o=m(e);if(o.includes("claude-sonnet-4-6")||o.includes("claude-sonnet-4-5")||o.includes("claude-sonnet-4-")||o.includes("claude-3-7-sonnet")||o.includes("claude-3-5-sonnet")){const e=F(x());if(e)return{alias:"Sonnet",currentVersionName:e}}if(o.includes("claude-opus-4")){const e=F(_());if(e)return{alias:"Opus",currentVersionName:e}}if(o.includes("claude-haiku")||o.includes("claude-3-5-haiku")){const e=F(b());if(e)return{alias:"Haiku",currentVersionName:e}}return null}(e);return t&&o!==t.currentVersionName?{value:e,label:o,description:`Newer version available · select ${t.alias} for ${t.currentVersionName}`}:{value:e,label:o,description:e}}export function getModelOptions(o=!1){const t=getModelOptionsBase(o),i=process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;i&&!t.some(e=>e.value===i)&&t.push({value:i,label:process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME??i,description:process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION??`Custom model (${i})`});for(const e of y().additionalModelOptionsCache??[])t.some(o=>o.value===e.value)||t.push(e);let n=null;const s=T(),r=e();if(null!=s?n=s:null!==r&&(n=r),null===n||t.some(e=>e.value===n))return filterModelOptionsByAllowlist(t);if("opusplan"===n)return filterModelOptionsByAllowlist([...t,{value:"opusplan",label:"Opus Plan Mode",description:"Use Opus 4.7 in plan mode, Sonnet 4.6 otherwise"}]);if("opus"===n&&"firstParty"===c())return filterModelOptionsByAllowlist([...t,getMaxOpusOption(o)]);if("opus[1m]"===n&&"firstParty"===c())return filterModelOptionsByAllowlist([...t,getMergedOpus1MOption(o)]);{const e=getKnownModelOption(n);return e?t.push(e):t.push({value:n,label:n,description:"Custom model"}),filterModelOptionsByAllowlist(t)}}function filterModelOptionsByAllowlist(e){return(a()||{}).availableModels?e.filter(e=>null===e.value||null!==e.value&&O(e.value)):e}
1
+ import{getInitialMainLoopModel as e}from"../../bootstrap/state.js";import{isClaudeAISubscriber as o,isMaxSubscriber as t,isTeamPremiumSubscriber as i}from"../auth.js";import{getModelStrings as n}from"./modelStrings.js";import{COST_TIER_3_15 as s,COST_HAIKU_35 as r,COST_HAIKU_45 as l,formatModelPricing as p}from"../modelCost.js";import{getSettings_DEPRECATED as a}from"../settings/settings.js";import{checkOpus1mAccess as u,checkSonnet1mAccess as d}from"./check1mAccess.js";import{getAPIProvider as c}from"./providers.js";import{isModelAllowed as O}from"./modelAllowlist.js";import{getCanonicalName as m,getClaudeAiUserDefaultModelDescription as f,getDefaultOpenAIModel as g,getDefaultOpenAIFastModel as M,getDefaultGeminiModel as v,getDefaultGeminiFastModel as h,getDefaultSonnetModel as x,getDefaultOpusModel as _,getDefaultHaikuModel as b,getDefaultMainLoopModelSetting as P,getMarketingNameForModel as F,getUserSpecifiedModelSetting as T,isOpus1mMergeEnabled as w,getOpus46PricingSuffix as D,isOpenAIProvider as S,isGeminiProvider as C,renderDefaultModelSetting as E}from"./model.js";import{getAntModels as A}from"./antModels.js";import{has1mContext as N}from"../context.js";import{getCustomProviderModels as y,getGlobalConfig as k}from"../config.js";import{resolveProviderProfile as U}from"./providerProfiles.js";export function getDefaultOptionForUser(e=!1){if("ant"===process.env.USER_TYPE){const e=E(P());return{value:null,label:"Default (recommended)",description:`Use the default model for Ants (currently ${e})`,descriptionForModel:`Default model (currently ${e})`}}if(S())return{value:null,label:"Predeterminado (recomendado)",description:`Usa el modelo predeterminado (actualmente ${E(P())})`};if(o())return{value:null,label:"Default (recommended)",description:f(e)};const t="firstParty"!==c();return{value:null,label:"Default (recommended)",description:`Use the default model (currently ${E(P())})${t?"":` · ${p(s)}`}`}}function getSonnet46Option(){const e="firstParty"!==c();return{value:e?n().sonnet46:"sonnet",label:"Sonnet",description:"Sonnet 4.6 · Best for everyday tasks"+(e?"":` · ${p(s)}`),descriptionForModel:"Sonnet 4.6 - best for everyday tasks. Generally recommended for most coding tasks"}}function getOpus47Option(e=!1){c();return{value:n().opus47,label:"Opus",description:`Opus 4.7 · Most capable for complex work${D(e)}`,descriptionForModel:"Opus 4.7 - most capable for complex work"}}function getOpus46Option(e=!1){return{value:"firstParty"!==c()?n().opus46:"opus",label:"Opus 4.6",description:`Opus 4.6 · Previous generation${D(e)}`,descriptionForModel:"Opus 4.6 - previous generation"}}export function getSonnet46_1MOption(){const e="firstParty"!==c();return{value:e?n().sonnet46+"[1m]":"sonnet[1m]",label:"Sonnet (1M context)",description:"Sonnet 4.6 for long sessions"+(e?"":` · ${p(s)}`),descriptionForModel:"Sonnet 4.6 with 1M context window - for long sessions with large codebases"}}export function getOpus47_1MOption(e=!1){c();return{value:n().opus47+"[1m]",label:"Opus 4.7 (1M context)",description:`Opus 4.7 for long sessions${D(e)}`,descriptionForModel:"Opus 4.7 with 1M context window - for long sessions with large codebases"}}export function getOpus46_1MOption(e=!1){return{value:"firstParty"!==c()?n().opus46+"[1m]":"opus[1m]",label:"Opus 4.6 (1M context)",description:`Opus 4.6 for long sessions${D(e)}`,descriptionForModel:"Opus 4.6 with 1M context window - for long sessions with large codebases"}}function getHaiku45Option(){return{value:"haiku",label:"Haiku",description:"Haiku 4.5 · Fastest for quick answers"+("firstParty"!==c()?"":` · ${p(l)}`),descriptionForModel:"Haiku 4.5 - fastest for quick answers. Lower cost but less capable than Sonnet 4.6."}}function getHaikuOption(){return b()===n().haiku45?getHaiku45Option():{value:"haiku",label:"Haiku",description:"Haiku 3.5 for simple tasks"+("firstParty"!==c()?"":` · ${p(r)}`),descriptionForModel:"Haiku 3.5 - faster and lower cost, but less capable than Sonnet. Use for simple tasks."}}function getMaxOpus47Option(e=!1){return{value:n().opus47,label:"Opus",description:`Opus 4.7 · Most capable for complex work${e?D(!0):""}`}}function getMaxOpusOption(e=!1){return{value:"opus",label:"Opus 4.6",description:`Opus 4.6 · Previous generation${e?D(!0):""}`}}export function getMaxSonnet46_1MOption(){const e="firstParty"!==c();return{value:"sonnet[1m]",label:"Sonnet (1M context)",description:`Sonnet 4.6 with 1M context${o()?" · Billed as extra usage":""}${e?"":` · ${p(s)}`}`}}export function getMaxOpus47_1MOption(e=!1){const t=o()?" · Billed as extra usage":"";return{value:n().opus47+"[1m]",label:"Opus 4.7 (1M context)",description:`Opus 4.7 with 1M context${t}${D(e)}`}}export function getMaxOpus46_1MOption(e=!1){return{value:"opus[1m]",label:"Opus 4.6 (1M context)",description:`Opus 4.6 with 1M context${o()?" · Billed as extra usage":""}${D(e)}`}}function getMergedOpus1MOption(e=!1){const o="firstParty"!==c();return{value:n().opus47+"[1m]",label:"Opus (1M context)",description:`Opus 4.7 with 1M context · Most capable for complex work${!o&&e?D(e):""}`,descriptionForModel:"Opus 4.7 with 1M context - most capable for complex work"}}const H={value:"sonnet",label:"Sonnet",description:"Sonnet 4.6 · Best for everyday tasks"},I={value:"haiku",label:"Haiku",description:"Haiku 4.5 · Fastest for quick answers"};function getModelOptionsBase(e=!1){if("ant"===process.env.USER_TYPE){const o=A().map(e=>({value:e.alias,label:e.label,description:e.description??`[ANT-ONLY] ${e.label} (${e.model})`}));return[getDefaultOptionForUser(),...o,getMergedOpus1MOption(e),getSonnet46Option(),getSonnet46_1MOption(),getHaiku45Option()]}if("openai"===c())return[getDefaultOptionForUser(e),{value:"gpt-5.5",label:"GPT-5.5",description:"gpt-5.5 - Modelo flagship para razonamiento, coding y agentes",descriptionForModel:"gpt-5.5 - flagship model for complex reasoning, coding, and agentic work"},{value:"gpt-5.5-pro",label:"GPT-5.5 Pro",description:"gpt-5.5-pro - Mayor precision para tareas dificiles",descriptionForModel:"gpt-5.5-pro - higher-accuracy model for harder tasks"},{value:"gpt-5.4",label:"GPT-5.4",description:"gpt-5.4 - Modelo principal recomendado",descriptionForModel:"gpt-5.4 - recommended flagship model"},{value:"gpt-5.2-codex",label:"GPT-5.2-Codex",description:"gpt-5.2-codex - Codex moderno para programacion",descriptionForModel:"gpt-5.2-codex - modern Codex model"},{value:"gpt-5.1-codex-max",label:"GPT-5.1-Codex-Max",description:"gpt-5.1-codex-max - Codex de maxima capacidad",descriptionForModel:"gpt-5.1-codex-max - highest-capacity Codex model"},{value:"gpt-5.4-mini",label:"GPT-5.4-Mini",description:"gpt-5.4-mini - Variante ligera y rapida",descriptionForModel:"gpt-5.4-mini - fast lightweight model"},{value:"gpt-5.3-codex",label:"GPT-5.3-Codex",description:"gpt-5.3-codex - Codex frontier anterior",descriptionForModel:"gpt-5.3-codex - previous frontier Codex model"},{value:"gpt-5.2",label:"GPT-5.2",description:"gpt-5.2 - Modelo general estable",descriptionForModel:"gpt-5.2 - stable general-purpose model"},{value:"gpt-5.1-codex-mini",label:"GPT-5.1-Codex-Mini",description:"gpt-5.1-codex-mini - Codex mini de compatibilidad",descriptionForModel:"gpt-5.1-codex-mini - compatibility Codex mini model"}];if("openrouter"===c())return[getDefaultOptionForUser(e)];if(C())return[getDefaultOptionForUser(e),{value:v(),label:"Gemini 3.5 Pro",description:"gemini-3.5-pro - Modelo Gemini principal para razonamiento, codigo y agentes",descriptionForModel:"gemini-3.5-pro - flagship Gemini model"},{value:h(),label:"Gemini 3.5 Flash",description:"gemini-3.5-flash - Variante Gemini rapida para tareas multimodales y de codigo",descriptionForModel:"gemini-3.5-flash - fast Gemini model"},{value:"gemini-3.5-flash-lite",label:"Gemini 3.5 Flash-Lite",description:"gemini-3.5-flash-lite - Variante de bajo costo y baja latencia",descriptionForModel:"gemini-3.5-flash-lite - fast low-cost Gemini model"},{value:"gemini-3.1-pro-preview",label:"Gemini 3.1 Pro Preview",description:"gemini-3.1-pro-preview - Version anterior de Pro",descriptionForModel:"gemini-3.1-pro-preview - previous Pro preview model"},{value:"gemini-3-flash-preview",label:"Gemini 3 Flash Preview",description:"gemini-3-flash-preview - Version anterior de Flash",descriptionForModel:"gemini-3-flash-preview - previous Flash preview model"},{value:"gemini-2.5-pro",label:"Gemini 2.5 Pro",description:"gemini-2.5-pro - Modelo estable para razonamiento y codigo",descriptionForModel:"gemini-2.5-pro - stable Gemini model"},{value:"gemini-2.5-flash",label:"Gemini 2.5 Flash",description:"gemini-2.5-flash - Modelo estable rapido",descriptionForModel:"gemini-2.5-flash - stable fast Gemini model"}];if("custom-openai"===c()||"custom-anthropic"===c()){const o=c(),t=U(o)?.id??null,i=y(o,t).map(e=>({value:e,label:e,description:`Modelo del endpoint ${o}`}));return[getDefaultOptionForUser(e),...i]}if("ollama"===c()||"ollama-cloud"===c()||"zai"===c()||"minimax"===c()||"deepseek"===c())return[getDefaultOptionForUser(e)];if(o()){if(t()||i()){const o=[getDefaultOptionForUser(e)];return o.push(getMaxOpus47Option(e)),!w()&&u()&&o.push(getMaxOpus47_1MOption(e)),o.push(getMaxOpusOption(e)),!w()&&u()&&o.push(getMaxOpus46_1MOption(e)),o.push(H),d()&&o.push(getMaxSonnet46_1MOption()),o.push(I),o}const o=[getDefaultOptionForUser(e)];return o.push(H),d()&&o.push(getMaxSonnet46_1MOption()),o.push(getMaxOpus47Option(e)),u()&&o.push(getMaxOpus47_1MOption(e)),o.push(getMaxOpusOption(e)),u()&&o.push(getMaxOpus46_1MOption(e)),o.push(I),o}if("firstParty"===c()){const o=[getDefaultOptionForUser(e)];return o.push(getSonnet46Option()),d()&&o.push(getSonnet46_1MOption()),o.push(getOpus47Option(e)),u()&&o.push(getOpus47_1MOption(e)),o.push(getOpus46Option(e)),u()&&o.push(getOpus46_1MOption(e)),o.push(getHaiku45Option()),o}const n=[getDefaultOptionForUser(e)],s=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_SONNET_MODEL;if(e&&o){const e=N(o);return{value:"sonnet",label:process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION??"Custom Sonnet model"+(e?" (1M context)":""),descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION??"Custom Sonnet model"+(e?" with 1M context":"")} (${o})`}}}();void 0!==s?n.push(s):(n.push(getSonnet46Option()),d()&&n.push(getSonnet46_1MOption()));const r=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_OPUS_MODEL;if(e&&o){const e=N(o);return{value:"opus",label:process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION??"Custom Opus model"+(e?" (1M context)":""),descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION??"Custom Opus model"+(e?" with 1M context":"")} (${o})`}}}();void 0!==r?n.push(r):(n.push(getOpus47Option(e)),u()&&n.push(getOpus47_1MOption(e)),n.push(getOpus46Option(e)),u()&&n.push(getOpus46_1MOption(e)),n.push({value:"opus",label:"Opus 4.1",description:"Opus 4.1 · Legacy",descriptionForModel:"Opus 4.1 - legacy version"}));const l=function(){const e="firstParty"!==c(),o=process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL;if(e&&o)return{value:"haiku",label:process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME??o,description:process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION??"Custom Haiku model",descriptionForModel:`${process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION??"Custom Haiku model"} (${o})`}}();return void 0!==l?n.push(l):n.push(getHaikuOption()),n}function getKnownModelOption(e){const o=F(e);if(!o)return null;const t=function(e){const o=m(e);if(o.includes("claude-sonnet-4-6")||o.includes("claude-sonnet-4-5")||o.includes("claude-sonnet-4-")||o.includes("claude-3-7-sonnet")||o.includes("claude-3-5-sonnet")){const e=F(x());if(e)return{alias:"Sonnet",currentVersionName:e}}if(o.includes("claude-opus-4")){const e=F(_());if(e)return{alias:"Opus",currentVersionName:e}}if(o.includes("claude-haiku")||o.includes("claude-3-5-haiku")){const e=F(b());if(e)return{alias:"Haiku",currentVersionName:e}}return null}(e);return t&&o!==t.currentVersionName?{value:e,label:o,description:`Newer version available · select ${t.alias} for ${t.currentVersionName}`}:{value:e,label:o,description:e}}export function getModelOptions(o=!1){const t=getModelOptionsBase(o),i=process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;i&&!t.some(e=>e.value===i)&&t.push({value:i,label:process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_NAME??i,description:process.env.ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION??`Custom model (${i})`});const n=c();if(!("custom-openai"===n||"custom-anthropic"===n))for(const e of k().additionalModelOptionsCache??[])t.some(o=>o.value===e.value)||t.push(e);let s=null;const r=T(),l=e();if(null!=r?s=r:null!==l&&(s=l),null===s||t.some(e=>e.value===s))return filterModelOptionsByAllowlist(t);if("opusplan"===s)return filterModelOptionsByAllowlist([...t,{value:"opusplan",label:"Opus Plan Mode",description:"Use Opus 4.7 in plan mode, Sonnet 4.6 otherwise"}]);if("opus"===s&&"firstParty"===c())return filterModelOptionsByAllowlist([...t,getMaxOpusOption(o)]);if("opus[1m]"===s&&"firstParty"===c())return filterModelOptionsByAllowlist([...t,getMergedOpus1MOption(o)]);{const e=getKnownModelOption(s);return e?t.push(e):t.push({value:s,label:s,description:"Custom model"}),filterModelOptionsByAllowlist(t)}}function filterModelOptionsByAllowlist(e){return(a()||{}).availableModels?e.filter(e=>null===e.value||null!==e.value&&O(e.value)):e}
@@ -1 +1 @@
1
- import{clearProviderProfileBaseUrl as r,getProviderProfileBaseUrl as t,setProviderProfileBaseUrl as e}from"./providerProfiles.js";import{clearStoredProviderBaseUrl as i,getStoredProviderBaseUrl as o,setStoredProviderBaseUrl as a}from"./providerProfilesDb.js";const n={openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic",nvidia:"https://integrate.api.nvidia.com/v1",deepseek:"https://api.deepseek.com/v1","custom-openai":"https://api.openai.com/v1","custom-anthropic":"https://api.anthropic.com/v1"};function trimTrailingSlash(r){return r.endsWith("/")?r.slice(0,-1):r}export function getDefaultProviderBaseUrl(r){return n[r]}export function getConfiguredProviderBaseUrl(r){const e=t(r)?.trim();if(e)try{return normalizeProviderBaseUrl(r,e)}catch{return e}const i=o(r)?.trim();if(i)try{return normalizeProviderBaseUrl(r,i)}catch{return i}return getDefaultProviderBaseUrl(r)}export function isProviderBaseUrlCustomized(r){return Boolean(t(r)?.trim()||o(r)?.trim())}export function normalizeProviderBaseUrl(r,t){const e=function(r,t){const e=t.trim();if(!e)throw new Error("La base URL no puede estar vacia.");try{return new URL(e)}catch{return new URL(`${"ollama"===r||"ollama-cloud"===r?"http://":"https://"}${e}`)}}(r,t),i=`${e.protocol}//${e.host}${e.pathname}${e.search}${e.hash}`;return"zai"===r||"minimax"===r||"gemini-api"===r||"gemini-google"===r||"nvidia"===r?trimTrailingSlash(i):function(r){const t=trimTrailingSlash(r);return t.endsWith("/v1")?t:`${t}/v1`}(i)}export function setProviderBaseUrl(r,t){const i=normalizeProviderBaseUrl(r,t);return e(r,i),a(r,i),i}export function clearProviderBaseUrl(t){r(t),i(t)}
1
+ import{clearProviderProfileBaseUrl as r,getProviderProfileBaseUrl as t,isProfiledProvider as e,setProviderProfileBaseUrl as i}from"./providerProfiles.js";import{clearStoredProviderBaseUrl as o,getStoredProviderBaseUrl as a,setStoredProviderBaseUrl as n}from"./providerProfilesDb.js";const s={openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic",nvidia:"https://integrate.api.nvidia.com/v1",deepseek:"https://api.deepseek.com/v1","custom-openai":"https://api.openai.com/v1","custom-anthropic":"https://api.anthropic.com/v1"};function trimTrailingSlash(r){return r.endsWith("/")?r.slice(0,-1):r}export function getDefaultProviderBaseUrl(r){return s[r]}export function getConfiguredProviderBaseUrl(r){const e=t(r)?.trim();if(e)try{return normalizeProviderBaseUrl(r,e)}catch{return e}const i=a(r)?.trim();if(i)try{return normalizeProviderBaseUrl(r,i)}catch{return i}return getDefaultProviderBaseUrl(r)}export function isProviderBaseUrlCustomized(r){return Boolean(t(r)?.trim()||a(r)?.trim())}export function normalizeProviderBaseUrl(r,t){const e=function(r,t){const e=t.trim();if(!e)throw new Error("La base URL no puede estar vacia.");try{return new URL(e)}catch{return new URL(`${"ollama"===r||"ollama-cloud"===r?"http://":"https://"}${e}`)}}(r,t),i=`${e.protocol}//${e.host}${e.pathname}${e.search}${e.hash}`;return"zai"===r||"minimax"===r||"gemini-api"===r||"gemini-google"===r||"nvidia"===r?trimTrailingSlash(i):function(r){const t=trimTrailingSlash(r);return t.endsWith("/v1")?t:`${t}/v1`}(i)}export function setProviderBaseUrl(r,t){const o=normalizeProviderBaseUrl(r,t);return e(r)&&i(r,o),n(r,o),o}export function clearProviderBaseUrl(t){e(t)&&r(t),o(t)}
@@ -1 +1 @@
1
- import{getStoredLastModelForProvider as e,getStoredProviderBaseUrl as r,readProviderProfilesState as i,writeProviderProfilesState as o}from"./providerProfilesDb.js";const t=new Set(["claude","openai","openrouter","ollama","ollama-cloud","gemini-api","gemini-google","zai","minimax","nvidia","deepseek"]),l={claude:"main",openai:"main",openrouter:"main",ollama:"local","ollama-cloud":"main","gemini-api":"main","gemini-google":"main",zai:"main",minimax:"main",nvidia:"main",deepseek:"main"},n={claude:"claude",openai:"openai",openrouter:"openrouter",ollama:"ollama-local","ollama-cloud":"ollama-cloud","gemini-api":"gemini-api","gemini-google":"gemini-google",zai:"z-ai",minimax:"minimax",nvidia:"nvidia",deepseek:"deepseek"},a={openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic",deepseek:"https://api.deepseek.com/v1"};function sanitizeProfileSegment(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"default"}function buildProfileId(e,r){return`${e}/${sanitizeProfileSegment(r)}`}function buildDefaultAgentName(e,r){const i=n[e],o=sanitizeProfileSegment(r);return o===sanitizeProfileSegment(l[e])?i:`${i}-${o}`}export function getDefaultProfileName(e){return l[e]}export function buildProviderProfileId(e,r){return buildProfileId(e,r)}export function isDefaultProfileId(e,r){return!!r&&r===buildProfileId(e,l[e])}function getState(){const e=i();return{version:1,profiles:e.profiles??{},lastProfileIdByProvider:e.lastProfileIdByProvider??{},activeProfileId:e.activeProfileId}}function saveState(e){const r=e(getState());return o(r),r}function getProfilesMap(){return getState().profiles??{}}function getProfileSeed(i,o){return o?function(i){return{baseUrl:"openrouter"===i||"ollama"===i||"ollama-cloud"===i||"zai"===i||"minimax"===i||"deepseek"===i?r(i):void 0,lastModel:e(i)??null}}(i):{baseUrl:a[i],lastModel:null}}export function isProfiledProvider(e){return t.has(e)}export function listProviderProfiles(e){const r=Object.values(getProfilesMap());return e?r.filter(r=>r.provider===e):r}export function getProviderProfile(e){return e?getProfilesMap()[e]??null:null}export function getActiveProviderProfile(){return getProviderProfile(getState().activeProfileId)}export function getLastUsedProviderProfile(e){const r=getState(),i=r.lastProfileIdByProvider?.[e];if(i){const e=getProviderProfile(i);if(e)return e}return listProviderProfiles(e)[0]??null}export function createProviderProfile(e){const r=buildProfileId(e.provider,e.name),i=getProviderProfile(r);if(i)return i;const o=(new Date).toISOString(),t={id:r,provider:e.provider,name:e.name.trim()||l[e.provider],agentName:e.agentName?.trim()||buildDefaultAgentName(e.provider,e.name),baseUrl:e.baseUrl,lastModel:e.lastModel??null,createdAt:o,updatedAt:o};return saveState(r=>({...r,activeProfileId:e.activate?t.id:r.activeProfileId,profiles:{...r.profiles??{},[t.id]:t},lastProfileIdByProvider:{...r.lastProfileIdByProvider??{},[e.provider]:t.id}})),t}export function ensureProviderProfile(e,r=l[e]){const i=getProviderProfile(buildProfileId(e,r));if(i)return i;return createProviderProfile({provider:e,name:r,...getProfileSeed(e,0===listProviderProfiles(e).length),activate:!1})}export function resolveProviderProfile(e,r={}){const i=getActiveProviderProfile();if(i?.provider===e)return i;const o=getLastUsedProviderProfile(e);return o||(r.createIfMissing?ensureProviderProfile(e):null)}export function getResolvedProviderProfileId(e){return resolveProviderProfile(e)?.id??null}export function setActiveProviderProfile(e){const r=getProviderProfile(e);return r?(saveState(e=>({...e,activeProfileId:r.id,lastProfileIdByProvider:{...e.lastProfileIdByProvider??{},[r.provider]:r.id}})),r):null}export function setActiveProfileForProvider(e,r){const i=r&&r.trim()?ensureProviderProfile(e,r):resolveProviderProfile(e,{createIfMissing:!0});return setActiveProviderProfile(i.id),i}export function findProviderProfileByName(e,r){return getProviderProfile(buildProfileId(e,r))}export function updateProviderProfile(e,r){let i=null;return saveState(o=>{const t=o.profiles?.[e];return t?(i=r(t),{...o,profiles:{...o.profiles??{},[e]:i},lastProfileIdByProvider:{...o.lastProfileIdByProvider??{},[t.provider]:e}}):o}),i}export function renameProviderProfile(e,r,i){const o=findProviderProfileByName(e,r);if(!o)return null;const t=i.trim();if(!t)throw new Error("Debes indicar un nuevo nombre de perfil.");const l=buildProfileId(e,t);if(l!==o.id&&getProviderProfile(l))throw new Error(`Ya existe un perfil ${e}/${t}.`);const n={...o,id:l,name:t,updatedAt:(new Date).toISOString()};return saveState(r=>{const i={...r.profiles??{}};delete i[o.id],i[l]=n;const t={...r.lastProfileIdByProvider??{},[e]:r.lastProfileIdByProvider?.[e]===o.id?l:r.lastProfileIdByProvider?.[e]};return{...r,activeProfileId:r.activeProfileId===o.id?l:r.activeProfileId,profiles:i,lastProfileIdByProvider:t}}),{previousId:o.id,profile:n}}export function removeProviderProfile(e,r){const i=findProviderProfileByName(e,r);return i?(saveState(r=>{const o={...r.profiles??{}};delete o[i.id];const t=Object.values(o).filter(r=>r.provider===e),l=t[0]?.id;return{...r,activeProfileId:r.activeProfileId===i.id?l:r.activeProfileId,profiles:o,lastProfileIdByProvider:{...r.lastProfileIdByProvider??{},[e]:r.lastProfileIdByProvider?.[e]===i.id?l:r.lastProfileIdByProvider?.[e]}}}),i):null}export function clearAllProviderProfiles(){const e=Object.values(getProfilesMap());return saveState(e=>({version:1,profiles:{},lastProfileIdByProvider:{}})),e}export function setProviderProfileAgentNameByName(e,r,i){const o=findProviderProfileByName(e,r);if(!o)return null;const t=sanitizeProfileSegment(i);if(!t)throw new Error("Debes indicar un agentName valido.");return updateProviderProfile(o.id,e=>({...e,agentName:t,updatedAt:(new Date).toISOString()}))}export function setProviderProfileBaseUrl(e,r){const i=resolveProviderProfile(e,{createIfMissing:!0});return updateProviderProfile(i.id,e=>({...e,baseUrl:r,updatedAt:(new Date).toISOString()}))??i}export function clearProviderProfileBaseUrl(e){const r=resolveProviderProfile(e);return r?updateProviderProfile(r.id,e=>({...e,baseUrl:void 0,updatedAt:(new Date).toISOString()})):null}export function getProviderProfileBaseUrl(e){return resolveProviderProfile(e)?.baseUrl??null}export function setProviderProfileLastModel(e,r){const i=resolveProviderProfile(e);return i?updateProviderProfile(i.id,e=>({...e,lastModel:r,updatedAt:(new Date).toISOString()})):null}export function getProviderProfileLastModel(e){return resolveProviderProfile(e)?.lastModel??null}export function setProviderProfileLastModelByName(e,r,i){const o=findProviderProfileByName(e,r);return o?updateProviderProfile(o.id,e=>({...e,lastModel:i,updatedAt:(new Date).toISOString()})):null}
1
+ import{getStoredLastModelForProvider as e,getStoredProviderBaseUrl as r,readProviderProfilesState as i,writeProviderProfilesState as o}from"./providerProfilesDb.js";const t=new Set(["claude","openai","openrouter","ollama","ollama-cloud","gemini-api","gemini-google","zai","minimax","nvidia","deepseek","custom-openai","custom-anthropic"]),l={claude:"main",openai:"main",openrouter:"main",ollama:"local","ollama-cloud":"main","gemini-api":"main","gemini-google":"main",zai:"main",minimax:"main",nvidia:"main",deepseek:"main","custom-openai":"main","custom-anthropic":"main"},n={claude:"claude",openai:"openai",openrouter:"openrouter",ollama:"ollama-local","ollama-cloud":"ollama-cloud","gemini-api":"gemini-api","gemini-google":"gemini-google",zai:"z-ai",minimax:"minimax",nvidia:"nvidia",deepseek:"deepseek","custom-openai":"custom-openai","custom-anthropic":"custom-anthropic"},a={openrouter:"https://openrouter.ai/api/v1",ollama:"http://localhost:11434/v1","ollama-cloud":"http://localhost:11434/v1","gemini-api":"https://generativelanguage.googleapis.com/v1beta/openai","gemini-google":"https://generativelanguage.googleapis.com/v1beta/openai",zai:"https://api.z.ai/api/coding/paas/v4",minimax:"https://api.minimax.io/anthropic",deepseek:"https://api.deepseek.com/v1"};function sanitizeProfileSegment(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"default"}function buildProfileId(e,r){return`${e}/${sanitizeProfileSegment(r)}`}function buildDefaultAgentName(e,r){const i=n[e],o=sanitizeProfileSegment(r);return o===sanitizeProfileSegment(l[e])?i:`${i}-${o}`}export function getDefaultProfileName(e){return l[e]}export function buildProviderProfileId(e,r){return buildProfileId(e,r)}export function isDefaultProfileId(e,r){return!!r&&r===buildProfileId(e,l[e])}function getState(){const e=i();return{version:1,profiles:e.profiles??{},lastProfileIdByProvider:e.lastProfileIdByProvider??{},activeProfileId:e.activeProfileId}}function saveState(e){const r=e(getState());return o(r),r}function getProfilesMap(){return getState().profiles??{}}function getProfileSeed(i,o){return o?function(i){return{baseUrl:"openrouter"===i||"ollama"===i||"ollama-cloud"===i||"zai"===i||"minimax"===i||"deepseek"===i?r(i):void 0,lastModel:e(i)??null}}(i):{baseUrl:a[i],lastModel:null}}export function isProfiledProvider(e){return t.has(e)}export function listProviderProfiles(e){const r=Object.values(getProfilesMap());return e?r.filter(r=>r.provider===e):r}export function getProviderProfile(e){return e?getProfilesMap()[e]??null:null}export function getActiveProviderProfile(){return getProviderProfile(getState().activeProfileId)}export function getLastUsedProviderProfile(e){const r=getState(),i=r.lastProfileIdByProvider?.[e];if(i){const e=getProviderProfile(i);if(e)return e}return listProviderProfiles(e)[0]??null}export function createProviderProfile(e){const r=buildProfileId(e.provider,e.name),i=getProviderProfile(r);if(i)return i;const o=(new Date).toISOString(),t={id:r,provider:e.provider,name:e.name.trim()||l[e.provider],agentName:e.agentName?.trim()||buildDefaultAgentName(e.provider,e.name),baseUrl:e.baseUrl,lastModel:e.lastModel??null,createdAt:o,updatedAt:o};return saveState(r=>({...r,activeProfileId:e.activate?t.id:r.activeProfileId,profiles:{...r.profiles??{},[t.id]:t},lastProfileIdByProvider:{...r.lastProfileIdByProvider??{},[e.provider]:t.id}})),t}export function ensureProviderProfile(e,r=l[e]){const i=getProviderProfile(buildProfileId(e,r));if(i)return i;return createProviderProfile({provider:e,name:r,...getProfileSeed(e,0===listProviderProfiles(e).length),activate:!1})}export function resolveProviderProfile(e,r={}){const i=getActiveProviderProfile();if(i?.provider===e)return i;const o=getLastUsedProviderProfile(e);return o||(r.createIfMissing?ensureProviderProfile(e):null)}export function getResolvedProviderProfileId(e){return resolveProviderProfile(e)?.id??null}export function setActiveProviderProfile(e){const r=getProviderProfile(e);return r?(saveState(e=>({...e,activeProfileId:r.id,lastProfileIdByProvider:{...e.lastProfileIdByProvider??{},[r.provider]:r.id}})),r):null}export function setActiveProfileForProvider(e,r){const i=r&&r.trim()?ensureProviderProfile(e,r):resolveProviderProfile(e,{createIfMissing:!0});return setActiveProviderProfile(i.id),i}export function findProviderProfileByName(e,r){return getProviderProfile(buildProfileId(e,r))}export function updateProviderProfile(e,r){let i=null;return saveState(o=>{const t=o.profiles?.[e];return t?(i=r(t),{...o,profiles:{...o.profiles??{},[e]:i},lastProfileIdByProvider:{...o.lastProfileIdByProvider??{},[t.provider]:e}}):o}),i}export function renameProviderProfile(e,r,i){const o=findProviderProfileByName(e,r);if(!o)return null;const t=i.trim();if(!t)throw new Error("Debes indicar un nuevo nombre de perfil.");const l=buildProfileId(e,t);if(l!==o.id&&getProviderProfile(l))throw new Error(`Ya existe un perfil ${e}/${t}.`);const n={...o,id:l,name:t,updatedAt:(new Date).toISOString()};return saveState(r=>{const i={...r.profiles??{}};delete i[o.id],i[l]=n;const t={...r.lastProfileIdByProvider??{},[e]:r.lastProfileIdByProvider?.[e]===o.id?l:r.lastProfileIdByProvider?.[e]};return{...r,activeProfileId:r.activeProfileId===o.id?l:r.activeProfileId,profiles:i,lastProfileIdByProvider:t}}),{previousId:o.id,profile:n}}export function removeProviderProfile(e,r){const i=findProviderProfileByName(e,r);return i?(saveState(r=>{const o={...r.profiles??{}};delete o[i.id];const t=Object.values(o).filter(r=>r.provider===e),l=t[0]?.id;return{...r,activeProfileId:r.activeProfileId===i.id?l:r.activeProfileId,profiles:o,lastProfileIdByProvider:{...r.lastProfileIdByProvider??{},[e]:r.lastProfileIdByProvider?.[e]===i.id?l:r.lastProfileIdByProvider?.[e]}}}),i):null}export function clearAllProviderProfiles(){const e=Object.values(getProfilesMap());return saveState(e=>({version:1,profiles:{},lastProfileIdByProvider:{}})),e}export function setProviderProfileAgentNameByName(e,r,i){const o=findProviderProfileByName(e,r);if(!o)return null;const t=sanitizeProfileSegment(i);if(!t)throw new Error("Debes indicar un agentName valido.");return updateProviderProfile(o.id,e=>({...e,agentName:t,updatedAt:(new Date).toISOString()}))}export function setProviderProfileBaseUrl(e,r){const i=resolveProviderProfile(e,{createIfMissing:!0});return updateProviderProfile(i.id,e=>({...e,baseUrl:r,updatedAt:(new Date).toISOString()}))??i}export function clearProviderProfileBaseUrl(e){const r=resolveProviderProfile(e);return r?updateProviderProfile(r.id,e=>({...e,baseUrl:void 0,updatedAt:(new Date).toISOString()})):null}export function getProviderProfileBaseUrl(e){return resolveProviderProfile(e)?.baseUrl??null}export function setProviderProfileLastModel(e,r){const i=resolveProviderProfile(e);return i?updateProviderProfile(i.id,e=>({...e,lastModel:r,updatedAt:(new Date).toISOString()})):null}export function getProviderProfileLastModel(e){return resolveProviderProfile(e)?.lastModel??null}export function setProviderProfileLastModelByName(e,r,i){const o=findProviderProfileByName(e,r);return o?updateProviderProfile(o.id,e=>({...e,lastModel:i,updatedAt:(new Date).toISOString()})):null}
@@ -1 +1 @@
1
- import{resetModelCapabilityOverridesForProviderChange as r}from"./modelSupportOverrides.js";import{resetModelStringsForProviderChange as e}from"./modelStrings.js";import{getStoredLastModelForProvider as o,setStoredActiveProviderPreference as i,setStoredLastModelForProvider as t}from"./providerProfilesDb.js";import{getProviderProfileLastModel as n,isProfiledProvider as d,setActiveProfileForProvider as a,setProviderProfileLastModel as u}from"./providerProfiles.js";export function toProviderPreference(r){return"openai"===r?"openai":"openrouter"===r?"openrouter":"ollama"===r?"ollama":"ollama-cloud"===r?"ollama-cloud":"gemini-api"===r?"gemini-api":"zai"===r?"zai":"minimax"===r?"minimax":"nvidia"===r?"nvidia":"deepseek"===r?"deepseek":"claude"}export function getStoredModelForProvider(r){if(d(r)){const e=n(r);if(null!==e)return e}const e=o(r);return void 0!==e?e:null}export function switchProviderPreference(o){const n="claude"===o.currentProvider||"openai"===o.currentProvider||"openrouter"===o.currentProvider||"ollama"===o.currentProvider||"ollama-cloud"===o.currentProvider||"gemini-google"===o.currentProvider||"zai"===o.currentProvider||"minimax"===o.currentProvider||"nvidia"===o.currentProvider||"deepseek"===o.currentProvider?o.currentProvider:toProviderPreference(o.currentProvider);return d(n)&&u(n,o.currentModel),t(n,o.currentModel),d(o.targetProvider)&&a(o.targetProvider,o.targetProfileName??void 0),i(o.targetProvider),n!==o.targetProvider&&(e(),r()),getStoredModelForProvider(o.targetProvider)}
1
+ import{resetModelCapabilityOverridesForProviderChange as r}from"./modelSupportOverrides.js";import{resetModelStringsForProviderChange as e}from"./modelStrings.js";import{getStoredLastModelForProvider as o,setStoredActiveProviderPreference as i,setStoredLastModelForProvider as t}from"./providerProfilesDb.js";import{getProviderProfileLastModel as n,isProfiledProvider as d,setActiveProfileForProvider as a,setProviderProfileLastModel as c}from"./providerProfiles.js";export function toProviderPreference(r){return"openai"===r?"openai":"openrouter"===r?"openrouter":"ollama"===r?"ollama":"ollama-cloud"===r?"ollama-cloud":"gemini-api"===r?"gemini-api":"zai"===r?"zai":"minimax"===r?"minimax":"nvidia"===r?"nvidia":"deepseek"===r?"deepseek":"custom-openai"===r?"custom-openai":"custom-anthropic"===r?"custom-anthropic":"claude"}export function getStoredModelForProvider(r){if(d(r)){const e=n(r);if(null!==e)return e}const e=o(r);return void 0!==e?e:null}export function switchProviderPreference(o){const n="claude"===o.currentProvider||"openai"===o.currentProvider||"openrouter"===o.currentProvider||"ollama"===o.currentProvider||"ollama-cloud"===o.currentProvider||"gemini-google"===o.currentProvider||"zai"===o.currentProvider||"minimax"===o.currentProvider||"nvidia"===o.currentProvider||"deepseek"===o.currentProvider||"custom-openai"===o.currentProvider||"custom-anthropic"===o.currentProvider?o.currentProvider:toProviderPreference(o.currentProvider);return d(n)&&c(n,o.currentModel),t(n,o.currentModel),d(o.targetProvider)&&a(o.targetProvider,o.targetProfileName??void 0),i(o.targetProvider),n!==o.targetProvider&&(e(),r()),getStoredModelForProvider(o.targetProvider)}
@@ -1 +1 @@
1
- import{isEnvTruthy as e}from"../envUtils.js";import{getSecureStorage as r}from"../secureStorage/index.js";import{isProviderBaseUrlCustomized as o}from"./providerBaseUrls.js";import{getProviderOverride as i}from"./providerOverrideContext.js";import{getStoredActiveProviderPreference as n}from"./providerProfilesDb.js";import{listProviderProfiles as t}from"./providerProfiles.js";export function providerPreferenceToApiProvider(e){if(e)return"claude"===e?"firstParty":e}export function isOpenAIProviderConfigured(){return e(process.env.CLAUDE_CODE_USE_OPENAI)||Boolean(process.env.OPENAI_API_KEY)||Boolean(process.env.OPENAI_API_TOKEN)||Boolean(process.env.OPENAI_OAUTH_TOKEN)||function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("openai/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o||e?.openAiOauth?.accessToken)}catch{return!1}}()}export function isOpenRouterProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("openrouter/")&&"string"==typeof r&&r.trim());return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||e?.providerApiKeys?.openrouter||o)}catch{return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN)}}export function isOllamaProviderConfigured(){try{const e=n();return Boolean(process.env.OLLAMA_BASE_URL||o("ollama")||t("ollama").length>0||"ollama"===e)}catch{return Boolean(process.env.OLLAMA_BASE_URL)}}export function isOllamaCloudProviderConfigured(){if(isOllamaProviderConfigured())return!0;try{const e=r().read(),i=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("ollama-cloud/")&&"string"==typeof r&&r.trim()),t=n();return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY||e?.providerApiKeys?.["ollama-cloud"]||i||o("ollama-cloud")||"ollama-cloud"===t||"ollama"===t)}catch{return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY)}}export function isGeminiApiProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("gemini-api/")&&"string"==typeof r&&r.trim());return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||e?.providerApiKeys?.["gemini-api"]||o)}catch{return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)}}export function isGeminiGoogleProviderConfigured(){try{const e=n();return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT||Object.entries(storage?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())||"gemini-google"===e)}catch{return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT)}}export function isZAIProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("zai/")&&"string"==typeof r&&r.trim());return Boolean(process.env.ZAI_API_KEY||e?.providerApiKeys?.zai||o)}catch{return Boolean(process.env.ZAI_API_KEY)}}export function isMiniMaxProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("minimax/")&&"string"==typeof r&&r.trim());return Boolean(process.env.MINIMAX_API_KEY||e?.providerApiKeys?.minimax||o)}catch{return Boolean(process.env.MINIMAX_API_KEY)}}export function isNvidiaProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("nvidia/")&&"string"==typeof r&&r.trim());return Boolean(process.env.NVIDIA_API_KEY||e?.providerApiKeys?.nvidia||o)}catch{return Boolean(process.env.NVIDIA_API_KEY)}}export function isDeepSeekProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("deepseek/")&&"string"==typeof r&&r.trim());return Boolean(process.env.DEEPSEEK_API_KEY||e?.providerApiKeys?.deepseek||o)}catch{return Boolean(process.env.DEEPSEEK_API_KEY)}}export function isOpenAICompatibleProvider(e){return"openai"===e||"openrouter"===e||"ollama"===e||"ollama-cloud"===e||"gemini-api"===e||"gemini-google"===e||"zai"===e||"minimax"===e||"nvidia"===e||"deepseek"===e}export function usesOpenAIBackend(e){return isOpenAICompatibleProvider(e)&&"minimax"!==e}export function hasDualProviderSessions(){return(isOpenAIProviderConfigured()||isOpenRouterProviderConfigured()||isOllamaProviderConfigured()||isOllamaCloudProviderConfigured()||isGeminiApiProviderConfigured()||isGeminiGoogleProviderConfigured()||isZAIProviderConfigured()||isMiniMaxProviderConfigured()||isNvidiaProviderConfigured()||isDeepSeekProviderConfigured())&&function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("claude/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o)}catch{return!1}}()}export function getAPIProvider(){const r=i();if(r)return r;if(e(process.env.CLAUDE_CODE_USE_BEDROCK))return"bedrock";if(e(process.env.CLAUDE_CODE_USE_VERTEX))return"vertex";if(e(process.env.CLAUDE_CODE_USE_FOUNDRY))return"foundry";try{const e=n();if("claude"===e)return"firstParty";if("openai"===e)return"openai";if("openrouter"===e)return"openrouter";if("ollama"===e)return"ollama";if("ollama-cloud"===e)return"ollama-cloud";if("gemini-api"===e)return"gemini-api";if("gemini-google"===e)return"gemini-google";if("zai"===e)return"zai";if("minimax"===e)return"minimax";if("nvidia"===e)return"nvidia";if("deepseek"===e)return"deepseek"}catch{}const o=isOpenAIProviderConfigured(),t=isOpenRouterProviderConfigured(),s=isOllamaProviderConfigured(),a=isOllamaCloudProviderConfigured(),p=isGeminiApiProviderConfigured(),c=isGeminiGoogleProviderConfigured(),d=isZAIProviderConfigured(),u=isMiniMaxProviderConfigured(),l=isNvidiaProviderConfigured(),v=isDeepSeekProviderConfigured();return o?"openai":t?"openrouter":d?"zai":u?"minimax":l?"nvidia":v?"deepseek":p?"gemini-api":c?"gemini-google":a?"ollama-cloud":s?"ollama":"firstParty"}export function getAPIProviderForStatsig(){return getAPIProvider()}export function isFirstPartyAnthropicBaseUrl(){const e=process.env.ANTHROPIC_BASE_URL;if(!e)return!0;try{const r=new URL(e).host,o=["api.anthropic.com"];return"ant"===process.env.USER_TYPE&&o.push("api-staging.anthropic.com"),o.includes(r)}catch{return!1}}
1
+ import{isEnvTruthy as e}from"../envUtils.js";import{getSecureStorage as r}from"../secureStorage/index.js";import{isProviderBaseUrlCustomized as o}from"./providerBaseUrls.js";import{getProviderOverride as i}from"./providerOverrideContext.js";import{getStoredActiveProviderPreference as n}from"./providerProfilesDb.js";import{listProviderProfiles as t}from"./providerProfiles.js";export function providerPreferenceToApiProvider(e){if(e)return"claude"===e?"firstParty":e}export function isOpenAIProviderConfigured(){return e(process.env.CLAUDE_CODE_USE_OPENAI)||Boolean(process.env.OPENAI_API_KEY)||Boolean(process.env.OPENAI_API_TOKEN)||Boolean(process.env.OPENAI_OAUTH_TOKEN)||function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("openai/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o||e?.openAiOauth?.accessToken)}catch{return!1}}()}export function isOpenRouterProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("openrouter/")&&"string"==typeof r&&r.trim());return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN||e?.providerApiKeys?.openrouter||o)}catch{return Boolean(process.env.OPENROUTER_API_KEY||process.env.OPENROUTER_API_TOKEN)}}export function isOllamaProviderConfigured(){try{const e=n();return Boolean(process.env.OLLAMA_BASE_URL||o("ollama")||t("ollama").length>0||"ollama"===e)}catch{return Boolean(process.env.OLLAMA_BASE_URL)}}export function isOllamaCloudProviderConfigured(){if(isOllamaProviderConfigured())return!0;try{const e=r().read(),i=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("ollama-cloud/")&&"string"==typeof r&&r.trim()),t=n();return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY||e?.providerApiKeys?.["ollama-cloud"]||i||o("ollama-cloud")||"ollama-cloud"===t||"ollama"===t)}catch{return Boolean(process.env.OLLAMA_CLOUD_BASE_URL||process.env.OLLAMA_BASE_URL||process.env.OLLAMA_API_KEY)}}export function isGeminiApiProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("gemini-api/")&&"string"==typeof r&&r.trim());return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY||e?.providerApiKeys?.["gemini-api"]||o)}catch{return Boolean(process.env.GEMINI_API_KEY||process.env.GOOGLE_API_KEY)}}export function isGeminiGoogleProviderConfigured(){try{const e=n();return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT||Object.entries(storage?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("gemini-google/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim())||"gemini-google"===e)}catch{return Boolean(process.env.GEMINI_OAUTH_TOKEN||process.env.GOOGLE_OAUTH_ACCESS_TOKEN||process.env.GOOGLE_APPLICATION_CREDENTIALS||process.env.GEMINI_GOOGLE_PROJECT_ID||process.env.GOOGLE_CLOUD_PROJECT||process.env.GCLOUD_PROJECT)}}export function isZAIProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("zai/")&&"string"==typeof r&&r.trim());return Boolean(process.env.ZAI_API_KEY||e?.providerApiKeys?.zai||o)}catch{return Boolean(process.env.ZAI_API_KEY)}}export function isMiniMaxProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("minimax/")&&"string"==typeof r&&r.trim());return Boolean(process.env.MINIMAX_API_KEY||e?.providerApiKeys?.minimax||o)}catch{return Boolean(process.env.MINIMAX_API_KEY)}}export function isNvidiaProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("nvidia/")&&"string"==typeof r&&r.trim());return Boolean(process.env.NVIDIA_API_KEY||e?.providerApiKeys?.nvidia||o)}catch{return Boolean(process.env.NVIDIA_API_KEY)}}export function isDeepSeekProviderConfigured(){try{const e=r().read(),o=Object.entries(e?.providerProfileApiKeys??{}).some(([e,r])=>e.startsWith("deepseek/")&&"string"==typeof r&&r.trim());return Boolean(process.env.DEEPSEEK_API_KEY||e?.providerApiKeys?.deepseek||o)}catch{return Boolean(process.env.DEEPSEEK_API_KEY)}}export function isOpenAICompatibleProvider(e){return"openai"===e||"openrouter"===e||"ollama"===e||"ollama-cloud"===e||"gemini-api"===e||"gemini-google"===e||"zai"===e||"minimax"===e||"nvidia"===e||"deepseek"===e||"custom-openai"===e}export function usesOpenAIBackend(e){return isOpenAICompatibleProvider(e)&&"minimax"!==e}export function hasDualProviderSessions(){return(isOpenAIProviderConfigured()||isOpenRouterProviderConfigured()||isOllamaProviderConfigured()||isOllamaCloudProviderConfigured()||isGeminiApiProviderConfigured()||isGeminiGoogleProviderConfigured()||isZAIProviderConfigured()||isMiniMaxProviderConfigured()||isNvidiaProviderConfigured()||isDeepSeekProviderConfigured())&&function(){try{const e=r().read(),o=Object.entries(e?.providerProfileOauth??{}).some(([e,r])=>e.startsWith("claude/")&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return Boolean(o)}catch{return!1}}()}export function getAPIProvider(){const r=i();if(r)return r;if(e(process.env.CLAUDE_CODE_USE_BEDROCK))return"bedrock";if(e(process.env.CLAUDE_CODE_USE_VERTEX))return"vertex";if(e(process.env.CLAUDE_CODE_USE_FOUNDRY))return"foundry";try{const e=n();if("claude"===e)return"firstParty";if("openai"===e)return"openai";if("openrouter"===e)return"openrouter";if("ollama"===e)return"ollama";if("ollama-cloud"===e)return"ollama-cloud";if("gemini-api"===e)return"gemini-api";if("gemini-google"===e)return"gemini-google";if("zai"===e)return"zai";if("minimax"===e)return"minimax";if("nvidia"===e)return"nvidia";if("deepseek"===e)return"deepseek";if("custom-openai"===e)return"custom-openai";if("custom-anthropic"===e)return"custom-anthropic"}catch{}const o=isOpenAIProviderConfigured(),t=isOpenRouterProviderConfigured(),s=isOllamaProviderConfigured(),a=isOllamaCloudProviderConfigured(),p=isGeminiApiProviderConfigured(),c=isGeminiGoogleProviderConfigured(),u=isZAIProviderConfigured(),d=isMiniMaxProviderConfigured(),l=isNvidiaProviderConfigured(),v=isDeepSeekProviderConfigured();return o?"openai":t?"openrouter":u?"zai":d?"minimax":l?"nvidia":v?"deepseek":p?"gemini-api":c?"gemini-google":a?"ollama-cloud":s?"ollama":"firstParty"}export function getAPIProviderForStatsig(){return getAPIProvider()}export function isFirstPartyAnthropicBaseUrl(){const e=process.env.ANTHROPIC_BASE_URL;if(!e)return!0;try{const r=new URL(e).host,o=["api.anthropic.com"];return"ant"===process.env.USER_TYPE&&o.push("api-staging.anthropic.com"),o.includes(r)}catch{return!1}}