@iaforged/context-code 2.3.6 → 2.3.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.
- package/dist/src/cli/handlers/auth.js +1 -1
- package/dist/src/commands/agent-spawn/agentSpawn.js +1 -0
- package/dist/src/commands/agent-spawn/index.js +1 -0
- package/dist/src/commands/login/login.js +1 -1
- package/dist/src/commands/skills/skills.js +1 -1
- package/dist/src/commands/swarm-init/index.js +1 -1
- package/dist/src/commands/swarm-init/swarmInit.js +1 -1
- package/dist/src/commands/swarm-list-teams/index.js +1 -0
- package/dist/src/commands/swarm-list-teams/swarmListTeams.js +1 -0
- package/dist/src/commands.js +1 -1
- package/dist/src/components/ConsoleOAuthFlow.js +1 -1
- package/dist/src/components/agents/agentFileUtils.js +1 -1
- package/dist/src/components/agents/new-agent-creation/wizard-steps/LocationStep.js +1 -1
- package/dist/src/components/agents/new-agent-creation/wizard-steps/MemoryStep.js +1 -1
- package/dist/src/components/permissions/ExitPlanModePermissionRequest/ExitPlanModePermissionRequest.js +1 -1
- package/dist/src/constants/oauth.js +1 -1
- package/dist/src/core/agents/blueprints.js +1 -1
- package/dist/src/core/agents/teams.js +1 -0
- package/dist/src/projectOnboardingState.js +1 -1
- package/dist/src/screens/Doctor.js +1 -1
- package/dist/src/services/api/openai.js +1 -1
- package/dist/src/services/oauth/copilotDevice.js +1 -0
- package/dist/src/skills/loadSkillsDir.js +1 -1
- package/dist/src/tools/AgentTool/agentMemory.js +1 -1
- package/dist/src/utils/auth.js +1 -1
- package/dist/src/utils/claudemd.js +1 -1
- package/dist/src/utils/cronTasks.js +1 -1
- package/dist/src/utils/cronTasksLock.js +1 -1
- package/dist/src/utils/doctorDiagnostic.js +1 -1
- package/dist/src/utils/envUtils.js +1 -1
- package/dist/src/utils/hooks/skillImprovement.js +1 -1
- package/dist/src/utils/markdownConfigLoader.js +1 -1
- package/dist/src/utils/metaMcp/common.js +1 -0
- package/dist/src/utils/metaMcp/mcpServer.js +1 -0
- package/dist/src/utils/metaMcp/server/index.js +1 -0
- package/dist/src/utils/metaMcp/setup.js +1 -0
- package/dist/src/utils/model/model.js +1 -1
- package/dist/src/utils/model/modelOptions.js +1 -1
- package/dist/src/utils/model/providerCatalog.js +1 -1
- package/dist/src/utils/model/providerModels.js +1 -1
- package/dist/src/utils/model/providerProfiles.js +1 -1
- package/dist/src/utils/model/providerProfilesDb.js +1 -1
- package/dist/src/utils/model/providers.js +1 -1
- package/dist/src/utils/nativeInstaller/installer.js +1 -1
- package/dist/src/utils/permissions/filesystem.js +1 -1
- package/dist/src/utils/plugins/addDirPluginSettings.js +1 -1
- package/dist/src/utils/sandbox/sandbox-adapter.js +1 -1
- package/dist/src/utils/settings/settings.js +1 -1
- package/dist/src/utils/skills/skillChangeDetector.js +1 -1
- package/dist/src/utils/worktree.js +1 -1
- package/dist/src/whatsapp/config.js +1 -1
- package/dist/webapp/chunk-OJZNEHPP.js +1 -1
- package/dist/webapp/chunk-VAB2VXFI.js +1 -1
- package/dist/webapp/ngsw-worker.js +1 -1
- package/dist/webapp/polyfills-7R4CRVNH.js +1 -1
- package/package.json +41 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
import{realpath as e}from"fs/promises";import t from"ignore";import o from"lodash-es/memoize.js";import{basename as i,dirname as s,isAbsolute as l,join as n,sep as r,relative as a}from"path";import{getAdditionalDirectoriesForClaudeMd as c,getSessionId as m}from"../bootstrap/state.js";import{logEvent as d}from"../services/analytics/index.js";import{roughTokenCountEstimation as u}from"../services/tokenEstimation.js";import{parseArgumentNames as p,substituteArguments as f}from"../utils/argumentSubstitution.js";import{logForDebugging as h}from"../utils/debug.js";import{EFFORT_LEVELS as g,parseEffortValue as k}from"../utils/effort.js";import{getClaudeConfigHomeDir as S,isBareMode as y,isEnvTruthy as v}from"../utils/envUtils.js";import{isENOENT as C,isFsInaccessible as D}from"../utils/errors.js";import{coerceDescriptionToString as $,parseBooleanFrontmatter as w,parseFrontmatter as F,parseShellFrontmatter as P,splitPathInFrontmatter as j}from"../utils/frontmatterParser.js";import{getFsImplementation as x}from"../utils/fsOperations.js";import{isPathGitignored as b}from"../utils/git/gitignore.js";import{logError as _}from"../utils/log.js";import{extractDescriptionFromMarkdown as L,getProjectDirsUpToHome as I,loadMarkdownFilesForSubdir as N,parseSlashCommandToolsFromFrontmatter as E}from"../utils/markdownConfigLoader.js";import{parseUserSpecifiedModel as A}from"../utils/model/model.js";import{executeShellCommandsInPrompt as T}from"../utils/promptShellExecution.js";import{isSettingSourceEnabled as U}from"../utils/settings/constants.js";import{getManagedFilePath as M}from"../utils/settings/managedPath.js";import{isRestrictedToPluginOnly as O}from"../utils/settings/pluginOnlyPolicy.js";import{HooksSchema as z}from"../utils/settings/types.js";import{createSignal as H}from"../utils/signal.js";import{registerMCPSkillBuilders as B}from"./mcpSkillBuilders.js";export function getSkillsPath(e,t){switch(e){case"policySettings":return n(M(),".claude",t);case"userSettings":return n(S(),t);case"projectSettings":return`.context/${t}`;case"plugin":return"plugin";default:return""}}export function estimateSkillFrontmatterTokens(e){const t=[e.name,e.description,e.whenToUse].filter(Boolean).join(" ");return u(t)}function parseHooksFromFrontmatter(e,t){if(!e.hooks)return;const o=z().safeParse(e.hooks);if(o.success)return o.data;h(`Invalid hooks in skill '${t}': ${o.error.message}`)}export function parseSkillFrontmatterFields(e,t,o,i="Skill"){const s=$(e.description,o),l=s??L(t,i),n=void 0===e["user-invocable"]||w(e["user-invocable"]),r="inherit"===e.model?void 0:e.model?A(e.model):void 0,a=e.effort,c=void 0!==a?k(a):void 0;return void 0!==a&&void 0===c&&h(`Skill ${o} has invalid effort '${a}'. Valid options: ${g.join(", ")} or an integer`),{displayName:null!=e.name?String(e.name):void 0,description:l,hasUserSpecifiedDescription:null!==s,allowedTools:E(e["allowed-tools"]),argumentHint:null!=e["argument-hint"]?String(e["argument-hint"]):void 0,argumentNames:p(e.arguments),whenToUse:e.when_to_use,version:e.version,model:r,disableModelInvocation:w(e["disable-model-invocation"]),userInvocable:n,hooks:parseHooksFromFrontmatter(e,o),executionContext:"fork"===e.context?"fork":void 0,agent:e.agent,effort:c,shell:P(e.shell,o)}}export function createSkillCommand({skillName:e,displayName:t,description:o,hasUserSpecifiedDescription:i,markdownContent:s,allowedTools:l,argumentHint:n,argumentNames:r,whenToUse:a,version:c,model:d,disableModelInvocation:u,userInvocable:p,source:h,baseDir:g,loadedFrom:k,hooks:S,executionContext:y,agent:v,paths:C,effort:D,shell:$}){return{type:"prompt",name:e,description:o,hasUserSpecifiedDescription:i,allowedTools:l,argumentHint:n,argNames:r.length>0?r:void 0,whenToUse:a,version:c,model:d,disableModelInvocation:u,userInvocable:p,context:y,agent:v,effort:D,paths:C,contentLength:s.length,isHidden:!p,progressMessage:"running",userFacingName:()=>t||e,source:h,loadedFrom:k,hooks:S,skillRoot:g,async getPromptForCommand(t,o){let i=g?`Base directory for this skill: ${g}\n\n${s}`:s;if(i=f(i,t,!0,r),g){const e="win32"===process.platform?g.replace(/\\/g,"/"):g;i=i.replace(/\$\{CLAUDE_SKILL_DIR\}/g,e)}return i=i.replace(/\$\{CLAUDE_SESSION_ID\}/g,m()),"mcp"!==k&&(i=await T(i,{...o,getAppState(){const e=o.getAppState();return{...e,toolPermissionContext:{...e.toolPermissionContext,alwaysAllowRules:{...e.toolPermissionContext.alwaysAllowRules,command:l}}}}},`/${e}`,$)),[{type:"text",text:i}]}}}async function loadSkillsFromSkillsDir(e,t){const o=x();let i;try{i=await o.readdir(e)}catch(e){return D(e)||_(e),[]}return(await Promise.all(i.map(async i=>{try{if(!i.isDirectory()&&!i.isSymbolicLink())return null;const s=n(e,i.name),l=n(s,"SKILL.md");let r;try{r=await o.readFile(l,{encoding:"utf-8"})}catch(e){return C(e)||h(`[skills] failed to read ${l}: ${e}`,{level:"warn"}),null}const{frontmatter:a,content:c}=F(r,l),m=i.name,d=parseSkillFrontmatterFields(a,c,m),u=function(e){if(!e.paths)return;const t=j(e.paths).map(e=>e.endsWith("/**")?e.slice(0,-3):e).filter(e=>e.length>0);return 0===t.length||t.every(e=>"**"===e)?void 0:t}(a);return{skill:createSkillCommand({...d,skillName:m,markdownContent:c,source:t,baseDir:s,loadedFrom:"skills",paths:u}),filePath:l}}catch(e){return _(e),null}}))).filter(e=>null!==e)}function isSkillFile(e){return/^skill\.md$/i.test(i(e))}function transformSkillFiles(e){const t=new Map;for(const o of e){const e=s(o.filePath),i=t.get(e)??[];i.push(o),t.set(e,i)}const o=[];for(const[e,s]of t){const t=s.filter(e=>isSkillFile(e.filePath));if(t.length>0){const s=t[0];t.length>1&&h(`Multiple skill files found in ${e}, using ${i(s.filePath)}`),o.push(s)}else o.push(...s)}return o}function buildNamespace(e,t){const o=t.endsWith(r)?t.slice(0,-1):t;if(e===o)return"";const i=e.slice(o.length+1);return i?i.split(r).join(":"):""}function getCommandName(e){return isSkillFile(e.filePath)?function(e,t){const o=s(e),l=s(o),n=i(o),r=buildNamespace(l,t);return r?`${r}:${n}`:n}(e.filePath,e.baseDir):function(e,t){const o=i(e),l=s(e),n=o.replace(/\.md$/,""),r=buildNamespace(l,t);return r?`${r}:${n}`:n}(e.filePath,e.baseDir)}async function loadSkillsFromCommandsDir(e){try{const t=transformSkillFiles(await N("commands",e)),o=[];for(const{baseDir:e,filePath:i,frontmatter:l,content:n,source:r}of t)try{const t=isSkillFile(i)?s(i):void 0,a=getCommandName({baseDir:e,filePath:i,frontmatter:l,content:n,source:r}),c=parseSkillFrontmatterFields(l,n,a,"Custom command");o.push({skill:createSkillCommand({...c,skillName:a,displayName:void 0,markdownContent:n,source:r,baseDir:t,loadedFrom:"commands_DEPRECATED",paths:void 0}),filePath:i})}catch(e){_(e)}return o}catch(e){return _(e),[]}}export const getSkillDirCommands=o(async t=>{const o=n(S(),"skills"),i=n(M(),".context","skills"),s=I("skills",t,".context"),l=I("skills",t,".claude");h(`Loading skills from: managed=${i}, user=${o}, project=[${s.join(", ")}]`);const r=c(),a=O("skills"),m=U("projectSettings")&&!a;if(y()){if(0===r.length||!m)return h(`[bare] Skipping skill dir discovery (${0===r.length?"no --add-dir":"projectSettings disabled or skillsLocked"})`),[];return(await Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".context","skills"),"projectSettings")))).flat().map(e=>e.skill)}const[d,u,p,f,g,k,C]=await Promise.all([v(process.env.CONTEXT_CODE_DISABLE_POLICY_SKILLS)||v(process.env.CLAUDE_CODE_DISABLE_POLICY_SKILLS)?Promise.resolve([]):loadSkillsFromSkillsDir(i,"policySettings"),U("userSettings")&&!a?loadSkillsFromSkillsDir(o,"userSettings"):Promise.resolve([]),m?Promise.all(s.map(e=>loadSkillsFromSkillsDir(e,"projectSettings"))):Promise.resolve([]),m?Promise.all(l.map(e=>loadSkillsFromSkillsDir(e,"projectSettings"))):Promise.resolve([]),m?Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".context","skills"),"projectSettings"))):Promise.resolve([]),m?Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".claude","skills"),"projectSettings"))):Promise.resolve([]),a?Promise.resolve([]):loadSkillsFromCommandsDir(t)]),D=[...d,...u,...p.flat(),...f.flat(),...g.flat(),...k.flat(),...C],$=await Promise.all(D.map(({skill:t,filePath:o})=>"prompt"===t.type?async function(t){try{return await e(t)}catch{return null}}(o):Promise.resolve(null))),w=new Map,F=[];for(let e=0;e<D.length;e++){const t=D[e];if(void 0===t||"prompt"!==t.skill.type)continue;const{skill:o}=t,i=$[e];if(null==i){F.push(o);continue}const s=w.get(i);void 0===s?(w.set(i,o.source),F.push(o)):h(`Skipping duplicate skill '${o.name}' from ${o.source} (same file already loaded from ${s})`)}const P=D.length-F.length;P>0&&h(`Deduplicated ${P} skills (same file)`);const j=[],x=[];for(const e of F)"prompt"===e.type&&e.paths&&e.paths.length>0&&!Y.has(e.name)?x.push(e):j.push(e);for(const e of x)K.set(e.name,e);return x.length>0&&h(`[skills] ${x.length} conditional skills stored (activated when matching files are touched)`),h(`Loaded ${F.length} unique skills (${j.length} unconditional, ${x.length} conditional, managed: ${d.length}, user: ${u.length}, project: ${p.flat().length}, legacy project: ${f.flat().length}, additional: ${g.flat().length}, legacy additional: ${k.flat().length}, legacy commands: ${C.length})`),j});export function clearSkillCaches(){getSkillDirCommands.cache?.clear?.(),N.cache?.clear?.(),K.clear(),Y.clear()}export{getSkillDirCommands as getCommandDirCommands};export{clearSkillCaches as clearCommandCaches};export{transformSkillFiles};const R=new Set,W=new Map,K=new Map,Y=new Set,q=H();export function onDynamicSkillsLoaded(e){return q.subscribe(()=>{try{e()}catch(e){_(e)}})}export async function discoverSkillDirsForPaths(e,t){const o=x(),i=t.endsWith(r)?t.slice(0,-1):t,l=[];for(const t of e){let e=s(t);for(;e.startsWith(i+r);){const t=[n(e,".context","skills"),n(e,".claude","skills")];for(const s of t)if(!R.has(s)){R.add(s);try{if(await o.stat(s),await b(e,i)){h(`[skills] Skipped gitignored skills dir: ${s}`);continue}l.push(s)}catch{}}const r=s(e);if(r===e)break;e=r}}return l.sort((e,t)=>t.split(r).length-e.split(r).length)}export async function addSkillDirectories(e){if(!U("projectSettings")||O("skills"))return void h("[skills] Dynamic skill discovery skipped: projectSettings disabled or plugin-only policy");if(0===e.length)return;const t=new Set(W.keys()),o=await Promise.all(e.map(e=>loadSkillsFromSkillsDir(e,"projectSettings")));for(let e=o.length-1;e>=0;e--)for(const{skill:t}of o[e]??[])"prompt"===t.type&&W.set(t.name,t);const i=o.flat().length;if(i>0){const o=[...W.keys()].filter(e=>!t.has(e));h(`[skills] Dynamically discovered ${i} skills from ${e.length} directories`),o.length>0&&d("tengu_dynamic_skills_changed",{source:"file_operation",previousCount:t.size,newCount:W.size,addedCount:o.length,directoryCount:e.length})}q.emit()}export function getDynamicSkills(){return Array.from(W.values())}export function activateConditionalSkillsForPaths(e,o){if(0===K.size)return[];const i=[];for(const[s,n]of K){if("prompt"!==n.type||!n.paths||0===n.paths.length)continue;const r=t().add(n.paths);for(const t of e){const e=l(t)?a(o,t):t;if(e&&!e.startsWith("..")&&!l(e)&&r.ignores(e)){W.set(s,n),K.delete(s),Y.add(s),i.push(s),h(`[skills] Activated conditional skill '${s}' (matched path: ${e})`);break}}}return i.length>0&&(d("tengu_dynamic_skills_changed",{source:"conditional_paths",previousCount:W.size-i.length,newCount:W.size,addedCount:i.length,directoryCount:0}),q.emit()),i}export function getConditionalSkillCount(){return K.size}export function clearDynamicSkills(){R.clear(),W.clear(),K.clear(),Y.clear()}B({createSkillCommand,parseSkillFrontmatterFields});
|
|
1
|
+
import{realpath as e}from"fs/promises";import t from"ignore";import o from"lodash-es/memoize.js";import{basename as i,dirname as l,isAbsolute as s,join as n,sep as r,relative as a}from"path";import{getAdditionalDirectoriesForClaudeMd as c,getSessionId as m}from"../bootstrap/state.js";import{logEvent as d}from"../services/analytics/index.js";import{roughTokenCountEstimation as u}from"../services/tokenEstimation.js";import{parseArgumentNames as p,substituteArguments as f}from"../utils/argumentSubstitution.js";import{logForDebugging as h}from"../utils/debug.js";import{EFFORT_LEVELS as g,parseEffortValue as k}from"../utils/effort.js";import{getClaudeConfigHomeDir as S,isBareMode as y,isEnvTruthy as v}from"../utils/envUtils.js";import{isENOENT as C,isFsInaccessible as D}from"../utils/errors.js";import{coerceDescriptionToString as $,parseBooleanFrontmatter as w,parseFrontmatter as F,parseShellFrontmatter as P,splitPathInFrontmatter as j}from"../utils/frontmatterParser.js";import{getFsImplementation as x}from"../utils/fsOperations.js";import{isPathGitignored as b}from"../utils/git/gitignore.js";import{logError as _}from"../utils/log.js";import{extractDescriptionFromMarkdown as L,getProjectDirsUpToHome as I,loadMarkdownFilesForSubdir as N,parseSlashCommandToolsFromFrontmatter as E}from"../utils/markdownConfigLoader.js";import{parseUserSpecifiedModel as A}from"../utils/model/model.js";import{executeShellCommandsInPrompt as T}from"../utils/promptShellExecution.js";import{isSettingSourceEnabled as U}from"../utils/settings/constants.js";import{getManagedFilePath as M}from"../utils/settings/managedPath.js";import{isRestrictedToPluginOnly as O}from"../utils/settings/pluginOnlyPolicy.js";import{HooksSchema as z}from"../utils/settings/types.js";import{createSignal as H}from"../utils/signal.js";import{registerMCPSkillBuilders as B}from"./mcpSkillBuilders.js";export function getSkillsPath(e,t){switch(e){case"policySettings":return n(M(),".claude",t);case"userSettings":return n(S(),t);case"projectSettings":return`.context/${t}`;case"plugin":return"plugin";default:return""}}export function estimateSkillFrontmatterTokens(e){const t=[e.name,e.description,e.whenToUse].filter(Boolean).join(" ");return u(t)}function parseHooksFromFrontmatter(e,t){if(!e.hooks)return;const o=z().safeParse(e.hooks);if(o.success)return o.data;h(`Invalid hooks in skill '${t}': ${o.error.message}`)}export function parseSkillFrontmatterFields(e,t,o,i="Skill"){const l=$(e.description,o),s=l??L(t,i),n=void 0===e["user-invocable"]||w(e["user-invocable"]),r="inherit"===e.model?void 0:e.model?A(e.model):void 0,a=e.effort,c=void 0!==a?k(a):void 0;return void 0!==a&&void 0===c&&h(`Skill ${o} has invalid effort '${a}'. Valid options: ${g.join(", ")} or an integer`),{displayName:null!=e.name?String(e.name):void 0,description:s,hasUserSpecifiedDescription:null!==l,allowedTools:E(e["allowed-tools"]),argumentHint:null!=e["argument-hint"]?String(e["argument-hint"]):void 0,argumentNames:p(e.arguments),whenToUse:e.when_to_use,version:e.version,model:r,disableModelInvocation:w(e["disable-model-invocation"]),userInvocable:n,hooks:parseHooksFromFrontmatter(e,o),executionContext:"fork"===e.context?"fork":void 0,agent:e.agent,effort:c,shell:P(e.shell,o)}}export function createSkillCommand({skillName:e,displayName:t,description:o,hasUserSpecifiedDescription:i,markdownContent:l,allowedTools:s,argumentHint:n,argumentNames:r,whenToUse:a,version:c,model:d,disableModelInvocation:u,userInvocable:p,source:h,baseDir:g,loadedFrom:k,hooks:S,executionContext:y,agent:v,paths:C,effort:D,shell:$}){return{type:"prompt",name:e,description:o,hasUserSpecifiedDescription:i,allowedTools:s,argumentHint:n,argNames:r.length>0?r:void 0,whenToUse:a,version:c,model:d,disableModelInvocation:u,userInvocable:p,context:y,agent:v,effort:D,paths:C,contentLength:l.length,isHidden:!p,progressMessage:"running",userFacingName:()=>t||e,source:h,loadedFrom:k,hooks:S,skillRoot:g,async getPromptForCommand(t,o){let i=g?`Base directory for this skill: ${g}\n\n${l}`:l;if(i=f(i,t,!0,r),g){const e="win32"===process.platform?g.replace(/\\/g,"/"):g;i=i.replace(/\$\{CLAUDE_SKILL_DIR\}/g,e)}return i=i.replace(/\$\{CLAUDE_SESSION_ID\}/g,m()),"mcp"!==k&&(i=await T(i,{...o,getAppState(){const e=o.getAppState();return{...e,toolPermissionContext:{...e.toolPermissionContext,alwaysAllowRules:{...e.toolPermissionContext.alwaysAllowRules,command:s}}}}},`/${e}`,$)),[{type:"text",text:i}]}}}async function loadSkillsFromSkillsDir(e,t){const o=x();let i;try{i=await o.readdir(e)}catch(e){return D(e)||_(e),[]}return(await Promise.all(i.map(async i=>{try{if(!i.isDirectory()&&!i.isSymbolicLink())return null;const l=n(e,i.name),s=n(l,"SKILL.md");let r;try{r=await o.readFile(s,{encoding:"utf-8"})}catch(e){return C(e)||h(`[skills] failed to read ${s}: ${e}`,{level:"warn"}),null}const{frontmatter:a,content:c}=F(r,s),m=i.name,d=parseSkillFrontmatterFields(a,c,m),u=function(e){if(!e.paths)return;const t=j(e.paths).map(e=>e.endsWith("/**")?e.slice(0,-3):e).filter(e=>e.length>0);return 0===t.length||t.every(e=>"**"===e)?void 0:t}(a);return{skill:createSkillCommand({...d,skillName:m,markdownContent:c,source:t,baseDir:l,loadedFrom:"skills",paths:u}),filePath:s}}catch(e){return _(e),null}}))).filter(e=>null!==e)}function isSkillFile(e){return/^skill\.md$/i.test(i(e))}function transformSkillFiles(e){const t=new Map;for(const o of e){const e=l(o.filePath),i=t.get(e)??[];i.push(o),t.set(e,i)}const o=[];for(const[e,l]of t){const t=l.filter(e=>isSkillFile(e.filePath));if(t.length>0){const l=t[0];t.length>1&&h(`Multiple skill files found in ${e}, using ${i(l.filePath)}`),o.push(l)}else o.push(...l)}return o}function buildNamespace(e,t){const o=t.endsWith(r)?t.slice(0,-1):t;if(e===o)return"";const i=e.slice(o.length+1);return i?i.split(r).join(":"):""}function getCommandName(e){return isSkillFile(e.filePath)?function(e,t){const o=l(e),s=l(o),n=i(o),r=buildNamespace(s,t);return r?`${r}:${n}`:n}(e.filePath,e.baseDir):function(e,t){const o=i(e),s=l(e),n=o.replace(/\.md$/,""),r=buildNamespace(s,t);return r?`${r}:${n}`:n}(e.filePath,e.baseDir)}async function loadSkillsFromCommandsDir(e){try{const t=transformSkillFiles(await N("commands",e)),o=[];for(const{baseDir:e,filePath:i,frontmatter:s,content:n,source:r}of t)try{const t=isSkillFile(i)?l(i):void 0,a=getCommandName({baseDir:e,filePath:i,frontmatter:s,content:n,source:r}),c=parseSkillFrontmatterFields(s,n,a,"Custom command");o.push({skill:createSkillCommand({...c,skillName:a,displayName:void 0,markdownContent:n,source:r,baseDir:t,loadedFrom:"commands_DEPRECATED",paths:void 0}),filePath:i})}catch(e){_(e)}return o}catch(e){return _(e),[]}}export const getSkillDirCommands=o(async t=>{const o=n(S(),"skills"),i=n(M(),".contextcli","skills"),l=I("skills",t,".contextcli"),s=I("skills",t,".claude");h(`Loading skills from: managed=${i}, user=${o}, project=[${l.join(", ")}]`);const r=c(),a=O("skills"),m=U("projectSettings")&&!a;if(y()){if(0===r.length||!m)return h(`[bare] Skipping skill dir discovery (${0===r.length?"no --add-dir":"projectSettings disabled or skillsLocked"})`),[];return(await Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".contextcli","skills"),"projectSettings")))).flat().map(e=>e.skill)}const[d,u,p,f,g,k,C]=await Promise.all([v(process.env.CONTEXT_CODE_DISABLE_POLICY_SKILLS)||v(process.env.CLAUDE_CODE_DISABLE_POLICY_SKILLS)?Promise.resolve([]):loadSkillsFromSkillsDir(i,"policySettings"),U("userSettings")&&!a?loadSkillsFromSkillsDir(o,"userSettings"):Promise.resolve([]),m?Promise.all(l.map(e=>loadSkillsFromSkillsDir(e,"projectSettings"))):Promise.resolve([]),m?Promise.all(s.map(e=>loadSkillsFromSkillsDir(e,"projectSettings"))):Promise.resolve([]),m?Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".contextcli","skills"),"projectSettings"))):Promise.resolve([]),m?Promise.all(r.map(e=>loadSkillsFromSkillsDir(n(e,".claude","skills"),"projectSettings"))):Promise.resolve([]),a?Promise.resolve([]):loadSkillsFromCommandsDir(t)]),D=[...d,...u,...p.flat(),...f.flat(),...g.flat(),...k.flat(),...C],$=await Promise.all(D.map(({skill:t,filePath:o})=>"prompt"===t.type?async function(t){try{return await e(t)}catch{return null}}(o):Promise.resolve(null))),w=new Map,F=[];for(let e=0;e<D.length;e++){const t=D[e];if(void 0===t||"prompt"!==t.skill.type)continue;const{skill:o}=t,i=$[e];if(null==i){F.push(o);continue}const l=w.get(i);void 0===l?(w.set(i,o.source),F.push(o)):h(`Skipping duplicate skill '${o.name}' from ${o.source} (same file already loaded from ${l})`)}const P=D.length-F.length;P>0&&h(`Deduplicated ${P} skills (same file)`);const j=[],x=[];for(const e of F)"prompt"===e.type&&e.paths&&e.paths.length>0&&!Y.has(e.name)?x.push(e):j.push(e);for(const e of x)K.set(e.name,e);return x.length>0&&h(`[skills] ${x.length} conditional skills stored (activated when matching files are touched)`),h(`Loaded ${F.length} unique skills (${j.length} unconditional, ${x.length} conditional, managed: ${d.length}, user: ${u.length}, project: ${p.flat().length}, legacy project: ${f.flat().length}, additional: ${g.flat().length}, legacy additional: ${k.flat().length}, legacy commands: ${C.length})`),j});export function clearSkillCaches(){getSkillDirCommands.cache?.clear?.(),N.cache?.clear?.(),K.clear(),Y.clear()}export{getSkillDirCommands as getCommandDirCommands};export{clearSkillCaches as clearCommandCaches};export{transformSkillFiles};const R=new Set,W=new Map,K=new Map,Y=new Set,q=H();export function onDynamicSkillsLoaded(e){return q.subscribe(()=>{try{e()}catch(e){_(e)}})}export async function discoverSkillDirsForPaths(e,t){const o=x(),i=t.endsWith(r)?t.slice(0,-1):t,s=[];for(const t of e){let e=l(t);for(;e.startsWith(i+r);){const t=[n(e,".contextcli","skills"),n(e,".claude","skills")];for(const l of t)if(!R.has(l)){R.add(l);try{if(await o.stat(l),await b(e,i)){h(`[skills] Skipped gitignored skills dir: ${l}`);continue}s.push(l)}catch{}}const r=l(e);if(r===e)break;e=r}}return s.sort((e,t)=>t.split(r).length-e.split(r).length)}export async function addSkillDirectories(e){if(!U("projectSettings")||O("skills"))return void h("[skills] Dynamic skill discovery skipped: projectSettings disabled or plugin-only policy");if(0===e.length)return;const t=new Set(W.keys()),o=await Promise.all(e.map(e=>loadSkillsFromSkillsDir(e,"projectSettings")));for(let e=o.length-1;e>=0;e--)for(const{skill:t}of o[e]??[])"prompt"===t.type&&W.set(t.name,t);const i=o.flat().length;if(i>0){const o=[...W.keys()].filter(e=>!t.has(e));h(`[skills] Dynamically discovered ${i} skills from ${e.length} directories`),o.length>0&&d("tengu_dynamic_skills_changed",{source:"file_operation",previousCount:t.size,newCount:W.size,addedCount:o.length,directoryCount:e.length})}q.emit()}export function getDynamicSkills(){return Array.from(W.values())}export function activateConditionalSkillsForPaths(e,o){if(0===K.size)return[];const i=[];for(const[l,n]of K){if("prompt"!==n.type||!n.paths||0===n.paths.length)continue;const r=t().add(n.paths);for(const t of e){const e=s(t)?a(o,t):t;if(e&&!e.startsWith("..")&&!s(e)&&r.ignores(e)){W.set(l,n),K.delete(l),Y.add(l),i.push(l),h(`[skills] Activated conditional skill '${l}' (matched path: ${e})`);break}}}return i.length>0&&(d("tengu_dynamic_skills_changed",{source:"conditional_paths",previousCount:W.size-i.length,newCount:W.size,addedCount:i.length,directoryCount:0}),q.emit()),i}export function getConditionalSkillCount(){return K.size}export function clearDynamicSkills(){R.clear(),W.clear(),K.clear(),Y.clear()}B({createSkillCommand,parseSkillFrontmatterFields});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{join as e,normalize as t,sep as r}from"path";import{getProjectRoot as o}from"../../bootstrap/state.js";import{buildMemoryPrompt as n,ensureMemoryDirExists as s}from"../../memdir/memdir.js";import{getMemoryBaseDir as c}from"../../memdir/paths.js";import{getCwd as i}from"../../utils/cwd.js";import{findCanonicalGitRoot as m}from"../../utils/git.js";import{sanitizePath as a}from"../../utils/path.js";function resolveProjectAgentMemoryRoot(t){const r=i();return e(r,".
|
|
1
|
+
import{join as e,normalize as t,sep as r}from"path";import{getProjectRoot as o}from"../../bootstrap/state.js";import{buildMemoryPrompt as n,ensureMemoryDirExists as s}from"../../memdir/memdir.js";import{getMemoryBaseDir as c}from"../../memdir/paths.js";import{getCwd as i}from"../../utils/cwd.js";import{findCanonicalGitRoot as m}from"../../utils/git.js";import{sanitizePath as a}from"../../utils/path.js";function resolveProjectAgentMemoryRoot(t){const r=i();return e(r,".contextcli",t)}function getLocalAgentMemoryDir(t){const n=process.env.CONTEXT_CODE_REMOTE_MEMORY_DIR??process.env.CLAUDE_CODE_REMOTE_MEMORY_DIR;return n?e(n,"projects",a(m(o())??o()),"agent-memory-local",t)+r:e(resolveProjectAgentMemoryRoot("agent-memory-local"),t)+r}export function getAgentMemoryDir(t,o){const n=function(e){return e.replace(/:/g,"-")}(t);switch(o){case"project":return e(resolveProjectAgentMemoryRoot("agent-memory"),n)+r;case"local":return getLocalAgentMemoryDir(n);case"user":return e(c(),"agent-memory",n)+r}}export function isAgentMemoryPath(o){const n=t(o),s=c();if(n.startsWith(e(s,"agent-memory")+r))return!0;if(n.startsWith(e(i(),".contextcli","agent-memory")+r))return!0;const m=process.env.CONTEXT_CODE_REMOTE_MEMORY_DIR??process.env.CLAUDE_CODE_REMOTE_MEMORY_DIR;if(m){if(n.includes(r+"agent-memory-local"+r)&&n.startsWith(e(m,"projects")+r))return!0}else if(n.startsWith(e(i(),".contextcli","agent-memory-local")+r))return!0;return!1}export function getAgentMemoryEntrypoint(t,r){return e(getAgentMemoryDir(t,r),"MEMORY.md")}export function getMemoryScopeDisplay(t){switch(t){case"user":return`User (${e(c(),"agent-memory")}/)`;case"project":return"Project (.contextcli/agent-memory/)";case"local":return`Local (${getLocalAgentMemoryDir("...")})`;default:return"None"}}export function loadAgentMemoryPrompt(e,t){let r;switch(t){case"user":r="- Since this memory is user-scope, keep learnings general since they apply across all projects";break;case"project":r="- Since this memory is project-scope and shared with your team via version control, tailor your memories to this project";break;case"local":r="- Since this memory is local-scope (not checked into version control), tailor your memories to this project and machine"}const o=getAgentMemoryDir(e,t);s(o);const c=process.env.CONTEXT_COWORK_MEMORY_EXTRA_GUIDELINES??process.env.CLAUDE_COWORK_MEMORY_EXTRA_GUIDELINES;return n({displayName:"Persistent Agent Memory",memoryDir:o,extraGuidelines:c&&c.trim().length>0?[r,c]:[r]})}
|
package/dist/src/utils/auth.js
CHANGED
|
@@ -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 E,resolveProviderProfile as T}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 P}from"../services/oauth/getOauthProfile.js";import{getApiKeyFromFileDescriptor as x,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 Y}from"./debug.js";import{getClaudeConfigHomeDir as $,isBareMode as X,isEnvTruthy as B,isRunningOnHomespace as z}from"./envUtils.js";import{errorMessage as W}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 B(process.env.CONTEXT_CODE_REMOTE)||B(process.env.CLAUDE_CODE_REMOTE)||"claude-desktop"===process.env.CLAUDE_CODE_ENTRYPOINT}export function isAnthropicAuthEnabled(){if(X())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=B(process.env.CONTEXT_CODE_USE_BEDROCK)||B(process.env.CLAUDE_CODE_USE_BEDROCK)||B(process.env.CONTEXT_CODE_USE_VERTEX)||B(process.env.CLAUDE_CODE_USE_VERTEX)||B(process.env.CONTEXT_CODE_USE_FOUNDRY)||B(process.env.CLAUDE_CODE_USE_FOUNDRY)||h(e)||"custom-anthropic"===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(X())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}}const Ae={gmi:"GMI_API_KEY",novita:"NOVITA_API_KEY",stepfun:"STEPFUN_API_KEY",huggingface:"HF_TOKEN","opencode-zen":"OPENCODE_ZEN_API_KEY",arcee:"ARCEEAI_API_KEY",alibaba:"DASHSCOPE_API_KEY",kimi:"KIMI_API_KEY"};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)&&!shouldUseLegacyProviderOauthFallback(e))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(X())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=z()?void 0:process.env.ANTHROPIC_API_KEY;if(y()&&r)return{key:r,source:"ANTHROPIC_API_KEY"};if(B(process.env.CI)||"test"===process.env.NODE_ENV){const e=x();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=x();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(X())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;Y(`Found CLAUDE_CODE_API_KEY_HELPER_TTL_MS env var, but it was not a valid number. Got ${e}`,{level:"error"})}return 3e5}let de=null,fe=null,he=0;export function getApiKeyHelperElapsedMs(){const e=fe?.startedAt;return e?Date.now()-e:0}export async function getApiKeyFromApiKeyHelper(e){if(!getConfiguredApiKeyHelper())return null;const r=calculateApiKeyHelperTTL();return de?(Date.now()-de.timestamp<r||fe||(fe={promise:_runAndCache(e,!1,he),startedAt:null}),de.value):(fe||(fe={promise:_runAndCache(e,!0,he),startedAt:Date.now()}),fe.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!==he||null!==r&&(de={value:r,timestamp:Date.now()}),r}catch(e){if(s!==he)return" ";const t=e instanceof Error?e.message:String(e);return console.error(r.red(`apiKeyHelper failed: ${t}`)),Y(`Error getting API key from apiKeyHelper: ${t}`,{level:"error"}),!o&&de&&" "!==de.value?(de={...de,timestamp:Date.now()},de.value):(de={value:" ",timestamp:Date.now()}," ")}finally{s===he&&(fe=null)}}export function getApiKeyFromApiKeyHelperCached(){return de?.value??null}export function clearApiKeyHelperCache(){he++,de=null,fe=null}export function prefetchApiKeyFromApiKeyHelperIfSafe(e){isApiKeyHelperFromProjectOrLocalSettings()&&!G()||getApiKeyFromApiKeyHelper(e)}const _e=18e4;export function refreshAwsAuth(e){Y("Running AWS auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:_e});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),Y(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),Y(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)Y("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 Y("Fetching AWS caller identity for AWS auth refresh command"),await D(),Y("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 Y("Fetching AWS caller identity for credential export command"),await D(),Y("Fetched AWS caller identity, skipping AWS credential export command"),null}catch{try{Y("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 Y("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 ge=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 Oe=18e4;export function refreshGcpAuth(e){Y("Running GCP auth refresh command");const n=b.getInstance();return n.startAuthentication(),new Promise(o=>{const s=t(e,{timeout:Oe});s.stdout.on("data",e=>{const r=e.toString().trim();r&&(n.addOutput(r),Y(r,{level:"debug"}))}),s.stderr.on("data",e=>{const r=e.toString().trim();r&&(n.setError(r),Y(r,{level:"error"}))}),s.on("close",(e,t)=>{if(0===e)Y("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(Y("Checking GCP credentials validity for auth refresh"),await checkGcpCredentialsValid())return Y("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=E(e)?T(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(E(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:W(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:W(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:W(e)}),{success:!1,warning:"Failed to save OpenAI OAuth tokens"}}}export function getClaudeAIOAuthTokens(){if(X())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(X())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||getStoredProviderApiKey("openai",_("openai"))||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:W(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=ge.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:ge}),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 getXaiAccessToken(){return process.env.XAI_API_KEY||getStoredProviderApiKey("xai",_("xai"))||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"xai":return getXaiAccessToken();case"gmi":case"novita":case"stepfun":case"huggingface":case"opencode-zen":case"arcee":case"alibaba":case"kimi":{const r=Ae[e];return(r?process.env[r]:void 0)||getStoredProviderApiKey(e,_(e))||null}case"ollama":return getOllamaAccessToken();case"ollama-cloud":return getOllamaCloudAccessToken();case"custom-openai":return process.env.CUSTOM_OPENAI_API_KEY||getStoredProviderApiKey("custom-openai",_("custom-openai"))||null;case"custom-anthropic":return process.env.CUSTOM_ANTHROPIC_API_KEY||getStoredProviderApiKey("custom-anthropic",_("custom-anthropic"))||null;default:return getOpenAIAccessToken()}}export async function getOpenAIOAuthTokensAsync(){if(X())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 Ee=0;async function invalidateOAuthCacheIfDiskChanged(){try{const e="sqlite"===Q().name?ie():se(),{mtimeMs:r}=await s(e);r!==Ee&&(Ee=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(X())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 me=null,ye=null;export function checkAndRefreshOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(me)return me;const t=checkAndRefreshOAuthTokenIfNeededImpl(e,r);return me=t.finally(()=>{me=null}),me}return checkAndRefreshOAuthTokenIfNeededImpl(e,r)}export function checkAndRefreshOpenAIOAuthTokenIfNeeded(e=0,r=!1){if(0===e&&!r){if(ye)return ye;const t=checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,r);return ye=t.finally(()=>{ye=null}),ye}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=$();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:W(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=$();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!(B(process.env.CONTEXT_CODE_USE_BEDROCK)||B(process.env.CLAUDE_CODE_USE_BEDROCK)||B(process.env.CONTEXT_CODE_USE_VERTEX)||B(process.env.CLAUDE_CODE_USE_VERTEX)||B(process.env.CONTEXT_CODE_USE_FOUNDRY)||B(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!!(B(process.env.CONTEXT_CODE_USE_BEDROCK)||B(process.env.CLAUDE_CODE_USE_BEDROCK)||B(process.env.CONTEXT_CODE_USE_VERTEX)||B(process.env.CLAUDE_CODE_USE_VERTEX)||B(process.env.CONTEXT_CODE_USE_FOUNDRY)||B(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 ke=null,Ce=0;const ve=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||ve.toString());if(ke&&Date.now()-Ce<r)return ke;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 ke=t,Ce=Date.now(),ke}catch(e){throw J(new Error(`Error getting OpenTelemetry headers from otelHeadersHelper (in settings): ${W(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 P(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 t from"chalk";import{exec as r}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 h,isOpenAICompatibleProvider as f}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 k}from"../bootstrap/state.js";import{getMockSubscriptionType as y,shouldUseMockSubscription as C}from"../services/mockRateLimits.js";import{isOAuthTokenExpired as v,refreshOpenAIOAuthToken as I,refreshOAuthToken as K,shouldUseClaudeAIAuth as P}from"../services/oauth/client.js";import{getOauthProfileFromOauthToken as S}from"../services/oauth/getOauthProfile.js";import{getApiKeyFromFileDescriptor as x,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 b}from"./aws.js";import{AwsAuthStatusManager as U}from"./awsAuthStatusManager.js";import{clearBetasCaches as L}from"./betas.js";import{checkHasTrustDialogAccepted as j,getGlobalConfig as G,saveGlobalConfig as F}from"./config.js";import{logAntError as M,logForDebugging as Y}from"./debug.js";import{getClaudeConfigHomeDir as $,isBareMode as B,isEnvTruthy as X,isRunningOnHomespace as z}from"./envUtils.js";import{errorMessage as W}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 te}from"./secureStorage/keychainPrefetch.js";import{clearKeychainCache as re,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=h(),t=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)||f(e)||"custom-anthropic"===e,r=(ce()||{}).apiKeyHelper,n=process.env.ANTHROPIC_AUTH_TOKEN||r||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!(t||n&&!isManagedOAuthContext()||s&&!isManagedOAuthContext())}export function getAuthTokenSource(){const e=h();if(f(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 t=getClaudeAIOAuthTokens();return P(t?.scopes)&&t?.accessToken?{source:"claude.ai",hasToken:!0}:{source:"none",hasToken:!1}}const Ae={gmi:"GMI_API_KEY",novita:"NOVITA_API_KEY",stepfun:"STEPFUN_API_KEY",huggingface:"HF_TOKEN","opencode-zen":"OPENCODE_ZEN_API_KEY",arcee:"ARCEEAI_API_KEY",alibaba:"DASHSCOPE_API_KEY",kimi:"KIMI_API_KEY"};function getProviderOauthStorageKey(e){return"claude"===e?"claudeAiOauth":"openAiOauth"}function shouldUseLegacyProviderOauthFallback(e){return"openai"===e}export function getStoredProviderOAuthTokens(e,t){try{const r=Q().read();if(t){const n=r?.providerProfileOauth?.[t];if(n?.accessToken)return n;if(!O(e,t)&&!shouldUseLegacyProviderOauthFallback(e))return null}if("gemini-google"===e)return null;if(!shouldUseLegacyProviderOauthFallback(e))return null;const n=r?.[getProviderOauthStorageKey(e)];return n?.accessToken?n:null}catch{return null}}export function hasStoredProviderOAuthTokens(e,t){if(t)return Boolean(getStoredProviderOAuthTokens(e,t));try{const t=Q().read(),r=Object.entries(t?.providerProfileOauth??{}).some(([t,r])=>t.startsWith(`${e}/`)&&"object"==typeof r&&null!==r&&"string"==typeof r.accessToken&&r.accessToken.trim());return shouldUseLegacyProviderOauthFallback(e)?Boolean(r||t?.[getProviderOauthStorageKey(e)]?.accessToken):Boolean(r)}catch{return!1}}export async function renameProviderScopedCredentials(e,t){if(!e||!t||e===t)return;const r=Q(),n=r.read()||{},o={...n.providerProfileApiKeys??{}},s={...n.providerProfileOauth??{}};e in o&&(o[t]=o[e],delete o[e]),e in s&&(s[t]=s[e],delete s[e]);if(!r.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 t=Q(),r=t.read()||{},n={...r.providerProfileApiKeys??{}},o={...r.providerProfileOauth??{}};delete n[e],delete o[e];if(!t.update({...r,providerProfileApiKeys:n,providerProfileOauth:o}).success)throw new Error("No se pudieron eliminar las credenciales del perfil.")}export async function removeAllProviderScopedCredentials(){const e=Q(),t=e.read()||{};if(!e.update({...t,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:t}=getAnthropicApiKeyWithSource({skipRetrievingKeyFromApiKeyHelper:!0});return null!==e&&"none"!==t}export function getAnthropicApiKeyWithSource(e={}){if(f(h()))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 t=z()?void 0:process.env.ANTHROPIC_API_KEY;if(k()&&t)return{key:t,source:"ANTHROPIC_API_KEY"};if(X(process.env.CI)||"test"===process.env.NODE_ENV){const e=x();if(e)return{key:e,source:"ANTHROPIC_API_KEY"};if(!(t||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 t?{key:t,source:"ANTHROPIC_API_KEY"}:{key:null,source:"none"}}if(t&&G().customApiKeyResponses?.approved?.includes(R(t)))return{key:t,source:"ANTHROPIC_API_KEY"};const r=x();if(r)return{key:r,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 t=ae("projectSettings"),r=ae("localSettings");return t?.apiKeyHelper===e||r?.apiKeyHelper===e}function getConfiguredAwsAuthRefresh(){return(ce()||{}).awsAuthRefresh}export function isAwsAuthRefreshFromProjectSettings(){const e=getConfiguredAwsAuthRefresh();if(!e)return!1;const t=ae("projectSettings"),r=ae("localSettings");return t?.awsAuthRefresh===e||r?.awsAuthRefresh===e}function getConfiguredAwsCredentialExport(){return(ce()||{}).awsCredentialExport}export function isAwsCredentialExportFromProjectSettings(){const e=getConfiguredAwsCredentialExport();if(!e)return!1;const t=ae("projectSettings"),r=ae("localSettings");return t?.awsCredentialExport===e||r?.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 t=parseInt(e,10);if(!Number.isNaN(t)&&t>=0)return t;Y(`Found CLAUDE_CODE_API_KEY_HELPER_TTL_MS env var, but it was not a valid number. Got ${e}`,{level:"error"})}return 3e5}let de=null,he=null,fe=0;export function getApiKeyHelperElapsedMs(){const e=he?.startedAt;return e?Date.now()-e:0}export async function getApiKeyFromApiKeyHelper(e){if(!getConfiguredApiKeyHelper())return null;const t=calculateApiKeyHelperTTL();return de?(Date.now()-de.timestamp<t||he||(he={promise:_runAndCache(e,!1,fe),startedAt:null}),de.value):(he||(he={promise:_runAndCache(e,!0,fe),startedAt:Date.now()}),he.promise)}async function _runAndCache(r,o,s){try{const t=await async function(t){const r=getConfiguredApiKeyHelper();if(!r)return null;if(isApiKeyHelperFromProjectOrLocalSettings()){if(!j()&&!t){const t=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",t),a("tengu_apiKeyHelper_missing_trust11",{}),null}}const o=await n(r,{shell:!0,timeout:6e5,reject:!1});if(o.failed){const e=o.timedOut?"timed out":`exited ${o.exitCode}`,t=o.stderr?.trim();throw new Error(t?`${e}: ${t}`:e)}const s=o.stdout?.trim();if(!s)throw new Error("did not return a value");return s}(r);return s!==fe||null!==t&&(de={value:t,timestamp:Date.now()}),t}catch(e){if(s!==fe)return" ";const r=e instanceof Error?e.message:String(e);return console.error(t.red(`apiKeyHelper failed: ${r}`)),Y(`Error getting API key from apiKeyHelper: ${r}`,{level:"error"}),!o&&de&&" "!==de.value?(de={...de,timestamp:Date.now()},de.value):(de={value:" ",timestamp:Date.now()}," ")}finally{s===fe&&(he=null)}}export function getApiKeyFromApiKeyHelperCached(){return de?.value??null}export function clearApiKeyHelperCache(){fe++,de=null,he=null}export function prefetchApiKeyFromApiKeyHelperIfSafe(e){isApiKeyHelperFromProjectOrLocalSettings()&&!j()||getApiKeyFromApiKeyHelper(e)}const _e=18e4;export function refreshAwsAuth(e){Y("Running AWS auth refresh command");const n=U.getInstance();return n.startAuthentication(),new Promise(o=>{const s=r(e,{timeout:_e});s.stdout.on("data",e=>{const t=e.toString().trim();t&&(n.addOutput(t),Y(t,{level:"debug"}))}),s.stderr.on("data",e=>{const t=e.toString().trim();t&&(n.setError(t),Y(t,{level:"error"}))}),s.on("close",(e,r)=>{if(0===e)Y("AWS auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===r?t.red("AWS auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):t.red("Error running awsAuthRefresh (in settings or ~/.context.json):");console.error(e),n.endAuthentication(!1),o(!1)}})})}export const refreshAndGetAwsCredentials=Z(async()=>{const r=await async function(){const t=getConfiguredAwsAuthRefresh();if(!t)return!1;if(isAwsAuthRefreshFromProjectSettings()&&!j()&&!m()){const t=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",t),a("tengu_awsAuthRefresh_missing_trust",{}),!1}try{return Y("Fetching AWS caller identity for AWS auth refresh command"),await D(),Y("Fetched AWS caller identity, skipping AWS auth refresh command"),!1}catch{return refreshAwsAuth(t)}}(),o=await async function(){const r=getConfiguredAwsCredentialExport();if(!r)return null;if(isAwsCredentialExportFromProjectSettings()&&!j()&&!m()){const t=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",t),a("tengu_awsCredentialExport_missing_trust",{}),null}try{return Y("Fetching AWS caller identity for credential export command"),await D(),Y("Fetched AWS caller identity, skipping AWS credential export command"),null}catch{try{Y("Running AWS credential export command");const e=await n(r,{shell:!0,reject:!1});if(0!==e.exitCode||!e.stdout)throw new Error("awsCredentialExport did not return a valid value");const t=pe(e.stdout.trim());if(!b(t))throw new Error("awsCredentialExport did not return valid AWS STS output structure");return Y("AWS credentials retrieved from awsCredentialExport"),{accessKeyId:t.Credentials.AccessKeyId,secretAccessKey:t.Credentials.SecretAccessKey,sessionToken:t.Credentials.SessionToken}}catch(e){const r=t.red("Error getting AWS credentials from awsCredentialExport (in settings or ~/.context.json):");return e instanceof Error?console.error(r,e.message):console.error(r,e),null}}}();return(r||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 t=ae("projectSettings"),r=ae("localSettings");return t?.gcpAuthRefresh===e||r?.gcpAuthRefresh===e}const ge=l;export async function checkGcpCredentialsValid(){try{const{GoogleAuth:e}=await import("google-auth-library"),t=new e({scopes:["https://www.googleapis.com/auth/cloud-platform"]}),r=(async()=>{const e=await t.getClient();await e.getAccessToken()})(),n=ue(5e3).then(()=>{throw new GcpCredentialsTimeoutError("GCP credentials check timed out")});return await Promise.race([r,n]),!0}catch{return!1}}const Oe=18e4;export function refreshGcpAuth(e){Y("Running GCP auth refresh command");const n=U.getInstance();return n.startAuthentication(),new Promise(o=>{const s=r(e,{timeout:Oe});s.stdout.on("data",e=>{const t=e.toString().trim();t&&(n.addOutput(t),Y(t,{level:"debug"}))}),s.stderr.on("data",e=>{const t=e.toString().trim();t&&(n.setError(t),Y(t,{level:"error"}))}),s.on("close",(e,r)=>{if(0===e)Y("GCP auth refresh completed successfully"),n.endAuthentication(!0),o(!0);else{const e="SIGTERM"===r?t.red("GCP auth refresh timed out after 3 minutes. Run your auth command manually in a separate terminal."):t.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 t=getConfiguredGcpAuthRefresh();if(!t)return!1;if(isGcpAuthRefreshFromProjectSettings()&&!j()&&!m()){const t=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",t),a("tengu_gcpAuthRefresh_missing_trust",{}),!1}try{if(Y("Checking GCP credentials validity for auth refresh"),await checkGcpCredentialsValid())return Y("GCP credentials are valid, skipping auth refresh command"),!1}catch{}return refreshGcpAuth(t)}(),36e5);export function clearGcpCredentialsCache(){refreshGcpCredentialsIfNeeded.cache.clear()}export function prefetchGcpCredentialsIfSafe(){if(getConfiguredGcpAuthRefresh()){if(isGcpAuthRefreshFromProjectSettings()){if(!j()&&!m())return}refreshGcpCredentialsIfNeeded()}}export function prefetchAwsCredentialsAndBedRockInfoIfSafe(){const e=getConfiguredAwsAuthRefresh(),t=getConfiguredAwsCredentialExport();if(e||t){if(isAwsAuthRefreshFromProjectSettings()||isAwsCredentialExportFromProjectSettings()){if(!j()&&!m())return}refreshAndGetAwsCredentials(),d()}}export const getApiKeyFromConfigOrMacOSKeychain=i(()=>{if("darwin"===process.platform){const e=te();if(e){if(e.stdout)return{key:e.stdout,source:"/login managed key"}}else{const e=ne();try{const t=q(`security find-generic-password -a $USER -w -s "${e}"`);if(t)return{key:t,source:"/login managed key"}}catch(e){J(e)}}}const e=G();return e.primaryApiKey?{key:e.primaryApiKey,source:"/login managed key"}:null});function isValidApiKey(e){return/^[a-zA-Z0-9-_\.]+$/.test(e)}function getStoredProviderApiKey(e,t){try{const r=Q().read();if(t){const n=r?.providerProfileApiKeys?.[t];if("string"==typeof n&&n.trim())return n;if(!O(e,t))return null}return r?.providerApiKeys?.[e]??null}catch{return null}}export function hasStoredProviderApiKey(e,t){return Boolean(getStoredProviderApiKey(e,t))}export async function saveProviderApiKey(e,t){if(!isValidApiKey(t))throw new Error("Formato de clave API inválido. La clave API solo debe contener caracteres alfanuméricos, guiones, guiones bajos y puntos.");const r=Q(),n=r.read()||{},o=T(e)?E(e,{createIfMissing:!0})?.id??null:null;if(!r.update({...n,providerApiKeys:{...n.providerApiKeys??{},[e]:t},...o?{providerProfileApiKeys:{...n.providerProfileApiKeys??{},[o]:t}}:{}}).success)throw new Error(`Failed to save ${e} API key`)}export async function removeProviderApiKey(e){const t=Q(),r=t.read()||{},n={...r.providerApiKeys??{}};delete n[e];const o={...r.providerProfileApiKeys??{}};if(T(e)){const t=_(e);t&&delete o[t]}if(!t.update({...r,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 t=!1;if("darwin"===process.platform)try{const r=ne(),o=oe(),s=`add-generic-password -U -a "${o}" -s "${r}" -X "${Buffer.from(e,"utf-8").toString("hex")}"\n`;await n("security",["-i"],{input:s,reject:!1}),a("tengu_api_key_saved_to_keychain",{}),t=!0}catch(e){J(e),a("tengu_api_key_keychain_error",{error:W(e)}),a("tengu_api_key_saved_to_config",{})}else a("tengu_api_key_saved_to_config",{});const r=R(e);F(n=>{const o=n.customApiKeyResponses?.approved??[];return{...n,primaryApiKey:t?n.primaryApiKey:e,customApiKeyResponses:{...n.customApiKeyResponses,approved:o.includes(r)?o:[...o,r],rejected:n.customApiKeyResponses?.rejected??[]}}}),getApiKeyFromConfigOrMacOSKeychain.cache.clear?.(),ee()}export function isCustomApiKeyApproved(e){const t=G(),r=R(e);return t.customApiKeyResponses?.approved?.includes(r)??!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,t){if(!P(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 r=Q(),n=r.name;try{const o=r.read()||{},s=o.claudeAiOauth,i=t??_("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=r.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:W(e)}),{success:!1,warning:"Failed to save OAuth tokens"}}}export function saveOpenAIOAuthTokens(e,t){const r=Q(),n=r.name;try{const o=r.read()||{},s=t??_("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=r.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:W(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 t=isManagedOAuthContext()?w():null;if(t)return{accessToken:t,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||getStoredProviderApiKey("openai",_("openai"))||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(),t=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0,r=fetch("https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",{method:"POST",headers:e,body:JSON.stringify({cloudaicompanionProject:t,metadata:{ideType:"IDE_UNSPECIFIED",platform:"PLATFORM_UNSPECIFIED",pluginType:"GEMINI",duetProject:t},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([r,n]),!0}catch{return!1}}export function getGeminiGoogleOAuthTokens(){try{const e=_("gemini-google"),t=Q().read(),r=e?t?.providerProfileOauth?.[e]:null;if(r?.accessToken)return r;const n=Object.entries(t?.providerProfileOauth??{}).find(([e,t])=>e.startsWith("gemini-google/")&&"object"==typeof t&&null!==t&&"string"==typeof t.accessToken&&t.accessToken.trim())?.[1];return n?.accessToken?n:null}catch{return null}}export function saveGeminiGoogleOAuthTokens(e){const t=Q(),r=t.name;try{const n=t.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=t.update(n);return a(i.success?"tengu_gemini_google_oauth_tokens_saved":"tengu_gemini_google_oauth_tokens_save_failed",{storageBackend:r}),i}catch(e){return J(e),a("tengu_gemini_google_oauth_tokens_save_exception",{storageBackend:r,error:W(e)}),{success:!1,warning:"Failed to save Gemini OAuth tokens"}}}export function getCopilotOAuthTokens(){try{const e=_("copilot"),t=Q().read(),r=e?t?.providerProfileOauth?.[e]:null;if(r?.githubToken||r?.accessToken)return r;const n=Object.entries(t?.providerProfileOauth??{}).find(([e,t])=>e.startsWith("copilot/")&&"object"==typeof t&&null!==t&&("string"==typeof t.githubToken||"string"==typeof t.accessToken))?.[1];return n?.githubToken||n?.accessToken?n:null}catch{return null}}export function saveCopilotOAuthTokens(e){const t=Q(),r=t.name;try{const n=t.read()||{},o=_("copilot")??g("copilot").id,s={accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,scopes:e.scopes,subscriptionType:null,rateLimitTier:null,githubToken:e.githubToken};o&&(n.providerProfileOauth={...n.providerProfileOauth??{},[o]:s});const i=t.update(n);return a(i.success?"tengu_copilot_oauth_tokens_saved":"tengu_copilot_oauth_tokens_save_failed",{storageBackend:r}),i}catch(e){return J(e),a("tengu_copilot_oauth_tokens_save_exception",{storageBackend:r,error:W(e)}),{success:!1,warning:"Failed to save Copilot OAuth tokens"}}}export async function checkAndRefreshCopilotTokenIfNeeded(){const e=getCopilotOAuthTokens();if(!e)return null;const t=e.githubToken||e.accessToken;if(!t)return e;if(e.accessToken&&e.accessToken!==e.githubToken&&e.expiresAt&&e.expiresAt>Date.now()+6e4)return e;try{const r=await fetch("https://api.github.com/copilot_internal/v2/token",{method:"GET",headers:{Authorization:`token ${t}`,"User-Agent":"ContextCode/1.0",Accept:"application/json"}});if(!r.ok)return e;const n=await r.json(),o=n.expires_at?1e3*n.expires_at:Date.now()+15e5,s={...e,accessToken:n.token,githubToken:t,expiresAt:o};return saveCopilotOAuthTokens(s),s}catch{return e}}export function getCopilotAccessToken(){const e=process.env.GITHUB_COPILOT_TOKEN||process.env.COPILOT_OAUTH_TOKEN;if(e)return e;const t=getCopilotOAuthTokens();return t?.accessToken||t?.githubToken||null}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,t=ge.join(",");return`gcloud auth application-default login${e?` --client-id-file=${quoteShellArg(e)}`:""} --scopes=${quoteShellArg(t)}`}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,t={"Content-Type":"application/json"};if(e)t.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 t=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(!t.ok)return e;const r=await t.json(),n={...e,accessToken:r.access_token,expiresAt:r.expires_in?Date.now()+1e3*r.expires_in:e.expiresAt,scopes:r.scope?.split(/\s+/).filter(Boolean)??e.scopes};return saveGeminiGoogleOAuthTokens(n),n}();if(e?.accessToken){t.Authorization=`Bearer ${e.accessToken}`;const r=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim();r&&(t["x-goog-user-project"]=r)}else{const{GoogleAuth:e}=await import("google-auth-library"),r=new e({scopes:ge}),n=await r.getClient(),o=await n.getRequestHeaders();if("function"==typeof o.forEach)o.forEach((e,r)=>{t[r]=e});else for(const[e,r]of Object.entries(o))Array.isArray(r)?t[e]=r.map(String).join(", "):null!=r&&(t[e]=String(r))}}const r=process.env.GEMINI_GOOGLE_PROJECT_ID?.trim()||void 0;return r&&(t["x-goog-user-project"]=r),t}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 getXaiAccessToken(){return process.env.XAI_API_KEY||getStoredProviderApiKey("xai",_("xai"))||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=h()){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"xai":return getXaiAccessToken();case"copilot":return getCopilotAccessToken();case"gmi":case"novita":case"stepfun":case"huggingface":case"opencode-zen":case"arcee":case"alibaba":case"kimi":{const t=Ae[e];return(t?process.env[t]:void 0)||getStoredProviderApiKey(e,_(e))||null}case"ollama":return getOllamaAccessToken();case"ollama-cloud":return getOllamaCloudAccessToken();case"custom-openai":return process.env.CUSTOM_OPENAI_API_KEY||getStoredProviderApiKey("custom-openai",_("custom-openai"))||null;case"custom-anthropic":return process.env.CUSTOM_ANTHROPIC_API_KEY||getStoredProviderApiKey("custom-anthropic",_("custom-anthropic"))||null;default:return getOpenAIAccessToken()}}export async function getOpenAIOAuthTokensAsync(){if(B())return null;if(process.env.OPENAI_OAUTH_TOKEN)return getOpenAIOAuthTokens();try{const e=Q(),t=await e.readAsync(),r=_("openai"),n=r&&t?.providerProfileOauth?.[r]||(r&&!O("openai",r)?null:t?.openAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}export function clearOAuthTokenCache(){getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.(),re()}let Te=0;async function invalidateOAuthCacheIfDiskChanged(){try{const e="sqlite"===Q().name?ie():se(),{mtimeMs:t}=await s(e);t!==Te&&(Te=t,clearOAuthTokenCache())}catch{getClaudeAIOAuthTokens.cache?.clear?.(),getOpenAIOAuthTokens.cache?.clear?.()}}const Ee=new Map;export function handleOAuth401Error(e){const t=Ee.get(e);if(t)return t;const r=async function(e){clearOAuthTokenCache();const t=await getClaudeAIOAuthTokensAsync();if(!t?.refreshToken)return!1;if(t.accessToken!==e)return a("tengu_oauth_401_recovered_from_keychain",{}),!0;return checkAndRefreshOAuthTokenIfNeeded(0,!0)}(e).finally(()=>{Ee.delete(e)});return Ee.set(e,r),r}export async function handleOpenAIOAuth401Error(e){clearOAuthTokenCache();const t=await getOpenAIOAuthTokensAsync();return!!t?.refreshToken&&(t.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(),t=await e.readAsync(),r=_("claude"),n=r&&t?.providerProfileOauth?.[r]||(r&&!O("claude",r)?null:t?.claudeAiOauth);return n?.accessToken?n:null}catch(e){return J(e),null}}let me=null,ke=null;export function checkAndRefreshOAuthTokenIfNeeded(e=0,t=!1){if(0===e&&!t){if(me)return me;const r=checkAndRefreshOAuthTokenIfNeededImpl(e,t);return me=r.finally(()=>{me=null}),me}return checkAndRefreshOAuthTokenIfNeededImpl(e,t)}export function checkAndRefreshOpenAIOAuthTokenIfNeeded(e=0,t=!1){if(0===e&&!t){if(ke)return ke;const r=checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,t);return ke=r.finally(()=>{ke=null}),ke}return checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e,t)}async function checkAndRefreshOAuthTokenIfNeededImpl(e,t){await invalidateOAuthCacheIfDiskChanged();const r=getClaudeAIOAuthTokens();if(!(t||r?.refreshToken&&v(r.expiresAt)))return!1;if(!r?.refreshToken)return!1;if(!P(r.scopes))return!1;getClaudeAIOAuthTokens.cache?.clear?.(),re();const n=await getClaudeAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=$();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(r){return"ELOCKED"===r.code?e<5?(a("tengu_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOAuthTokenIfNeededImpl(e+1,t)):(a("tengu_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(r),a("tengu_oauth_token_refresh_lock_error",{error:W(r)}),!1)}try{getClaudeAIOAuthTokens.cache?.clear?.(),re();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:P(e.scopes)?void 0:e.scopes})),getClaudeAIOAuthTokens.cache?.clear?.(),re(),!0}catch(e){J(e),getClaudeAIOAuthTokens.cache?.clear?.(),re();const t=await getClaudeAIOAuthTokensAsync();return!(!t||v(t.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,t){await invalidateOAuthCacheIfDiskChanged();const r=getOpenAIOAuthTokens();if(!(t||r?.refreshToken&&v(r.expiresAt)))return!1;if(!r?.refreshToken)return!1;getOpenAIOAuthTokens.cache?.clear?.(),re();const n=await getOpenAIOAuthTokensAsync();if(!n?.refreshToken||!v(n.expiresAt))return!1;const s=$();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(r){return"ELOCKED"===r.code?e<5?(a("tengu_openai_oauth_token_refresh_lock_retry",{retryCount:e+1}),await ue(1e3+1e3*Math.random()),checkAndRefreshOpenAIOAuthTokenIfNeededImpl(e+1,t)):(a("tengu_openai_oauth_token_refresh_lock_retry_limit_reached",{maxRetries:5}),!1):(J(r),!1)}try{getOpenAIOAuthTokens.cache?.clear?.(),re();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?.(),re(),!0}catch(e){J(e),getOpenAIOAuthTokens.cache?.clear?.(),re();const t=await getOpenAIOAuthTokensAsync();return!(!t||v(t.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()&&P(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)||f(h()))&&!isClaudeAISubscriber()}export function getOauthAccountInfo(){return isAnthropicAuthEnabled()?G().oauthAccount:void 0}export function isOverageProvisioningAllowed(){const e=getOauthAccountInfo(),t=e?.billingType;return!(!isClaudeAISubscriber()||!t)&&("stripe_subscription"===t||"stripe_subscription_contracted"===t||"apple_subscription"===t||"google_play_subscription"===t)}export function hasOpusAccess(){const e=getSubscriptionType();return"max"===e||"enterprise"===e||"team"===e||"pro"===e||null===e}export function getSubscriptionType(){if(C())return y();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)||f(h()))}function getConfiguredOtelHeadersHelper(){return(ce()||{}).otelHeadersHelper}export function isOtelHeadersHelperFromProjectOrLocalSettings(){const e=getConfiguredOtelHeadersHelper();if(!e)return!1;const t=ae("projectSettings"),r=ae("localSettings");return t?.otelHeadersHelper===e||r?.otelHeadersHelper===e}let ye=null,Ce=0;const ve=174e4;export function getOtelHeadersFromHelper(){const e=getConfiguredOtelHeadersHelper();if(!e)return{};const t=parseInt(process.env.CONTEXT_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||process.env.CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS||ve.toString());if(ye&&Date.now()-Ce<t)return ye;if(isOtelHeadersHelperFromProjectOrLocalSettings()){if(!j())return{}}try{const t=q(e,{timeout:3e4})?.toString().trim();if(!t)throw new Error("otelHeadersHelper did not return a valid value");const r=pe(t);if("object"!=typeof r||null===r||Array.isArray(r))throw new Error("otelHeadersHelper must return a JSON object with string key-value pairs");for(const[e,t]of Object.entries(r))if("string"!=typeof t)throw new Error(`otelHeadersHelper returned non-string value for key "${e}": ${typeof t}`);return ye=r,Ce=Date.now(),ye}catch(e){throw J(new Error(`Error getting OpenTelemetry headers from otelHeadersHelper (in settings): ${W(e)}`)),e}}export function isConsumerSubscriber(){const e=getSubscriptionType();return isClaudeAISubscriber()&&null!==e&&("max"===(t=e)||"pro"===t);var t}export function getAccountInformation(){if("firstParty"!==h())return;const{source:e}=getAuthTokenSource(),t={};"CLAUDE_CODE_OAUTH_TOKEN"===e||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===e?t.tokenSource=e:isClaudeAISubscriber()?t.subscription=getSubscriptionName():t.tokenSource=e;const{key:r,source:n}=getAnthropicApiKeyWithSource();if(r&&(t.apiKeySource=n),"claude.ai"===e||"/login managed key"===n){const e=getOauthAccountInfo()?.organizationName;e&&(t.organization=e)}const o=getOauthAccountInfo()?.emailAddress;return"claude.ai"!==e&&"/login managed key"!==n||!o||(t.email=o),t}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 t=getClaudeAIOAuthTokens();if(!t)return{valid:!0};const{source:r}=getAuthTokenSource(),n="CLAUDE_CODE_OAUTH_TOKEN"===r||"CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR"===r,o=await S(t.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"===r?"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 s=t(import.meta.url);import o from"ignore";import n from"lodash-es/memoize.js";import{Lexer as r}from"marked";import{basename as i,dirname as c,extname as a,isAbsolute as l,join as u,parse as m,relative as p,sep as d}from"path";import f from"picomatch";import{logEvent as h}from"../services/analytics/index.js";import{getAdditionalDirectoriesForClaudeMd as y,getOriginalCwd as M}from"../bootstrap/state.js";import{truncateEntrypointContent as g}from"../memdir/memdir.js";import{getAutoMemEntrypoint as x,isAutoMemoryEnabled as E}from"../memdir/paths.js";import{getFeatureValue_CACHED_MAY_BE_STALE as C}from"../services/analytics/growthbook.js";import{getCurrentProjectConfig as w,getManagedClaudeRulesDir as j,getMemoryPath as _,getUserClaudeRulesDir as A}from"./config.js";import{logForDebugging as F}from"./debug.js";import{logForDiagnosticsNoPII as D}from"./diagLogs.js";import{getClaudeConfigHomeDir as P,isEnvTruthy as T}from"./envUtils.js";import{getErrnoCode as R}from"./errors.js";import{normalizePathForComparison as S}from"./file.js";import{cacheKeys as v}from"./fileStateCache.js";import{parseFrontmatter as I,splitPathInFrontmatter as L}from"./frontmatterParser.js";import{getFsImplementation as b,safeResolvePath as U}from"./fsOperations.js";import{findCanonicalGitRoot as O,findGitRoot as k}from"./git.js";import{executeInstructionsLoadedHooks as N,hasInstructionsLoadedHook as W}from"./hooks.js";import{expandPath as $}from"./path.js";import{pathInWorkingPath as X}from"./permissions/filesystem.js";import{isSettingSourceEnabled as H}from"./settings/constants.js";import{getInitialSettings as z}from"./settings/settings.js";const q=e("TEAMMEM")?s("../memdir/teamMemPaths.js"):null;let B=!1;export const MAX_MEMORY_CHARACTER_COUNT=4e4;const G=new Set([".md",".txt",".text",".json",".yaml",".yml",".toml",".xml",".csv",".html",".htm",".css",".scss",".sass",".less",".js",".ts",".tsx",".jsx",".mjs",".cjs",".mts",".cts",".py",".pyi",".pyw",".rb",".erb",".rake",".go",".rs",".java",".kt",".kts",".scala",".c",".cpp",".cc",".cxx",".h",".hpp",".hxx",".cs",".swift",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".env",".ini",".cfg",".conf",".config",".properties",".sql",".graphql",".gql",".proto",".vue",".svelte",".astro",".ejs",".hbs",".pug",".jade",".php",".pl",".pm",".lua",".r",".R",".dart",".ex",".exs",".erl",".hrl",".clj",".cljs",".cljc",".edn",".hs",".lhs",".elm",".ml",".mli",".f",".f90",".f95",".for",".cmake",".make",".makefile",".gradle",".sbt",".rst",".adoc",".asciidoc",".org",".tex",".latex",".lock",".log",".diff",".patch"]);function pathInOriginalCwd(e){return X(e,M())}export function stripHtmlComments(e){return e.includes("\x3c!--")?stripHtmlCommentsFromTokens(new r({gfm:!1}).lex(e)):{content:e,stripped:!1}}function stripHtmlCommentsFromTokens(e){let t="",s=!1;const o=/<!--[\s\S]*?-->/g;for(const n of e){if("html"===n.type){const e=n.raw.trimStart();if(e.startsWith("\x3c!--")&&e.includes("--\x3e")){const e=n.raw.replace(o,"");s=!0,e.trim().length>0&&(t+=e);continue}}t+=n.raw}return{content:t,stripped:s}}function parseMemoryFileContent(e,t,s,o){const n=a(t).toLowerCase();if(n&&!G.has(n))return F(`Skipping non-text file in @include: ${t}`),{info:null,includePaths:[]};const{content:i,paths:l}=function(e){const{frontmatter:t,content:s}=I(e);if(!t.paths)return{content:s};const o=L(t.paths).map(e=>e.endsWith("/**")?e.slice(0,-3):e).filter(e=>e.length>0);return 0===o.length||o.every(e=>"**"===e)?{content:s}:{content:s,paths:o}}(e),u=i.includes("\x3c!--"),m=u||void 0!==o?new r({gfm:!1}).lex(i):void 0,p=u&&m?stripHtmlCommentsFromTokens(m).content:i,d=m&&void 0!==o?function(e,t){const s=new Set;function extractPathsFromText(e){const o=/(?:^|\s)@((?:[^\s\\]|\\ )+)/g;let n;for(;null!==(n=o.exec(e));){let e=n[1];if(!e)continue;const o=e.indexOf("#");if(-1!==o&&(e=e.substring(0,o)),e&&(e=e.replace(/\\ /g," "),e)){if(e.startsWith("./")||e.startsWith("~/")||e.startsWith("/")&&"/"!==e||!e.startsWith("@")&&!e.match(/^[#%^&*()]+/)&&e.match(/^[a-zA-Z0-9._-]/)){const o=$(e,c(t));s.add(o)}}}}function processElements(e){for(const t of e)if("code"!==t.type&&"codespan"!==t.type){if("html"===t.type){const e=t.raw||"",s=e.trimStart();if(s.startsWith("\x3c!--")&&s.includes("--\x3e")){const t=/<!--[\s\S]*?-->/g,s=e.replace(t,"");s.trim().length>0&&extractPathsFromText(s)}continue}"text"===t.type&&extractPathsFromText(t.text||""),t.tokens&&processElements(t.tokens),t.items&&processElements(t.items)}}return processElements(e),[...s]}(m,o):[];let f=p;"AutoMem"!==s&&"TeamMem"!==s||(f=g(p).content);const h=f!==e;return{info:{path:t,type:s,content:f,globs:l,contentDiffersFromDisk:h,rawContent:h?e:void 0},includePaths:d}}async function safelyReadMemoryFileAsync(e,t,s){try{const o=b();return parseMemoryFileContent(await o.readFile(e,{encoding:"utf-8"}),e,t,s)}catch(t){return function(e,t){const s=R(e);"ENOENT"!==s&&"EISDIR"!==s&&"EACCES"===s&&h("tengu_claude_md_permission_error",{is_access_error:1,has_home_dir:t.includes(P())?1:0})}(t,e),{info:null,includePaths:[]}}}function isClaudeMdExcluded(e,t){if("User"!==t&&"Project"!==t&&"Local"!==t)return!1;const s=z().claudeMdExcludes;if(!s||0===s.length)return!1;const o=e.replaceAll("\\","/"),n=function(e){const t=b(),s=e.map(e=>e.replaceAll("\\","/"));for(const e of s){if(!e.startsWith("/"))continue;const o=e.search(/[*?{[]/),n=-1===o?e:e.slice(0,o),r=c(n);try{const o=t.realpathSync(r).replaceAll("\\","/");if(o!==r){const t=o+e.slice(r.length);s.push(t)}}catch{}}return s}(s).filter(e=>e.length>0);return 0!==n.length&&f.isMatch(o,n,{dot:!0})}export async function processMemoryFile(e,t,s,o,n=0,r){const i=S(e);if(s.has(i)||n>=5)return[];if(isClaudeMdExcluded(e,t))return[];const{resolvedPath:c,isSymlink:a}=U(b(),e);s.add(i),a&&s.add(S(c));const{info:l,includePaths:u}=await safelyReadMemoryFileAsync(e,t,c);if(!l||!l.content.trim())return[];r&&(l.parent=r);const m=[];m.push(l);for(const r of u){if(!pathInOriginalCwd(r)&&!o)continue;const i=await processMemoryFile(r,t,s,o,n+1,e);m.push(...i)}return m}export async function processMdRules({rulesDir:e,type:t,processedPaths:s,includeExternal:o,conditionalRule:n,visitedDirs:r=new Set}){if(r.has(e))return[];try{const i=b(),{resolvedPath:c,isSymlink:a}=U(i,dotContextRulesDir);r.add(e),a&&r.add(c);const l=[];let m;try{m=await i.readdir(c)}catch(e){const t=R(e);if("ENOENT"===t||"EACCES"===t||"ENOTDIR"===t)return[];throw e}for(const c of m){const a=u(e,c.name),{resolvedPath:m,isSymlink:p}=U(i,a),d=p?await i.stat(m):null,f=d?d.isDirectory():c.isDirectory(),h=d?d.isFile():c.isFile();if(f)l.push(...await processMdRules({rulesDir:m,type:t,processedPaths:s,includeExternal:o,conditionalRule:n,visitedDirs:r}));else if(h&&c.name.endsWith(".md")){const e=await processMemoryFile(m,t,s,o);l.push(...e.filter(e=>n?e.globs:!e.globs))}}return l}catch(t){return t instanceof Error&&t.message.includes("EACCES")&&h("tengu_claude_rules_md_permission_error",{is_access_error:1,has_home_dir:e.includes(P())?1:0}),[]}}export const getMemoryFiles=n(async(t=!1)=>{const s=Date.now();D("info","memory_files_started");const o=[],n=new Set,r=w(),i=t||r.hasClaudeMdExternalIncludesApproved||!1,a=_("Managed");o.push(...await processMemoryFile(a,"Managed",n,i));const l=j();if(o.push(...await processMdRules({rulesDir:l,type:"Managed",processedPaths:n,includeExternal:i,conditionalRule:!1})),H("userSettings")){const e=_("User");o.push(...await processMemoryFile(e,"User",n,!0));const t=A();o.push(...await processMdRules({rulesDir:t,type:"User",processedPaths:n,includeExternal:!0,conditionalRule:!1}))}const p=[],d=M();let f=d;for(;f!==m(f).root;)p.push(f),f=c(f);const g=k(d),C=O(d),F=null!==g&&null!==C&&S(g)!==S(C)&&X(g,C);for(const e of p.reverse()){const t=F&&X(e,C)&&!X(e,g);if(H("projectSettings")&&!t){const t=u(e,"CLAUDE.md");o.push(...await processMemoryFile(t,"Project",n,i));const s=u(e,".context","CONTEXT.md");o.push(...await processMemoryFile(s,"Project",n,i));const r=u(e,".context","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",n,i));const c=u(e,".context","rules");o.push(...await processMdRules({rulesDir:c,type:"Project",processedPaths:n,includeExternal:i,conditionalRule:!1}))}if(H("localSettings")){const t=u(e,"CLAUDE.local.md");o.push(...await processMemoryFile(t,"Local",n,i))}}if(T(process.env.CONTEXT_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD)||T(process.env.CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD)){const e=y();for(const t of e){const e=u(t,"CLAUDE.md");o.push(...await processMemoryFile(e,"Project",n,i));const s=u(t,".context","CONTEXT.md");o.push(...await processMemoryFile(s,"Project",n,i));const r=u(t,".context","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",n,i));const c=u(t,".context","rules");o.push(...await processMdRules({rulesDir:c,type:"Project",processedPaths:n,includeExternal:i,conditionalRule:!1}))}}if(E()){const{info:e}=await safelyReadMemoryFileAsync(x(),"AutoMem");if(e){const t=S(e.path);n.has(t)||(n.add(t),o.push(e))}}if(e("TEAMMEM")&&q.isTeamMemoryEnabled()){const{info:e}=await safelyReadMemoryFileAsync(q.getTeamMemEntrypoint(),"TeamMem");if(e){const t=S(e.path);n.has(t)||(n.add(t),o.push(e))}}const P=o.reduce((e,t)=>e+t.content.length,0);D("info","memory_files_completed",{duration_ms:Date.now()-s,file_count:o.length,total_content_length:P});const R={};for(const e of o)R[e.type]=(R[e.type]??0)+1;if(B||(B=!0,h("tengu_claudemd__initial_load",{file_count:o.length,total_content_length:P,user_count:R.User??0,project_count:R.Project??0,local_count:R.Local??0,managed_count:R.Managed??0,automem_count:R.AutoMem??0,...e("TEAMMEM")?{teammem_count:R.TeamMem??0}:{},duration_ms:Date.now()-s})),!t){const e=function(){if(!Y)return;Y=!1;const e=V;return V="session_start",e}();if(void 0!==e&&W())for(const t of o){if(!isInstructionsMemoryType(t.type))continue;const s=t.parent?"include":e;N(t.path,t.type,s,{globs:t.globs,parentFilePath:t.parent})}}return o});function isInstructionsMemoryType(e){return"User"===e||"Project"===e||"Local"===e||"Managed"===e}let V="session_start",Y=!0;export function clearMemoryFileCaches(){getMemoryFiles.cache?.clear?.()}export function resetGetMemoryFilesCache(e="session_start"){V=e,Y=!0,clearMemoryFileCaches()}export function getLargeMemoryFiles(e){return e.filter(e=>e.content.length>4e4)}export function filterInjectedMemoryFiles(e){return C("tengu_moth_copse",!1)?e.filter(e=>"AutoMem"!==e.type&&"TeamMem"!==e.type):e}export const getClaudeMds=(t,s)=>{const o=[],n=C("tengu_paper_halyard",!1);for(const r of t)if((!s||s(r.type))&&(!n||"Project"!==r.type&&"Local"!==r.type)&&r.content){const t="Project"===r.type?" (project instructions, checked into the codebase)":"Local"===r.type?" (user's private project instructions, not checked in)":e("TEAMMEM")&&"TeamMem"===r.type?" (shared team memory, synced across the organization)":"AutoMem"===r.type?" (user's auto-memory, persists across conversations)":" (user's private global instructions for all projects)",s=r.content.trim();e("TEAMMEM")&&"TeamMem"===r.type?o.push(`Contents of ${r.path}${t}:\n\n<team-memory-content source="shared">\n${s}\n</team-memory-content>`):o.push(`Contents of ${r.path}${t}:\n\n${s}`)}return 0===o.length?"":`Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.\n\n${o.join("\n\n")}`};export async function getManagedAndUserConditionalRules(e,t){const s=[],o=j();if(s.push(...await processConditionedMdRules(e,o,"Managed",t,!1)),H("userSettings")){const o=A();s.push(...await processConditionedMdRules(e,o,"User",t,!0))}return s}export async function getMemoryFilesForNestedDirectory(e,t,s){const o=[];if(H("projectSettings")){const t=u(e,"CLAUDE.md");o.push(...await processMemoryFile(t,"Project",s,!1));const n=u(e,".context","CONTEXT.md");o.push(...await processMemoryFile(n,"Project",s,!1));const r=u(e,".context","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",s,!1))}if(H("localSettings")){const t=u(e,"CLAUDE.local.md");o.push(...await processMemoryFile(t,"Local",s,!1))}const n=u(e,".context","rules"),r=new Set(s);o.push(...await processMdRules({dotContextRulesDir:n,type:"Project",processedPaths:r,includeExternal:!1,conditionalRule:!1})),o.push(...await processConditionedMdRules(t,n,"Project",s,!1));for(const e of r)s.add(e);return o}export async function getConditionalRulesForCwdLevelDirectory(e,t,s){return processConditionedMdRules(t,u(e,".context","rules"),"Project",s,!1)}export async function processConditionedMdRules(e,t,s,n,r){return(await processMdRules({rulesDir:t,type:s,processedPaths:n,includeExternal:r,conditionalRule:!0})).filter(n=>{if(!n.globs||0===n.globs.length)return!1;const r="Project"===s?c(c(t)):M(),i=l(e)?p(r,e):e;return!(!i||i.startsWith("..")||l(i))&&o().add(n.globs).ignores(i)})}export function getExternalClaudeMdIncludes(e){const t=[];for(const s of e)"User"!==s.type&&s.parent&&!pathInOriginalCwd(s.path)&&t.push({path:s.path,parent:s.parent});return t}export function hasExternalClaudeMdIncludes(e){return getExternalClaudeMdIncludes(e).length>0}export async function shouldShowClaudeMdExternalIncludesWarning(){const e=w();return!e.hasClaudeMdExternalIncludesApproved&&!e.hasClaudeMdExternalIncludesWarningShown&&hasExternalClaudeMdIncludes(await getMemoryFiles(!0))}export function isMemoryFilePath(e){const t=i(e);return"CLAUDE.md"===t||"CLAUDE.local.md"===t||(!("CONTEXT.md"!==t||!e.includes(`${d}.context${d}`))||!(!t.endsWith(".md")||!e.includes(`${d}.context${d}rules${d}`)))}export function getAllMemoryFilePaths(e,t){const s=new Set;for(const t of e)t.content.trim().length>0&&s.add(t.path);for(const e of v(t))isMemoryFilePath(e)&&s.add(e);return Array.from(s)}
|
|
1
|
+
import{feature as e}from"../recovery/bunBundleShim.js";import{createRequire as t}from"module";const s=t(import.meta.url);import o from"ignore";import n from"lodash-es/memoize.js";import{Lexer as r}from"marked";import{basename as i,dirname as c,extname as a,isAbsolute as l,join as u,parse as m,relative as p,sep as d}from"path";import f from"picomatch";import{logEvent as h}from"../services/analytics/index.js";import{getAdditionalDirectoriesForClaudeMd as y,getOriginalCwd as M}from"../bootstrap/state.js";import{truncateEntrypointContent as g}from"../memdir/memdir.js";import{getAutoMemEntrypoint as x,isAutoMemoryEnabled as E}from"../memdir/paths.js";import{getFeatureValue_CACHED_MAY_BE_STALE as C}from"../services/analytics/growthbook.js";import{getCurrentProjectConfig as w,getManagedClaudeRulesDir as j,getMemoryPath as _,getUserClaudeRulesDir as A}from"./config.js";import{logForDebugging as F}from"./debug.js";import{logForDiagnosticsNoPII as D}from"./diagLogs.js";import{getClaudeConfigHomeDir as P,isEnvTruthy as T}from"./envUtils.js";import{getErrnoCode as R}from"./errors.js";import{normalizePathForComparison as S}from"./file.js";import{cacheKeys as v}from"./fileStateCache.js";import{parseFrontmatter as I,splitPathInFrontmatter as L}from"./frontmatterParser.js";import{getFsImplementation as b,safeResolvePath as U}from"./fsOperations.js";import{findCanonicalGitRoot as O,findGitRoot as k}from"./git.js";import{executeInstructionsLoadedHooks as N,hasInstructionsLoadedHook as W}from"./hooks.js";import{expandPath as $}from"./path.js";import{pathInWorkingPath as X}from"./permissions/filesystem.js";import{isSettingSourceEnabled as H}from"./settings/constants.js";import{getInitialSettings as z}from"./settings/settings.js";const q=e("TEAMMEM")?s("../memdir/teamMemPaths.js"):null;let B=!1;export const MAX_MEMORY_CHARACTER_COUNT=4e4;const G=new Set([".md",".txt",".text",".json",".yaml",".yml",".toml",".xml",".csv",".html",".htm",".css",".scss",".sass",".less",".js",".ts",".tsx",".jsx",".mjs",".cjs",".mts",".cts",".py",".pyi",".pyw",".rb",".erb",".rake",".go",".rs",".java",".kt",".kts",".scala",".c",".cpp",".cc",".cxx",".h",".hpp",".hxx",".cs",".swift",".sh",".bash",".zsh",".fish",".ps1",".bat",".cmd",".env",".ini",".cfg",".conf",".config",".properties",".sql",".graphql",".gql",".proto",".vue",".svelte",".astro",".ejs",".hbs",".pug",".jade",".php",".pl",".pm",".lua",".r",".R",".dart",".ex",".exs",".erl",".hrl",".clj",".cljs",".cljc",".edn",".hs",".lhs",".elm",".ml",".mli",".f",".f90",".f95",".for",".cmake",".make",".makefile",".gradle",".sbt",".rst",".adoc",".asciidoc",".org",".tex",".latex",".lock",".log",".diff",".patch"]);function pathInOriginalCwd(e){return X(e,M())}export function stripHtmlComments(e){return e.includes("\x3c!--")?stripHtmlCommentsFromTokens(new r({gfm:!1}).lex(e)):{content:e,stripped:!1}}function stripHtmlCommentsFromTokens(e){let t="",s=!1;const o=/<!--[\s\S]*?-->/g;for(const n of e){if("html"===n.type){const e=n.raw.trimStart();if(e.startsWith("\x3c!--")&&e.includes("--\x3e")){const e=n.raw.replace(o,"");s=!0,e.trim().length>0&&(t+=e);continue}}t+=n.raw}return{content:t,stripped:s}}function parseMemoryFileContent(e,t,s,o){const n=a(t).toLowerCase();if(n&&!G.has(n))return F(`Skipping non-text file in @include: ${t}`),{info:null,includePaths:[]};const{content:i,paths:l}=function(e){const{frontmatter:t,content:s}=I(e);if(!t.paths)return{content:s};const o=L(t.paths).map(e=>e.endsWith("/**")?e.slice(0,-3):e).filter(e=>e.length>0);return 0===o.length||o.every(e=>"**"===e)?{content:s}:{content:s,paths:o}}(e),u=i.includes("\x3c!--"),m=u||void 0!==o?new r({gfm:!1}).lex(i):void 0,p=u&&m?stripHtmlCommentsFromTokens(m).content:i,d=m&&void 0!==o?function(e,t){const s=new Set;function extractPathsFromText(e){const o=/(?:^|\s)@((?:[^\s\\]|\\ )+)/g;let n;for(;null!==(n=o.exec(e));){let e=n[1];if(!e)continue;const o=e.indexOf("#");if(-1!==o&&(e=e.substring(0,o)),e&&(e=e.replace(/\\ /g," "),e)){if(e.startsWith("./")||e.startsWith("~/")||e.startsWith("/")&&"/"!==e||!e.startsWith("@")&&!e.match(/^[#%^&*()]+/)&&e.match(/^[a-zA-Z0-9._-]/)){const o=$(e,c(t));s.add(o)}}}}function processElements(e){for(const t of e)if("code"!==t.type&&"codespan"!==t.type){if("html"===t.type){const e=t.raw||"",s=e.trimStart();if(s.startsWith("\x3c!--")&&s.includes("--\x3e")){const t=/<!--[\s\S]*?-->/g,s=e.replace(t,"");s.trim().length>0&&extractPathsFromText(s)}continue}"text"===t.type&&extractPathsFromText(t.text||""),t.tokens&&processElements(t.tokens),t.items&&processElements(t.items)}}return processElements(e),[...s]}(m,o):[];let f=p;"AutoMem"!==s&&"TeamMem"!==s||(f=g(p).content);const h=f!==e;return{info:{path:t,type:s,content:f,globs:l,contentDiffersFromDisk:h,rawContent:h?e:void 0},includePaths:d}}async function safelyReadMemoryFileAsync(e,t,s){try{const o=b();return parseMemoryFileContent(await o.readFile(e,{encoding:"utf-8"}),e,t,s)}catch(t){return function(e,t){const s=R(e);"ENOENT"!==s&&"EISDIR"!==s&&"EACCES"===s&&h("tengu_claude_md_permission_error",{is_access_error:1,has_home_dir:t.includes(P())?1:0})}(t,e),{info:null,includePaths:[]}}}function isClaudeMdExcluded(e,t){if("User"!==t&&"Project"!==t&&"Local"!==t)return!1;const s=z().claudeMdExcludes;if(!s||0===s.length)return!1;const o=e.replaceAll("\\","/"),n=function(e){const t=b(),s=e.map(e=>e.replaceAll("\\","/"));for(const e of s){if(!e.startsWith("/"))continue;const o=e.search(/[*?{[]/),n=-1===o?e:e.slice(0,o),r=c(n);try{const o=t.realpathSync(r).replaceAll("\\","/");if(o!==r){const t=o+e.slice(r.length);s.push(t)}}catch{}}return s}(s).filter(e=>e.length>0);return 0!==n.length&&f.isMatch(o,n,{dot:!0})}export async function processMemoryFile(e,t,s,o,n=0,r){const i=S(e);if(s.has(i)||n>=5)return[];if(isClaudeMdExcluded(e,t))return[];const{resolvedPath:c,isSymlink:a}=U(b(),e);s.add(i),a&&s.add(S(c));const{info:l,includePaths:u}=await safelyReadMemoryFileAsync(e,t,c);if(!l||!l.content.trim())return[];r&&(l.parent=r);const m=[];m.push(l);for(const r of u){if(!pathInOriginalCwd(r)&&!o)continue;const i=await processMemoryFile(r,t,s,o,n+1,e);m.push(...i)}return m}export async function processMdRules({rulesDir:e,type:t,processedPaths:s,includeExternal:o,conditionalRule:n,visitedDirs:r=new Set}){if(r.has(e))return[];try{const i=b(),{resolvedPath:c,isSymlink:a}=U(i,dotContextRulesDir);r.add(e),a&&r.add(c);const l=[];let m;try{m=await i.readdir(c)}catch(e){const t=R(e);if("ENOENT"===t||"EACCES"===t||"ENOTDIR"===t)return[];throw e}for(const c of m){const a=u(e,c.name),{resolvedPath:m,isSymlink:p}=U(i,a),d=p?await i.stat(m):null,f=d?d.isDirectory():c.isDirectory(),h=d?d.isFile():c.isFile();if(f)l.push(...await processMdRules({rulesDir:m,type:t,processedPaths:s,includeExternal:o,conditionalRule:n,visitedDirs:r}));else if(h&&c.name.endsWith(".md")){const e=await processMemoryFile(m,t,s,o);l.push(...e.filter(e=>n?e.globs:!e.globs))}}return l}catch(t){return t instanceof Error&&t.message.includes("EACCES")&&h("tengu_claude_rules_md_permission_error",{is_access_error:1,has_home_dir:e.includes(P())?1:0}),[]}}export const getMemoryFiles=n(async(t=!1)=>{const s=Date.now();D("info","memory_files_started");const o=[],n=new Set,r=w(),i=t||r.hasClaudeMdExternalIncludesApproved||!1,a=_("Managed");o.push(...await processMemoryFile(a,"Managed",n,i));const l=j();if(o.push(...await processMdRules({rulesDir:l,type:"Managed",processedPaths:n,includeExternal:i,conditionalRule:!1})),H("userSettings")){const e=_("User");o.push(...await processMemoryFile(e,"User",n,!0));const t=A();o.push(...await processMdRules({rulesDir:t,type:"User",processedPaths:n,includeExternal:!0,conditionalRule:!1}))}const p=[],d=M();let f=d;for(;f!==m(f).root;)p.push(f),f=c(f);const g=k(d),C=O(d),F=null!==g&&null!==C&&S(g)!==S(C)&&X(g,C);for(const e of p.reverse()){const t=F&&X(e,C)&&!X(e,g);if(H("projectSettings")&&!t){const t=u(e,"CLAUDE.md");o.push(...await processMemoryFile(t,"Project",n,i));const s=u(e,".contextcli","CONTEXT.md");o.push(...await processMemoryFile(s,"Project",n,i));const r=u(e,".contextcli","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",n,i));const c=u(e,".contextcli","rules");o.push(...await processMdRules({rulesDir:c,type:"Project",processedPaths:n,includeExternal:i,conditionalRule:!1}))}if(H("localSettings")){const t=u(e,"CLAUDE.local.md");o.push(...await processMemoryFile(t,"Local",n,i))}}if(T(process.env.CONTEXT_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD)||T(process.env.CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD)){const e=y();for(const t of e){const e=u(t,"CLAUDE.md");o.push(...await processMemoryFile(e,"Project",n,i));const s=u(t,".contextcli","CONTEXT.md");o.push(...await processMemoryFile(s,"Project",n,i));const r=u(t,".contextcli","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",n,i));const c=u(t,".contextcli","rules");o.push(...await processMdRules({rulesDir:c,type:"Project",processedPaths:n,includeExternal:i,conditionalRule:!1}))}}if(E()){const{info:e}=await safelyReadMemoryFileAsync(x(),"AutoMem");if(e){const t=S(e.path);n.has(t)||(n.add(t),o.push(e))}}if(e("TEAMMEM")&&q.isTeamMemoryEnabled()){const{info:e}=await safelyReadMemoryFileAsync(q.getTeamMemEntrypoint(),"TeamMem");if(e){const t=S(e.path);n.has(t)||(n.add(t),o.push(e))}}const P=o.reduce((e,t)=>e+t.content.length,0);D("info","memory_files_completed",{duration_ms:Date.now()-s,file_count:o.length,total_content_length:P});const R={};for(const e of o)R[e.type]=(R[e.type]??0)+1;if(B||(B=!0,h("tengu_claudemd__initial_load",{file_count:o.length,total_content_length:P,user_count:R.User??0,project_count:R.Project??0,local_count:R.Local??0,managed_count:R.Managed??0,automem_count:R.AutoMem??0,...e("TEAMMEM")?{teammem_count:R.TeamMem??0}:{},duration_ms:Date.now()-s})),!t){const e=function(){if(!Y)return;Y=!1;const e=V;return V="session_start",e}();if(void 0!==e&&W())for(const t of o){if(!isInstructionsMemoryType(t.type))continue;const s=t.parent?"include":e;N(t.path,t.type,s,{globs:t.globs,parentFilePath:t.parent})}}return o});function isInstructionsMemoryType(e){return"User"===e||"Project"===e||"Local"===e||"Managed"===e}let V="session_start",Y=!0;export function clearMemoryFileCaches(){getMemoryFiles.cache?.clear?.()}export function resetGetMemoryFilesCache(e="session_start"){V=e,Y=!0,clearMemoryFileCaches()}export function getLargeMemoryFiles(e){return e.filter(e=>e.content.length>4e4)}export function filterInjectedMemoryFiles(e){return C("tengu_moth_copse",!1)?e.filter(e=>"AutoMem"!==e.type&&"TeamMem"!==e.type):e}export const getClaudeMds=(t,s)=>{const o=[],n=C("tengu_paper_halyard",!1);for(const r of t)if((!s||s(r.type))&&(!n||"Project"!==r.type&&"Local"!==r.type)&&r.content){const t="Project"===r.type?" (project instructions, checked into the codebase)":"Local"===r.type?" (user's private project instructions, not checked in)":e("TEAMMEM")&&"TeamMem"===r.type?" (shared team memory, synced across the organization)":"AutoMem"===r.type?" (user's auto-memory, persists across conversations)":" (user's private global instructions for all projects)",s=r.content.trim();e("TEAMMEM")&&"TeamMem"===r.type?o.push(`Contents of ${r.path}${t}:\n\n<team-memory-content source="shared">\n${s}\n</team-memory-content>`):o.push(`Contents of ${r.path}${t}:\n\n${s}`)}return 0===o.length?"":`Codebase and user instructions are shown below. Be sure to adhere to these instructions. IMPORTANT: These instructions OVERRIDE any default behavior and you MUST follow them exactly as written.\n\n${o.join("\n\n")}`};export async function getManagedAndUserConditionalRules(e,t){const s=[],o=j();if(s.push(...await processConditionedMdRules(e,o,"Managed",t,!1)),H("userSettings")){const o=A();s.push(...await processConditionedMdRules(e,o,"User",t,!0))}return s}export async function getMemoryFilesForNestedDirectory(e,t,s){const o=[];if(H("projectSettings")){const t=u(e,"CLAUDE.md");o.push(...await processMemoryFile(t,"Project",s,!1));const n=u(e,".contextcli","CONTEXT.md");o.push(...await processMemoryFile(n,"Project",s,!1));const r=u(e,".contextcli","CLAUDE.md");o.push(...await processMemoryFile(r,"Project",s,!1))}if(H("localSettings")){const t=u(e,"CLAUDE.local.md");o.push(...await processMemoryFile(t,"Local",s,!1))}const n=u(e,".contextcli","rules"),r=new Set(s);o.push(...await processMdRules({dotContextRulesDir:n,type:"Project",processedPaths:r,includeExternal:!1,conditionalRule:!1})),o.push(...await processConditionedMdRules(t,n,"Project",s,!1));for(const e of r)s.add(e);return o}export async function getConditionalRulesForCwdLevelDirectory(e,t,s){return processConditionedMdRules(t,u(e,".contextcli","rules"),"Project",s,!1)}export async function processConditionedMdRules(e,t,s,n,r){return(await processMdRules({rulesDir:t,type:s,processedPaths:n,includeExternal:r,conditionalRule:!0})).filter(n=>{if(!n.globs||0===n.globs.length)return!1;const r="Project"===s?c(c(t)):M(),i=l(e)?p(r,e):e;return!(!i||i.startsWith("..")||l(i))&&o().add(n.globs).ignores(i)})}export function getExternalClaudeMdIncludes(e){const t=[];for(const s of e)"User"!==s.type&&s.parent&&!pathInOriginalCwd(s.path)&&t.push({path:s.path,parent:s.parent});return t}export function hasExternalClaudeMdIncludes(e){return getExternalClaudeMdIncludes(e).length>0}export async function shouldShowClaudeMdExternalIncludesWarning(){const e=w();return!e.hasClaudeMdExternalIncludesApproved&&!e.hasClaudeMdExternalIncludesWarningShown&&hasExternalClaudeMdIncludes(await getMemoryFiles(!0))}export function isMemoryFilePath(e){const t=i(e);return"CLAUDE.md"===t||"CLAUDE.local.md"===t||(!("CONTEXT.md"!==t||!e.includes(`${d}.contextcli${d}`))||!(!t.endsWith(".md")||!e.includes(`${d}.contextcli${d}rules${d}`)))}export function getAllMemoryFilePaths(e,t){const s=new Set;for(const t of e)t.content.trim().length>0&&s.add(t.path);for(const e of v(t))isMemoryFilePath(e)&&s.add(e);return Array.from(s)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{randomUUID as t}from"crypto";import{readFileSync as r}from"fs";import{mkdir as n,writeFile as e}from"fs/promises";import{dirname as o,join as s}from"path";import{addSessionCronTask as i,getProjectRoot as a,getSessionCronTasks as c,removeSessionCronTasks as u}from"../bootstrap/state.js";import{computeNextCronRun as f,parseCronExpression as p}from"./cron.js";import{logForDebugging as l}from"./debug.js";import{isFsInaccessible as d}from"./errors.js";import{getFsImplementation as m}from"./fsOperations.js";import{safeParseJSON as C}from"./json.js";import{logError as h}from"./log.js";import{jsonStringify as g}from"./slowOperations.js";const k=s(".
|
|
1
|
+
import{randomUUID as t}from"crypto";import{readFileSync as r}from"fs";import{mkdir as n,writeFile as e}from"fs/promises";import{dirname as o,join as s}from"path";import{addSessionCronTask as i,getProjectRoot as a,getSessionCronTasks as c,removeSessionCronTasks as u}from"../bootstrap/state.js";import{computeNextCronRun as f,parseCronExpression as p}from"./cron.js";import{logForDebugging as l}from"./debug.js";import{isFsInaccessible as d}from"./errors.js";import{getFsImplementation as m}from"./fsOperations.js";import{safeParseJSON as C}from"./json.js";import{logError as h}from"./log.js";import{jsonStringify as g}from"./slowOperations.js";const k=s(".contextcli","scheduled_tasks.json");export function getCronFilePath(t){const r=t??a();return s(r,k)}export async function readCronTasks(t){const r=m();let n;try{n=await r.readFile(getCronFilePath(t),{encoding:"utf-8"})}catch(t){return d(t)||h(t),[]}const e=C(n,!1);if(!e||"object"!=typeof e)return[];const o=e;if(!Array.isArray(o.tasks))return[];const s=[];for(const t of o.tasks)t&&"string"==typeof t.id&&"string"==typeof t.cron&&"string"==typeof t.prompt&&"number"==typeof t.createdAt?p(t.cron)?s.push({id:t.id,cron:t.cron,prompt:t.prompt,createdAt:t.createdAt,..."number"==typeof t.lastFiredAt?{lastFiredAt:t.lastFiredAt}:{},...t.recurring?{recurring:!0}:{},...t.permanent?{permanent:!0}:{}}):l(`[ScheduledTasks] skipping task ${t.id} with invalid cron '${t.cron}'`):l(`[ScheduledTasks] skipping malformed task: ${g(t)}`);return s}export function hasCronTasksSync(t){let n;try{n=r(getCronFilePath(t),"utf-8")}catch{return!1}const e=C(n,!1);if(!e||"object"!=typeof e)return!1;const o=e.tasks;return Array.isArray(o)&&o.length>0}export async function writeCronTasks(t,r){const s=getCronFilePath(r??a());await n(o(s),{recursive:!0});const i={tasks:t.map(({durable:t,...r})=>r)};await e(s,g(i,null,2)+"\n","utf-8")}export async function addCronTask(r,n,e,o,s){const a=t().slice(0,8),c={id:a,cron:r,prompt:n,createdAt:Date.now(),...e?{recurring:!0}:{}};if(!o)return i({...c,...s?{agentId:s}:{}}),a;const u=await readCronTasks();return u.push(c),await writeCronTasks(u),a}export async function removeCronTasks(t,r){if(0===t.length)return;if(void 0===r&&u(t)===t.length)return;const n=new Set(t),e=await readCronTasks(r),o=e.filter(t=>!n.has(t.id));o.length!==e.length&&await writeCronTasks(o,r)}export async function markCronTasksFired(t,r,n){if(0===t.length)return;const e=new Set(t),o=await readCronTasks(n);let s=!1;for(const t of o)e.has(t.id)&&(t.lastFiredAt=r,s=!0);s&&await writeCronTasks(o,n)}export async function listAllCronTasks(t){const r=await readCronTasks(t);if(void 0!==t)return r;const n=c().map(t=>({...t,durable:!1}));return[...r,...n]}export function nextCronRunMs(t,r){const n=p(t);if(!n)return null;const e=f(n,new Date(r));return e?e.getTime():null}export const DEFAULT_CRON_JITTER_CONFIG={recurringFrac:.1,recurringCapMs:9e5,oneShotMaxMs:9e4,oneShotFloorMs:0,oneShotMinuteMod:30,recurringMaxAgeMs:6048e5};function jitterFrac(t){const r=parseInt(t.slice(0,8),16)/4294967296;return Number.isFinite(r)?r:0}export function jitteredNextCronRunMs(t,r,n,e=DEFAULT_CRON_JITTER_CONFIG){const o=nextCronRunMs(t,r);if(null===o)return null;const s=nextCronRunMs(t,o);if(null===s)return o;return o+Math.min(jitterFrac(n)*e.recurringFrac*(s-o),e.recurringCapMs)}export function oneShotJitteredNextCronRunMs(t,r,n,e=DEFAULT_CRON_JITTER_CONFIG){const o=nextCronRunMs(t,r);if(null===o)return null;if(new Date(o).getMinutes()%e.oneShotMinuteMod!==0)return o;const s=e.oneShotFloorMs+jitterFrac(n)*(e.oneShotMaxMs-e.oneShotFloorMs);return Math.max(o-s,r)}export function findMissedTasks(t,r){return t.filter(t=>{const n=nextCronRunMs(t.cron,t.createdAt);return null!==n&&n<r})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mkdir as e,readFile as t,unlink as r,writeFile as s}from"fs/promises";import{dirname as o,join as c}from"path";import{z as i}from"zod/v4";import{getProjectRoot as a,getSessionId as n}from"../bootstrap/state.js";import{registerCleanup as d}from"./cleanupRegistry.js";import{logForDebugging as u}from"./debug.js";import{getErrnoCode as l}from"./errors.js";import{isProcessRunning as p}from"./genericProcessUtils.js";import{safeParseJSON as f}from"./json.js";import{lazySchema as h}from"./lazySchema.js";import{jsonStringify as k}from"./slowOperations.js";const m=c(".
|
|
1
|
+
import{mkdir as e,readFile as t,unlink as r,writeFile as s}from"fs/promises";import{dirname as o,join as c}from"path";import{z as i}from"zod/v4";import{getProjectRoot as a,getSessionId as n}from"../bootstrap/state.js";import{registerCleanup as d}from"./cleanupRegistry.js";import{logForDebugging as u}from"./debug.js";import{getErrnoCode as l}from"./errors.js";import{isProcessRunning as p}from"./genericProcessUtils.js";import{safeParseJSON as f}from"./json.js";import{lazySchema as h}from"./lazySchema.js";import{jsonStringify as k}from"./slowOperations.js";const m=c(".contextcli","scheduled_tasks.lock"),w=h(()=>i.object({sessionId:i.string(),pid:i.number(),acquiredAt:i.number()}));let y,g;function getLockPath(e){const t=e??a();return c(t,m)}async function readLock(e){let r;try{r=await t(getLockPath(e),"utf8")}catch{return}const s=w().safeParse(f(r,!1));return s.success?s.data:void 0}async function tryCreateExclusive(t,r){const c=getLockPath(r),i=k(t);try{return await s(c,i,{flag:"wx"}),!0}catch(t){const r=l(t);if("EEXIST"===r)return!1;if("ENOENT"===r){await e(o(c),{recursive:!0});try{return await s(c,i,{flag:"wx"}),!0}catch(e){if("EEXIST"===l(e))return!1;throw e}}throw t}}function registerLockCleanup(e){y?.(),y=d(async()=>{await releaseSchedulerLock(e)})}export async function tryAcquireSchedulerLock(e){const t=e?.dir,o=e?.lockIdentity??n(),c={sessionId:o,pid:process.pid,acquiredAt:Date.now()};if(await tryCreateExclusive(c,t))return g=void 0,registerLockCleanup(e),u(`[ScheduledTasks] acquired scheduler lock (PID ${process.pid})`),!0;const i=await readLock(t);return i?.sessionId===o?(i.pid!==process.pid&&(await s(getLockPath(t),k(c)),registerLockCleanup(e)),!0):i&&p(i.pid)?(g!==i.sessionId&&(g=i.sessionId,u(`[ScheduledTasks] scheduler lock held by session ${i.sessionId} (PID ${i.pid})`)),!1):(i&&u(`[ScheduledTasks] recovering stale scheduler lock from PID ${i.pid}`),await r(getLockPath(t)).catch(()=>{}),!!await tryCreateExclusive(c,t)&&(g=void 0,registerLockCleanup(e),!0))}export async function releaseSchedulerLock(e){y?.(),y=void 0,g=void 0;const t=e?.dir,s=e?.lockIdentity??n(),o=await readLock(t);if(o&&o.sessionId===s)try{await r(getLockPath(t)),u("[ScheduledTasks] released scheduler lock")}catch{}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MACRO as t}from"../recovery/bunBundleShim.js";import{execa as e}from"execa";import{readFile as n,realpath as a}from"fs/promises";import{homedir as o}from"os";import{delimiter as s,join as i,posix as r,win32 as l}from"path";import{checkGlobalInstallPermissions as c}from"./autoUpdater.js";import{isInBundledMode as p}from"./bundledMode.js";import{formatAutoUpdaterDisabledReason as u,getAutoUpdaterDisabledReason as m,getGlobalConfig as d}from"./config.js";import{getCwd as f}from"./cwd.js";import{isEnvTruthy as g}from"./envUtils.js";import{execFileNoThrow as h}from"./execFileNoThrow.js";import{getFsImplementation as x}from"./fsOperations.js";import{getShellType as b,isRunningFromLocalInstallation as w,localInstallationExists as v}from"./localInstaller.js";import{detectApk as y,detectAsdf as j,detectDeb as E,detectHomebrew as $,detectMise as P,detectPacman as A,detectRpm as C,detectWinget as k,getPackageManager as L}from"./nativeInstaller/packageManagers.js";import{getPlatform as I}from"./platform.js";import{getRipgrepStatus as _}from"./ripgrep.js";import{SandboxManager as M}from"./sandbox/sandbox-adapter.js";import{getManagedFilePath as O}from"./settings/managedPath.js";import{CUSTOMIZATION_SURFACES as T}from"./settings/types.js";import{findClaudeAlias as U,findValidClaudeAlias as H,getShellConfigPaths as N}from"./shellConfig.js";import{jsonParse as S}from"./slowOperations.js";import{which as G}from"./which.js";export async function getCurrentInstallationType(){if("development"===process.env.NODE_ENV)return"development";const[t]=function(){let t=process.argv[1]||"",e=process.execPath||process.argv[0]||"";return"windows"===I()&&(t=t.split(l.sep).join(r.sep),e=e.split(l.sep).join(r.sep)),[t,e]}();if(p())return $()||k()||P()||j()||await A()||await E()||await C()||await y()?"package-manager":"native";if(w())return"npm-local";if(["/usr/local/lib/node_modules","/usr/lib/node_modules","/opt/homebrew/lib/node_modules","/opt/homebrew/bin","/usr/local/bin","/.nvm/versions/node/"].some(e=>t.includes(e)))return"npm-global";if(t.includes("/npm/")||t.includes("/nvm/"))return"npm-global";const n=await e("npm config get prefix",{shell:!0,reject:!1}),a=0===n.exitCode?n.stdout.trim():null;return a&&t.startsWith(a)?"npm-global":"unknown"}export function getInvokedBinary(){try{return p()?process.execPath||"unknown":process.argv[1]||"unknown"}catch{return"unknown"}}export function detectLinuxGlobPatternWarnings(){if("linux"!==I())return[];const t=[],e=M.getLinuxGlobPatternWarnings();if(e.length>0){const n=e.slice(0,3).join(", "),a=e.length-3,o=a>0?`${n} (${a} more)`:n;t.push({issue:"Los patrones glob en las reglas de permisos del sandbox no están totalmente soportados en Linux",fix:`Se han encontrado ${e.length} patrón(es): ${o}. En Linux, los patrones glob en las reglas de Editar/Leer serán ignorados.`})}return t}export async function getDoctorDiagnostic(){const e=await getCurrentInstallationType(),w=void 0!==t&&t.VERSION?t.VERSION:"unknown",y=await async function(){if("development"===process.env.NODE_ENV)return f();if(p()){try{return await a(process.execPath)}catch{}try{const t=await G("context");if(t)return t}catch{}try{return await x().stat(i(o(),".local/bin/context")),i(o(),".local/bin/context")}catch{}return"native"}try{return process.argv[0]||"unknown"}catch{return"unknown"}}(),j=getInvokedBinary(),E=await async function(){const e=x(),n=[],s=i(o(),".
|
|
1
|
+
import{MACRO as t}from"../recovery/bunBundleShim.js";import{execa as e}from"execa";import{readFile as n,realpath as a}from"fs/promises";import{homedir as o}from"os";import{delimiter as s,join as i,posix as r,win32 as l}from"path";import{checkGlobalInstallPermissions as c}from"./autoUpdater.js";import{isInBundledMode as p}from"./bundledMode.js";import{formatAutoUpdaterDisabledReason as u,getAutoUpdaterDisabledReason as m,getGlobalConfig as d}from"./config.js";import{getCwd as f}from"./cwd.js";import{isEnvTruthy as g}from"./envUtils.js";import{execFileNoThrow as h}from"./execFileNoThrow.js";import{getFsImplementation as x}from"./fsOperations.js";import{getShellType as b,isRunningFromLocalInstallation as w,localInstallationExists as v}from"./localInstaller.js";import{detectApk as y,detectAsdf as j,detectDeb as E,detectHomebrew as $,detectMise as P,detectPacman as A,detectRpm as C,detectWinget as k,getPackageManager as L}from"./nativeInstaller/packageManagers.js";import{getPlatform as I}from"./platform.js";import{getRipgrepStatus as _}from"./ripgrep.js";import{SandboxManager as M}from"./sandbox/sandbox-adapter.js";import{getManagedFilePath as O}from"./settings/managedPath.js";import{CUSTOMIZATION_SURFACES as T}from"./settings/types.js";import{findClaudeAlias as U,findValidClaudeAlias as H,getShellConfigPaths as N}from"./shellConfig.js";import{jsonParse as S}from"./slowOperations.js";import{which as G}from"./which.js";export async function getCurrentInstallationType(){if("development"===process.env.NODE_ENV)return"development";const[t]=function(){let t=process.argv[1]||"",e=process.execPath||process.argv[0]||"";return"windows"===I()&&(t=t.split(l.sep).join(r.sep),e=e.split(l.sep).join(r.sep)),[t,e]}();if(p())return $()||k()||P()||j()||await A()||await E()||await C()||await y()?"package-manager":"native";if(w())return"npm-local";if(["/usr/local/lib/node_modules","/usr/lib/node_modules","/opt/homebrew/lib/node_modules","/opt/homebrew/bin","/usr/local/bin","/.nvm/versions/node/"].some(e=>t.includes(e)))return"npm-global";if(t.includes("/npm/")||t.includes("/nvm/"))return"npm-global";const n=await e("npm config get prefix",{shell:!0,reject:!1}),a=0===n.exitCode?n.stdout.trim():null;return a&&t.startsWith(a)?"npm-global":"unknown"}export function getInvokedBinary(){try{return p()?process.execPath||"unknown":process.argv[1]||"unknown"}catch{return"unknown"}}export function detectLinuxGlobPatternWarnings(){if("linux"!==I())return[];const t=[],e=M.getLinuxGlobPatternWarnings();if(e.length>0){const n=e.slice(0,3).join(", "),a=e.length-3,o=a>0?`${n} (${a} more)`:n;t.push({issue:"Los patrones glob en las reglas de permisos del sandbox no están totalmente soportados en Linux",fix:`Se han encontrado ${e.length} patrón(es): ${o}. En Linux, los patrones glob en las reglas de Editar/Leer serán ignorados.`})}return t}export async function getDoctorDiagnostic(){const e=await getCurrentInstallationType(),w=void 0!==t&&t.VERSION?t.VERSION:"unknown",y=await async function(){if("development"===process.env.NODE_ENV)return f();if(p()){try{return await a(process.execPath)}catch{}try{const t=await G("context");if(t)return t}catch{}try{return await x().stat(i(o(),".local/bin/context")),i(o(),".local/bin/context")}catch{}return"native"}try{return process.argv[0]||"unknown"}catch{return"unknown"}}(),j=getInvokedBinary(),E=await async function(){const e=x(),n=[],s=i(o(),".contextcli","local");await v()&&n.push({type:"npm-local",path:s});const r=["@iaforged/context-code"];t.PACKAGE_URL&&"@iaforged/context-code"!==t.PACKAGE_URL&&r.push(t.PACKAGE_URL);const l=await h("npm",["-g","config","get","prefix"]);if(0===l.code&&l.stdout){const t=l.stdout.trim(),o="windows"===I(),s=o?i(t,"context"):i(t,"bin","context");let c=!1;try{await e.stat(s),c=!0}catch{}if(c){let t=!1;try{(await a(s)).includes("/Caskroom/")&&(t=$())}catch{}t||n.push({type:"npm-global",path:s})}else for(const a of r){const s=o?i(t,"node_modules",a):i(t,"lib","node_modules",a);try{await e.stat(s),n.push({type:"npm-global-orphan",path:s})}catch{}}}const c=i(o(),".local","bin","context");try{await e.stat(c),n.push({type:"native",path:c})}catch{}if("native"===d().installMethod){const t=i(o(),".local","share","context");try{await e.stat(t),n.some(t=>"native"===t.type)||n.push({type:"native",path:t})}catch{}}return n}(),P=await async function(t){const e=[];try{const t=await n(i(O(),"managed-settings.json"),"utf-8"),a=S(t),o=a&&"object"==typeof a?a.strictPluginOnlyCustomization:void 0;if(void 0!==o&&"boolean"!=typeof o)if(Array.isArray(o)){const t=o.filter(t=>"string"==typeof t&&!T.includes(t));t.length>0&&e.push({issue:`managed-settings.json: strictPluginOnlyCustomization tiene ${t.length} valor(es) que este cliente no reconoce: ${t.map(String).join(", ")}`,fix:`Estos se ignoran silenciosamente. Superficies conocidas para esta versión: ${T.join(", ")}. Elimínalos o actualiza el cliente.`})}else e.push({issue:`managed-settings.json: strictPluginOnlyCustomization tiene un valor no válido (se esperaba boolean o array, se obtuvo ${typeof o})`,fix:`El campo se ignora silenciosamente. Establécelo en true o en un array de: ${T.join(", ")}.`})}catch{}const a=d();if("development"===t)return e;if("native"===t){const t=(process.env.PATH||"").split(s),n=o(),a=i(n,".local","bin");let c=a;if("windows"===I()&&(c=a.split(l.sep).join(r.sep)),!t.some(t=>{let e=t;"windows"===I()&&(e=t.split(l.sep).join(r.sep));const n=e.replace(/\/+$/,""),a=t.replace(/[/\\]+$/,"");return n===c||"~/.local/bin"===a||"$HOME/.local/bin"===a}))if("windows"===I()){const t=a.split(r.sep).join(l.sep);e.push({issue:`Existe una instalación nativa pero ${t} no está en tu PATH`,fix:"Añádelo abriendo: Propiedades del sistema → Variables de entorno → Editar PATH de usuario → Nuevo → Añade la ruta de arriba. Luego reinicia tu terminal."})}else{const t=b(),n=N()[t],a=n?n.replace(o(),"~"):"your shell config file";e.push({issue:"Existe una instalación nativa pero ~/.local/bin no está en tu PATH",fix:`Ejecuta: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ${a} luego abre una nueva terminal o ejecuta: source ${a}`})}}g(process.env.DISABLE_INSTALLATION_CHECKS)||("npm-local"===t&&"local"!==a.installMethod&&e.push({issue:`Ejecutando desde una instalación local pero el método de instalación configurado es '${a.installMethod}'`,fix:"Considera usar la instalación nativa: context install"}),"native"===t&&"native"!==a.installMethod&&e.push({issue:`Ejecutando instalación nativa pero el método de instalación configurado es '${a.installMethod}'`,fix:"Ejecuta context install para actualizar la configuración"})),"npm-global"===t&&await v()&&e.push({issue:"Existe una instalación local pero no se está usando",fix:"Considera usar la instalación nativa: context install"});const c=await U(),p=await H();"npm-local"===t&&(await G("claude")||p||(c?e.push({issue:"Instalación local no accesible",fix:`El alias existe pero apunta a un destino no válido: ${c}. Actualiza el alias: alias context="~/.contextcli/local/context"`}):e.push({issue:"Instalación local no accesible",fix:'Crea un alias: alias context="~/.contextcli/local/context"'})));return e}(e);if(P.push(...detectLinuxGlobPatternWarnings()),"native"===e){const e=E.filter(t=>"npm-global"===t.type||"npm-global-orphan"===t.type||"npm-local"===t.type),n="windows"===I();for(const a of e)if("npm-global"===a.type){let e="npm -g uninstall @iaforged/context-code";t.PACKAGE_URL&&"@iaforged/context-code"!==t.PACKAGE_URL&&(e+=` && npm -g uninstall ${t.PACKAGE_URL}`),P.push({issue:`Quedan restos de una instalación global de npm en ${a.path}`,fix:`Ejecuta: ${e}`})}else"npm-global-orphan"===a.type?P.push({issue:`Paquete global de npm huérfano en ${a.path}`,fix:n?`Ejecuta: rmdir /s /q "${a.path}"`:`Ejecuta: rm -rf ${a.path}`}):"npm-local"===a.type&&P.push({issue:`Quedan restos de una instalación local de npm en ${a.path}`,fix:n?`Ejecuta: rmdir /s /q "${a.path}"`:`Ejecuta: rm -rf ${a.path}`})}const A=d().installMethod||"not set";let C=null;if("npm-global"===e){C=(await c()).hasPermissions,C||m()||P.push({issue:"Permisos insuficientes para actualizaciones automáticas",fix:"Haz una de las dos: (1) Reinstala node sin sudo, o (2) Usa `context install` para una instalación nativa"})}const k=_(),M={working:k.working??!0,mode:k.mode,systemPath:"system"===k.mode?k.path:null},R="package-manager"===e?await L():void 0;return{installationType:e,version:w,installationPath:y,invokedBinary:j,configInstallMethod:A,autoUpdates:(()=>{const t=m();return t?`disabled (${u(t)})`:"enabled"})(),hasUpdatePermissions:C,multipleInstallations:E,warnings:P,packageManager:R,ripgrepStatus:M}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createRequire as e}from"module";const n=e(import.meta.url);import r from"lodash-es/memoize.js";import{homedir as o}from"os";import{join as t}from"path";export const getContextConfigHomeDir=r(()=>(process.env.CONTEXT_CONFIG_DIR??t(o(),".
|
|
1
|
+
import{createRequire as e}from"module";const n=e(import.meta.url);import r from"lodash-es/memoize.js";import{homedir as o}from"os";import{join as t}from"path";export const getContextConfigHomeDir=r(()=>(process.env.CONTEXT_CONFIG_DIR??t(o(),".contextcli")).normalize("NFC"),()=>`${process.env.CONTEXT_CONFIG_DIR??""}`);export const getClaudeConfigHomeDir=getContextConfigHomeDir;export function getTeamsDir(){return t(getContextConfigHomeDir(),"teams")}export function hasNodeOption(e){const n=process.env.NODE_OPTIONS;return!!n&&n.split(/\s+/).includes(e)}export function isEnvTruthy(e){if(!e)return!1;if("boolean"==typeof e)return e;const n=e.toLowerCase().trim();return["1","true","yes","on"].includes(n)}export function isEnvDefinedFalsy(e){if(void 0===e)return!1;if("boolean"==typeof e)return!e;if(!e)return!1;const n=e.toLowerCase().trim();return["0","false","no","off"].includes(n)}export function isBareMode(){return isEnvTruthy(process.env.CONTEXT_CODE_SIMPLE)||isEnvTruthy(process.env.CLAUDE_CODE_SIMPLE)||process.argv.includes("--bare")}export function parseEnvVars(e){const n={};if(e)for(const r of e){const[e,...o]=r.split("=");if(!e||0===o.length)throw new Error(`Invalid environment variable format: ${r}, environment variables should be added as: -e KEY1=value1 -e KEY2=value2`);n[e]=o.join("=")}return n}export function getAWSRegion(){return process.env.AWS_REGION||process.env.AWS_DEFAULT_REGION||"us-east-1"}export function getDefaultVertexRegion(){return process.env.CLOUD_ML_REGION||"us-east5"}export function shouldMaintainProjectWorkingDir(){return isEnvTruthy(process.env.CONTEXT_BASH_MAINTAIN_PROJECT_WORKING_DIR)||isEnvTruthy(process.env.CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR)}export function readForkEnvVar(e,n){return process.env[e]??process.env[n]}export function isForkEnvVarTruthy(e,n){return isEnvTruthy(process.env[e])||isEnvTruthy(process.env[n])}export function isBackgroundTasksDisabled(){return isForkEnvVarTruthy("CONTEXT_CODE_DISABLE_BACKGROUND_TASKS","CLAUDE_CODE_DISABLE_BACKGROUND_TASKS")}export function isCoordinatorMode(){return isForkEnvVarTruthy("CONTEXT_CODE_COORDINATOR_MODE","CLAUDE_CODE_COORDINATOR_MODE")}export function isRunningOnHomespace(){return"ant"===process.env.USER_TYPE&&isEnvTruthy(process.env.COO_RUNNING_ON_HOMESPACE)}export function isInProtectedNamespace(){return"ant"===process.env.USER_TYPE&&n("./protectedNamespace.js").checkProtectedNamespace()}const s=[["claude-haiku-4-5","VERTEX_REGION_CLAUDE_HAIKU_4_5"],["claude-3-5-haiku","VERTEX_REGION_CLAUDE_3_5_HAIKU"],["claude-3-5-sonnet","VERTEX_REGION_CLAUDE_3_5_SONNET"],["claude-3-7-sonnet","VERTEX_REGION_CLAUDE_3_7_SONNET"],["claude-opus-4-8","VERTEX_REGION_CLAUDE_4_8_OPUS"],["claude-opus-4-1","VERTEX_REGION_CLAUDE_4_1_OPUS"],["claude-opus-4","VERTEX_REGION_CLAUDE_4_0_OPUS"],["claude-sonnet-4-6","VERTEX_REGION_CLAUDE_4_6_SONNET"],["claude-sonnet-4-5","VERTEX_REGION_CLAUDE_4_5_SONNET"],["claude-sonnet-4","VERTEX_REGION_CLAUDE_4_0_SONNET"]];export function getVertexRegionForModel(e){if(e){const n=s.find(([n])=>e.startsWith(n));if(n)return process.env[n[1]]||getDefaultVertexRegion()}return getDefaultVertexRegion()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{feature as e}from"../../recovery/bunBundleShim.js";import{getInvokedSkillsForAgent as t}from"../../bootstrap/state.js";import{getFeatureValue_CACHED_MAY_BE_STALE as s}from"../../services/analytics/growthbook.js";import{logEvent as n}from"../../services/analytics/index.js";import{queryModelWithoutStreaming as o}from"../../services/api/claude.js";import{getEmptyToolPermissionContext as r}from"../../Tool.js";import{createAbortController as i}from"../abortController.js";import{count as a}from"../array.js";import{getCwd as l}from"../cwd.js";import{toError as m}from"../errors.js";import{logError as p}from"../log.js";import{createUserMessage as u,extractTag as c,extractTextContent as d}from"../messages.js";import{getSmallFastModel as f}from"../model/model.js";import{jsonParse as g}from"../slowOperations.js";import{asSystemPrompt as h}from"../systemPromptType.js";import{createApiQueryHook as y}from"./apiQueryHookHelper.js";import{registerPostSamplingHook as k}from"./postSamplingHooks.js";function findProjectSkill(){const e=t(null);for(const[,t]of e)if(t.skillPath.startsWith("projectSettings:"))return t}export function initSkillImprovement(){e("SKILL_IMPROVEMENT")&&s("tengu_copper_panda",!1)&&k(function(){let e=0,t=0;return y({name:"skill_improvement",async shouldRun(t){if("repl_main_thread"!==t.querySource)return!1;if(!findProjectSkill())return!1;const s=a(t.messages,e=>"user"===e.type);return!(s-e<5||(e=s,0))},buildMessages(e){const s=findProjectSkill(),n=e.messages.slice(t);return t=e.messages.length,[u({content:`You are analyzing a conversation where a user is executing a skill (a repeatable process).\nYour job: identify if the user's recent messages contain preferences, requests, or corrections that should be permanently added to the skill definition for future runs.\n\n<skill_definition>\n${s.content}\n</skill_definition>\n\n<recent_messages>\n${o=n,o.filter(e=>"user"===e.type||"assistant"===e.type).map(e=>{const t="user"===e.type?"User":"Assistant",s=e.message.content;return"string"==typeof s?`${t}: ${s.slice(0,500)}`:`${t}: ${s.filter(e=>"text"===e.type).map(e=>e.text).join("\n").slice(0,500)}`}).join("\n\n")}\n</recent_messages>\n\nLook for:\n- Requests to add, change, or remove steps: "can you also ask me X", "please do Y too", "don't do Z"\n- Preferences about how steps should work: "ask me about energy levels", "note the time", "use a casual tone"\n- Corrections: "no, do X instead", "always use Y", "make sure to..."\n\nIgnore:\n- Routine conversation that doesn't generalize (one-time answers, chitchat)\n- Things the skill already does\n\nOutput a JSON array inside <updates> tags. Each item: {"section": "which step/section to modify or 'new step'", "change": "what to add/modify", "reason": "which user message prompted this"}.\nOutput <updates>[]</updates> if no updates are needed.`})];var o},systemPrompt:"You detect user preferences and process improvements during skill execution. Flag anything the user asks for that should be remembered for next time.",useTools:!1,parseResponse(e){const t=c(e,"updates");if(!t)return[];try{return g(t)}catch{return[]}},logResult(e,t){if("success"===e.type&&e.result.length>0){const s=findProjectSkill(),o=s?.skillName??"unknown";n("tengu_skill_improvement_detected",{updateCount:e.result.length,uuid:e.uuid,_PROTO_skill_name:o}),t.toolUseContext.setAppState(t=>({...t,skillImprovement:{suggestion:{skillName:o,updates:e.result}}}))}},getModel:f})}())}export async function applySkillImprovement(e,t){if(!e)return;const{join:s}=await import("path"),n=await import("fs/promises"),a=s(l(),".
|
|
1
|
+
import{feature as e}from"../../recovery/bunBundleShim.js";import{getInvokedSkillsForAgent as t}from"../../bootstrap/state.js";import{getFeatureValue_CACHED_MAY_BE_STALE as s}from"../../services/analytics/growthbook.js";import{logEvent as n}from"../../services/analytics/index.js";import{queryModelWithoutStreaming as o}from"../../services/api/claude.js";import{getEmptyToolPermissionContext as r}from"../../Tool.js";import{createAbortController as i}from"../abortController.js";import{count as a}from"../array.js";import{getCwd as l}from"../cwd.js";import{toError as m}from"../errors.js";import{logError as p}from"../log.js";import{createUserMessage as u,extractTag as c,extractTextContent as d}from"../messages.js";import{getSmallFastModel as f}from"../model/model.js";import{jsonParse as g}from"../slowOperations.js";import{asSystemPrompt as h}from"../systemPromptType.js";import{createApiQueryHook as y}from"./apiQueryHookHelper.js";import{registerPostSamplingHook as k}from"./postSamplingHooks.js";function findProjectSkill(){const e=t(null);for(const[,t]of e)if(t.skillPath.startsWith("projectSettings:"))return t}export function initSkillImprovement(){e("SKILL_IMPROVEMENT")&&s("tengu_copper_panda",!1)&&k(function(){let e=0,t=0;return y({name:"skill_improvement",async shouldRun(t){if("repl_main_thread"!==t.querySource)return!1;if(!findProjectSkill())return!1;const s=a(t.messages,e=>"user"===e.type);return!(s-e<5||(e=s,0))},buildMessages(e){const s=findProjectSkill(),n=e.messages.slice(t);return t=e.messages.length,[u({content:`You are analyzing a conversation where a user is executing a skill (a repeatable process).\nYour job: identify if the user's recent messages contain preferences, requests, or corrections that should be permanently added to the skill definition for future runs.\n\n<skill_definition>\n${s.content}\n</skill_definition>\n\n<recent_messages>\n${o=n,o.filter(e=>"user"===e.type||"assistant"===e.type).map(e=>{const t="user"===e.type?"User":"Assistant",s=e.message.content;return"string"==typeof s?`${t}: ${s.slice(0,500)}`:`${t}: ${s.filter(e=>"text"===e.type).map(e=>e.text).join("\n").slice(0,500)}`}).join("\n\n")}\n</recent_messages>\n\nLook for:\n- Requests to add, change, or remove steps: "can you also ask me X", "please do Y too", "don't do Z"\n- Preferences about how steps should work: "ask me about energy levels", "note the time", "use a casual tone"\n- Corrections: "no, do X instead", "always use Y", "make sure to..."\n\nIgnore:\n- Routine conversation that doesn't generalize (one-time answers, chitchat)\n- Things the skill already does\n\nOutput a JSON array inside <updates> tags. Each item: {"section": "which step/section to modify or 'new step'", "change": "what to add/modify", "reason": "which user message prompted this"}.\nOutput <updates>[]</updates> if no updates are needed.`})];var o},systemPrompt:"You detect user preferences and process improvements during skill execution. Flag anything the user asks for that should be remembered for next time.",useTools:!1,parseResponse(e){const t=c(e,"updates");if(!t)return[];try{return g(t)}catch{return[]}},logResult(e,t){if("success"===e.type&&e.result.length>0){const s=findProjectSkill(),o=s?.skillName??"unknown";n("tengu_skill_improvement_detected",{updateCount:e.result.length,uuid:e.uuid,_PROTO_skill_name:o}),t.toolUseContext.setAppState(t=>({...t,skillImprovement:{suggestion:{skillName:o,updates:e.result}}}))}},getModel:f})}())}export async function applySkillImprovement(e,t){if(!e)return;const{join:s}=await import("path"),n=await import("fs/promises"),a=s(l(),".contextcli","skills",e,"SKILL.md");let g;try{g=await n.readFile(a,"utf-8")}catch{return void p(new Error(`Failed to read skill file for improvement: ${a}`))}const y=t.map(e=>`- ${e.section}: ${e.change}`).join("\n"),k=await o({messages:[u({content:`You are editing a skill definition file. Apply the following improvements to the skill.\n\n<current_skill_file>\n${g}\n</current_skill_file>\n\n<improvements>\n${y}\n</improvements>\n\nRules:\n- Integrate the improvements naturally into the existing structure\n- Preserve frontmatter (--- block) exactly as-is\n- Preserve the overall format and style\n- Do not remove existing content unless an improvement explicitly replaces it\n- Output the complete updated file inside <updated_file> tags`})],systemPrompt:h(["You edit skill definition files to incorporate user preferences. Output only the updated file content."]),thinkingConfig:{type:"disabled"},tools:[],signal:i().signal,options:{getToolPermissionContext:async()=>r(),model:f(),toolChoice:void 0,isNonInteractiveSession:!1,hasAppendSystemPrompt:!1,temperatureOverride:0,agents:[],querySource:"skill_improvement_apply",mcpTools:[]}}),v=d(k.message.content).trim(),j=c(v,"updated_file");if(j)try{await n.writeFile(a,j,"utf-8")}catch(e){p(m(e))}else p(new Error("Skill improvement apply: no updated_file tag in response"))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{feature as t}from"../recovery/bunBundleShim.js";import{statSync as o}from"fs";import{lstat as r,readdir as e,readFile as n,realpath as i,stat as s}from"fs/promises";import a from"lodash-es/memoize.js";import{homedir as c}from"os";import{dirname as l,join as m,resolve as u,sep as f}from"path";import{logEvent as d}from"../services/analytics/index.js";import{getProjectRoot as p}from"../bootstrap/state.js";import{logForDebugging as g}from"./debug.js";import{getClaudeConfigHomeDir as h,isEnvTruthy as y}from"./envUtils.js";import{isFsInaccessible as w}from"./errors.js";import{normalizePathForComparison as F}from"./file.js";import{parseFrontmatter as S}from"./frontmatterParser.js";import{findCanonicalGitRoot as j,findGitRoot as $}from"./git.js";import{parseToolListFromCLI as k}from"./permissions/permissionSetup.js";import{ripGrep as D}from"./ripgrep.js";import{isSettingSourceEnabled as v}from"./settings/constants.js";import{getManagedFilePath as b}from"./settings/managedPath.js";import{isRestrictedToPluginOnly as P}from"./settings/pluginOnlyPolicy.js";export const CLAUDE_CONFIG_DIRECTORIES=["commands","agents","output-styles","skills","workflows",...t("TEMPLATES")?["templates"]:[]];export function extractDescriptionFromMarkdown(t,o="Custom item"){const r=t.split("\n");for(const t of r){const o=t.trim();if(o){const t=o.match(/^#+\s+(.+)$/),r=t?.[1]??o;return r.length>100?r.substring(0,97)+"...":r}}return o}function parseToolListString(t){if(null==t)return null;if(!t)return[];let o=[];if("string"==typeof t?o=[t]:Array.isArray(t)&&(o=t.filter(t=>"string"==typeof t)),0===o.length)return[];const r=k(o);return r.includes("*")?["*"]:r}export function parseAgentToolsFromFrontmatter(t){const o=parseToolListString(t);return null===o?void 0===t?void 0:[]:o.includes("*")?void 0:o}export function parseSlashCommandToolsFromFrontmatter(t){const o=parseToolListString(t);return null===o?[]:o}export function getProjectDirsUpToHome(t,r,e=".claude"){const n=u(c()).normalize("NFC"),i=function(t){const o=$(t),r=$(p());if(!o||!r)return o;const e=j(t);if(e&&F(e)===F(r))return o;const n=F(o),i=F(r);return n!==i&&n.startsWith(i+f)?r:o}(r);let s=u(r);const a=[];for(;F(s)!==F(n);){const r=m(s,e,t);try{o(r),a.push(r)}catch(t){if(!w(t))throw t}if(i&&F(s)===F(i))break;const n=l(s);if(n===s)break;s=n}return a}export function getDualProjectDirsUpToHome(t,o){return getProjectDirsUpToHome(t,o,".
|
|
1
|
+
import{feature as t}from"../recovery/bunBundleShim.js";import{statSync as o}from"fs";import{lstat as r,readdir as e,readFile as n,realpath as i,stat as s}from"fs/promises";import a from"lodash-es/memoize.js";import{homedir as c}from"os";import{dirname as l,join as m,resolve as u,sep as f}from"path";import{logEvent as d}from"../services/analytics/index.js";import{getProjectRoot as p}from"../bootstrap/state.js";import{logForDebugging as g}from"./debug.js";import{getClaudeConfigHomeDir as h,isEnvTruthy as y}from"./envUtils.js";import{isFsInaccessible as w}from"./errors.js";import{normalizePathForComparison as F}from"./file.js";import{parseFrontmatter as S}from"./frontmatterParser.js";import{findCanonicalGitRoot as j,findGitRoot as $}from"./git.js";import{parseToolListFromCLI as k}from"./permissions/permissionSetup.js";import{ripGrep as D}from"./ripgrep.js";import{isSettingSourceEnabled as v}from"./settings/constants.js";import{getManagedFilePath as b}from"./settings/managedPath.js";import{isRestrictedToPluginOnly as P}from"./settings/pluginOnlyPolicy.js";export const CLAUDE_CONFIG_DIRECTORIES=["commands","agents","output-styles","skills","workflows",...t("TEMPLATES")?["templates"]:[]];export function extractDescriptionFromMarkdown(t,o="Custom item"){const r=t.split("\n");for(const t of r){const o=t.trim();if(o){const t=o.match(/^#+\s+(.+)$/),r=t?.[1]??o;return r.length>100?r.substring(0,97)+"...":r}}return o}function parseToolListString(t){if(null==t)return null;if(!t)return[];let o=[];if("string"==typeof t?o=[t]:Array.isArray(t)&&(o=t.filter(t=>"string"==typeof t)),0===o.length)return[];const r=k(o);return r.includes("*")?["*"]:r}export function parseAgentToolsFromFrontmatter(t){const o=parseToolListString(t);return null===o?void 0===t?void 0:[]:o.includes("*")?void 0:o}export function parseSlashCommandToolsFromFrontmatter(t){const o=parseToolListString(t);return null===o?[]:o}export function getProjectDirsUpToHome(t,r,e=".claude"){const n=u(c()).normalize("NFC"),i=function(t){const o=$(t),r=$(p());if(!o||!r)return o;const e=j(t);if(e&&F(e)===F(r))return o;const n=F(o),i=F(r);return n!==i&&n.startsWith(i+f)?r:o}(r);let s=u(r);const a=[];for(;F(s)!==F(n);){const r=m(s,e,t);try{o(r),a.push(r)}catch(t){if(!w(t))throw t}if(i&&F(s)===F(i))break;const n=l(s);if(n===s)break;s=n}return a}export function getDualProjectDirsUpToHome(t,o){return getProjectDirsUpToHome(t,o,".contextcli")}export const loadMarkdownFilesForSubdir=a(async function(t,o){const e=Date.now(),n=m(h(),t),i=m(b(),".claude",t),s=getDualProjectDirsUpToHome(t,o),a=$(o),c=j(o);if(a&&c&&c!==a)for(const o of[".contextcli",".claude"]){const r=F(m(a,o,t));if(!s.some(t=>F(t)===r)){const r=m(c,o,t);s.includes(r)||s.push(r)}}const[l,u,f]=await Promise.all([loadMarkdownFiles(i).then(t=>t.map(t=>({...t,baseDir:i,source:"policySettings"}))),!v("userSettings")||"agents"===t&&P("agents")?Promise.resolve([]):loadMarkdownFiles(n).then(t=>t.map(t=>({...t,baseDir:n,source:"userSettings"}))),!v("projectSettings")||"agents"===t&&P("agents")?Promise.resolve([]):Promise.all(s.map(t=>loadMarkdownFiles(t).then(o=>o.map(o=>({...o,baseDir:t,source:"projectSettings"})))))]),p=f.flat(),y=[...l,...u,...p],w=await Promise.all(y.map(t=>async function(t){try{const o=await r(t,{bigint:!0});return 0n===o.dev&&0n===o.ino?null:`${o.dev}:${o.ino}`}catch{return null}}(t.filePath))),S=new Map,k=[];for(const[t,o]of y.entries()){const r=w[t]??null;if(null===r){k.push(o);continue}const e=S.get(r);void 0===e?(S.set(r,o.source),k.push(o)):g(`Skipping duplicate file '${o.filePath}' from ${o.source} (same inode already loaded from ${e})`)}const D=y.length-k.length;return D>0&&g(`Deduplicated ${D} files in ${t} (same inode via symlinks or hard links)`),d("tengu_dir_search",{durationMs:Date.now()-e,managedFilesFound:l.length,userFilesFound:u.length,projectFilesFound:p.length,projectDirsSearched:s.length,subdir:t}),k},(t,o)=>`${t}:${o}`);async function loadMarkdownFiles(t){const o=y(process.env.CLAUDE_CODE_USE_NATIVE_FILE_SEARCH),r=AbortSignal.timeout(3e3);let a;try{a=o?await async function(t,o){const r=[],n=new Set;return await async function walk(t){if(!o.aborted){try{const o=await s(t,{bigint:!0});if(o.isDirectory()){const r=void 0!==o.dev&&void 0!==o.ino?`${o.dev}:${o.ino}`:await i(t);if(n.has(r))return void g(`Skipping already visited directory (circular symlink): ${t}`);n.add(r)}}catch(o){const r=o instanceof Error?o.message:String(o);return void g(`Failed to stat directory ${t}: ${r}`)}try{const n=await e(t,{withFileTypes:!0});for(const e of n){if(o.aborted)break;const n=m(t,e.name);try{if(e.isSymbolicLink())try{const t=await s(n);t.isDirectory()?await walk(n):t.isFile()&&e.name.endsWith(".md")&&r.push(n)}catch(t){const o=t instanceof Error?t.message:String(t);g(`Failed to follow symlink ${n}: ${o}`)}else e.isDirectory()?await walk(n):e.isFile()&&e.name.endsWith(".md")&&r.push(n)}catch(t){const o=t instanceof Error?t.message:String(t);g(`Failed to access ${n}: ${o}`)}}}catch(o){const r=o instanceof Error?o.message:String(o);g(`Failed to read directory ${t}: ${r}`)}}}(t),r}(t,r):await D(["--files","--hidden","--follow","--no-ignore","--glob","*.md"],t,r)}catch(t){if(w(t))return[];throw t}return(await Promise.all(a.map(async t=>{try{const o=await n(t,{encoding:"utf-8"}),{frontmatter:r,content:e}=S(o,t);return{filePath:t,frontmatter:r,content:e}}catch(o){const r=o instanceof Error?o.message:String(o);return g(`Failed to read/parse markdown file: ${t}: ${r}`),null}}))).filter(t=>null!==t)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const META_MCP_SERVER_NAME="meta_marketing";export function isMetaMCPServer(e){return"meta_marketing"===e}export const META_MCP_TOOLS=["meta_connect","meta_status","meta_disconnect","meta_create_campaign","meta_create_adset","meta_create_ad","meta_update_budget","meta_get_ad_metrics","meta_pause_campaign","meta_duplicate_campaign","meta_get_page_posts","meta_schedule_post","meta_get_page_comments","meta_reply_comment","meta_get_page_insights","meta_publish_ig_content","meta_schedule_ig_post","meta_get_ig_comments","meta_reply_ig_message","meta_get_ig_insights","meta_send_wa_message","meta_send_wa_notification","meta_create_catalog_product","meta_update_catalog_inventory","meta_search_ads_library"];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{runMetaMcpServer as r}from"./server/index.js";export{r as runMetaMcpServer};
|