@astralyn/pi 0.87.5 → 0.87.6
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/CHANGELOG.md +21 -0
- package/dist/bundle/chunks/{chunk-EWLAVDVN.js → chunk-4W4Q2H6W.js} +55 -54
- package/dist/bundle/chunks/{chunk-APQ4ACY3.js → chunk-IORR2FW4.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-W3OGMIX7.js → virtual-modules-KUEIEAZN.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +8 -24
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +54 -109
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background/session.d.ts +11 -7
- package/dist/core/background/session.d.ts.map +1 -1
- package/dist/core/background/session.js +42 -16
- package/dist/core/background/session.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +17 -4
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +48 -50
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/extensions/distribution-api.d.ts +0 -7
- package/dist/core/extensions/distribution-api.d.ts.map +1 -1
- package/dist/core/extensions/distribution-api.js +6 -6
- package/dist/core/extensions/distribution-api.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +3 -2
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -5
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +10 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +59 -7
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/tools/bash.d.ts +1 -3
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +0 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +0 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +0 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +0 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +0 -7
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +0 -11
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +59 -5
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.d.ts.map +1 -1
- package/dist/core/tools/renderers/edit.js +4 -22
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/core/tools/renderers/find.d.ts.map +1 -1
- package/dist/core/tools/renderers/find.js +7 -6
- package/dist/core/tools/renderers/find.js.map +1 -1
- package/dist/core/tools/renderers/grep.d.ts.map +1 -1
- package/dist/core/tools/renderers/grep.js +8 -7
- package/dist/core/tools/renderers/grep.js.map +1 -1
- package/dist/core/tools/renderers/ls.d.ts.map +1 -1
- package/dist/core/tools/renderers/ls.js +3 -2
- package/dist/core/tools/renderers/ls.js.map +1 -1
- package/dist/core/tools/renderers/read.d.ts.map +1 -1
- package/dist/core/tools/renderers/read.js +7 -12
- package/dist/core/tools/renderers/read.js.map +1 -1
- package/dist/core/tools/renderers/write.d.ts.map +1 -1
- package/dist/core/tools/renderers/write.js +3 -2
- package/dist/core/tools/renderers/write.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +2 -6
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +0 -2
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/background/completion-render.d.ts.map +1 -1
- package/dist/extensions/background/completion-render.js +3 -4
- package/dist/extensions/background/completion-render.js.map +1 -1
- package/dist/extensions/background/constants.d.ts +2 -0
- package/dist/extensions/background/constants.d.ts.map +1 -1
- package/dist/extensions/background/constants.js +2 -0
- package/dist/extensions/background/constants.js.map +1 -1
- package/dist/extensions/background/index.d.ts.map +1 -1
- package/dist/extensions/background/index.js +31 -5
- package/dist/extensions/background/index.js.map +1 -1
- package/dist/extensions/question/detail-pane.d.ts +12 -0
- package/dist/extensions/question/detail-pane.d.ts.map +1 -0
- package/dist/extensions/question/detail-pane.js +42 -0
- package/dist/extensions/question/detail-pane.js.map +1 -0
- package/dist/extensions/question/dialog.d.ts.map +1 -1
- package/dist/extensions/question/dialog.js +175 -105
- package/dist/extensions/question/dialog.js.map +1 -1
- package/dist/extensions/question/option-window.d.ts +26 -0
- package/dist/extensions/question/option-window.d.ts.map +1 -0
- package/dist/extensions/question/option-window.js +53 -0
- package/dist/extensions/question/option-window.js.map +1 -0
- package/dist/extensions/question/render-cache.d.ts +4 -4
- package/dist/extensions/question/render-cache.d.ts.map +1 -1
- package/dist/extensions/question/render-cache.js +10 -11
- package/dist/extensions/question/render-cache.js.map +1 -1
- package/dist/extensions/todo/index.d.ts.map +1 -1
- package/dist/extensions/todo/index.js +12 -8
- package/dist/extensions/todo/index.js.map +1 -1
- package/dist/extensions/todo/view.d.ts +3 -3
- package/dist/extensions/todo/view.d.ts.map +1 -1
- package/dist/extensions/todo/view.js +7 -6
- package/dist/extensions/todo/view.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/status-marker.d.ts +2 -2
- package/dist/modes/interactive/components/status-marker.js +2 -2
- package/dist/modes/interactive/components/status-marker.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -10
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +2 -3
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +20 -0
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/chat.js +46 -0
- package/dist/modes/interactive/tool-view/chat.js.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts +14 -0
- package/dist/modes/interactive/tool-view/fallback.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/fallback.js +52 -0
- package/dist/modes/interactive/tool-view/fallback.js.map +1 -0
- package/dist/modes/interactive/tool-view/style.d.ts +63 -0
- package/dist/modes/interactive/tool-view/style.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/style.js +83 -0
- package/dist/modes/interactive/tool-view/style.js.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.d.ts +17 -24
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/{components → tool-view}/tool-execution.js +42 -116
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -0
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/background.md +1 -1
- package/docs/bundled/extensions/question.md +6 -5
- package/docs/bundled/tool-presentation.md +41 -31
- package/docs/extensions.md +1 -4
- package/docs/keybindings.md +11 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/core/model-stream-options.d.ts +0 -6
- package/dist/core/model-stream-options.d.ts.map +0 -1
- package/dist/core/model-stream-options.js +0 -20
- package/dist/core/model-stream-options.js.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts +0 -28
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-chrome.js +0 -84
- package/dist/modes/interactive/components/tool-chrome.js.map +0 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-execution.js.map +0 -1
- package/dist/modes/interactive/components/tool-group.d.ts +0 -17
- package/dist/modes/interactive/components/tool-group.d.ts.map +0 -1
- package/dist/modes/interactive/components/tool-group.js +0 -78
- package/dist/modes/interactive/components/tool-group.js.map +0 -1
- package/dist/modes/interactive/tool-chat.d.ts +0 -21
- package/dist/modes/interactive/tool-chat.d.ts.map +0 -1
- package/dist/modes/interactive/tool-chat.js +0 -58
- package/dist/modes/interactive/tool-chat.js.map +0 -1
|
@@ -632,7 +632,7 @@ File: ${path14}`)}let config=parsed,providers=new Map;for(let[providerId,provide
|
|
|
632
632
|
`):void 0}getRegisteredProviderConfig(providerId){return this.extensionProviders.get(providerId)}getRegisteredProviderIds(){return[...new Set([...this.extensionProviders.keys(),...this.nativeExtensionProviders.keys()])]}getRegisteredNativeProvider(providerId){return this.nativeExtensionProviders.get(providerId)}getCompatibilityRequestConfig(model){return resolveCompatibilityRequestConfig(model,this.config.getProvider(model.provider),this.extensionProviders.get(model.provider))}isUsingOAuth(providerId){return this.snapshot.auth.get(providerId)?.type==="oauth"}isUsingSubscription(providerId){return this.isUsingOAuth(providerId)&&this.models.getProvider(providerId)?.auth.oauth?.isSubscription===!0}hasConfiguredAuth(providerId){return this.snapshot.configuredProviders.has(providerId)}async getAuth(providerOrModel,overrides={}){if(typeof providerOrModel=="string")return this.models.getAuth(providerOrModel,overrides);let resolution=await this.models.getAuth(providerOrModel,overrides);if(!resolution)return;let configuredHeaders2=resolveConfiguredModelHeaders(providerOrModel,this.config.getProvider(providerOrModel.provider),this.extensionProviders.get(providerOrModel.provider),{...resolution.env??{},...overrides.env??{}});return{...resolution,auth:{...resolution.auth,headers:mergeHeaders(resolution.auth.headers,configuredHeaders2)}}}enqueueCredentialOperation(providerId,signal,task){let previous=this.credentialOperations.get(providerId)??Promise.resolve(),markStarted,started=new Promise(resolve17=>{markStarted=resolve17}),operation=(async()=>(await previous.catch(()=>{}),signal.throwIfAborted(),markStarted?.(),task()))(),tail=operation.catch(()=>{});return this.credentialOperations.set(providerId,tail),tail.then(()=>{this.credentialOperations.get(providerId)===tail&&this.credentialOperations.delete(providerId)}),raceWithAbortSignal(started,signal).then(()=>operation)}async synchronizeCredentialState(providerId,operation,credential,signal){try{signal.throwIfAborted(),this.recomposeProvider(providerId);let compositionError=this.compositionErrors.get(providerId);if(compositionError)throw new Error(compositionError);let result2=await this.models.refresh({allowNetwork:!1,providers:[providerId],signal});result2.aborted&&signal.throwIfAborted();let refreshError=result2.errors.get(providerId);if(refreshError)throw refreshError;this.updateModelSnapshot(),await this.refreshProviderAvailability(providerId,signal)}catch(cause){throw new CredentialSynchronizationError(providerId,operation,credential,{cause})}}setRuntimeApiKey(providerId,apiKey,options={}){let signal=operationSignal(options.signal);return this.enqueueCredentialOperation(providerId,signal,async()=>{this.credentials.setRuntimeApiKey(providerId,apiKey),await this.synchronizeCredentialState(providerId,"setRuntimeApiKey",{type:"api_key",key:apiKey},signal)})}removeRuntimeApiKey(providerId,options={}){let signal=operationSignal(options.signal);return this.enqueueCredentialOperation(providerId,signal,async()=>{this.credentials.removeRuntimeApiKey(providerId),await this.synchronizeCredentialState(providerId,"removeRuntimeApiKey",void 0,signal)})}listCredentials(options){return this.credentials.list(options)}getProviderAuthStatus(providerId){if(this.credentials.hasRuntimeApiKey(providerId))return{configured:!0,source:"runtime"};if(this.snapshot.storedProviders.has(providerId))return{configured:!0,source:"stored"};let configured=configuredRequestAuthStatus(this.config.getProvider(providerId),this.extensionProviders.get(providerId));if(configured)return configured;let check=this.snapshot.auth.get(providerId);return check?{configured:!0,source:"environment",label:check.source}:{configured:!1}}async prepareRequest(model,options){let provider=this.models.getProvider(model.provider);if(!provider)throw new ModelsError("provider",`Unknown provider: ${model.provider}`);let resolution=await this.getAuth(model,{apiKey:options?.apiKey,env:options?.env,signal:options?.signal});if(!resolution)throw new ModelsError("auth",`Provider is not configured: ${model.provider}`);let{transformHeaders,...rawProviderOptions}=options??{},providerOptions=rawProviderOptions,headers=mergeHeaders(resolution.auth.headers,providerOptions.headers);transformHeaders&&(headers=await transformHeaders(headers??{}));let env2=resolution.env||providerOptions.env?{...resolution.env??{},...providerOptions.env??{}}:void 0;return{provider,model:resolution.auth.baseUrl?{...model,baseUrl:resolution.auth.baseUrl}:model,options:{...providerOptions,apiKey:providerOptions.apiKey??resolution.auth.apiKey,headers,env:env2}}}stream(model,context,options){let transcript=normalizeContext(context);return lazyStream(model,async()=>{let prepared=await this.prepareRequest(model,options);return prepared.provider.stream(prepared.model,transcript,prepared.options)})}complete(model,context,options){return this.stream(model,context,options).result()}streamSimple(model,context,options){let transcript=normalizeContext(context);return lazyStream(model,async()=>{let prepared=await this.prepareRequest(model,options);return prepared.provider.streamSimple(prepared.model,transcript,prepared.options)})}completeSimple(model,context,options){return this.streamSimple(model,context,options).result()}streamDeferred(model,handle,options){return lazyStream(model,async()=>{let prepared=await this.prepareRequest(model,options);if(!prepared.provider.fetchDeferred)throw new ModelsError("provider",`Provider ${model.provider} does not support deferred responses`);return prepared.provider.fetchDeferred(prepared.model,handle,prepared.options)})}async fetchDeferred(model,handle,options){return this.streamDeferred(model,handle,options).result()}async cancelDeferred(model,handle,options){let prepared=await this.prepareRequest(model,options);if(!prepared.provider.cancelDeferred)throw new ModelsError("provider",`Provider ${model.provider} does not support deferred responses`);await prepared.provider.cancelDeferred(prepared.model,handle,prepared.options)}login(providerId,type,interaction){let signal=operationSignal(interaction.signal);return this.enqueueCredentialOperation(providerId,signal,async()=>{let credential=await this.models.login(providerId,type,{...interaction,signal});return await this.synchronizeCredentialState(providerId,"login",credential,signal),credential})}logout(providerId,options={}){let signal=operationSignal(options.signal);return this.enqueueCredentialOperation(providerId,signal,async()=>{await this.models.logout(providerId,{signal}),await this.synchronizeCredentialState(providerId,"logout",void 0,signal)})}async refresh(options={}){if(this.config=await ModelConfig.load(this.modelsPath),this.configureRadiusProviders(),options.providers){for(let providerId of new Set(options.providers))this.recomposeProvider(providerId);this.updateModelSnapshot()}else this.rebuildProviders();let refreshOptions={...options,allowNetwork:options.allowNetwork??this.modelNetworkEnabled},result2=await this.models.refresh(refreshOptions)??{aborted:refreshOptions.signal?.aborted??!1,errors:new Map},errors=new Map(result2.errors);if(this.updateModelSnapshot(),options.providers)await Promise.all([...new Set(options.providers)].map(async providerId=>{try{await this.refreshProviderAvailability(providerId,operationSignal(options.signal))}catch(error){options.signal?.aborted||errors.set(providerId,error instanceof Error?error:new Error(String(error)))}}));else try{await this.queueAvailabilityRefresh(options.signal)}catch{}return{aborted:result2.aborted||(options.signal?.aborted??!1),errors}}registerNativeProvider(provider){if(!provider.id.trim())throw new Error("Provider id must not be empty.");this.extensionProviders.delete(provider.id),this.nativeExtensionProviders.set(provider.id,provider),this.recomposeProvider(provider.id),this.updateModelSnapshot(),this.refresh({allowNetwork:!1})}registerProvider(providerId,config){validateExtensionProvider(providerId,this.builtins.get(providerId),this.config.getProvider(providerId),config),this.nativeExtensionProviders.delete(providerId);let effective={...this.extensionProviders.get(providerId)};for(let[key,value2]of Object.entries(config))value2!==void 0&&(effective[key]=value2);if(this.extensionProviders.set(providerId,effective),this.recomposeProvider(providerId),this.updateModelSnapshot(),this.snapshot.storedProviders.has(providerId)||configuredRequestAuthStatus(this.config.getProvider(providerId),effective)?.configured){let configuredProviders=new Set(this.snapshot.configuredProviders).add(providerId),auth=new Map(this.snapshot.auth);auth.get(providerId)||auth.set(providerId,{type:effective.oauth&&!effective.apiKey?"oauth":"api_key",source:"configured provider"}),this.snapshot={...this.snapshot,auth,configuredProviders,available:this.snapshot.all.filter(model=>configuredProviders.has(model.provider))}}this.refresh({allowNetwork:!1})}unregisterProvider(providerId){this.extensionProviders.delete(providerId),this.nativeExtensionProviders.delete(providerId),this.recomposeProvider(providerId),this.updateModelSnapshot(),this.refresh({allowNetwork:!1})}};function readOrientationFromTiff(bytes,tiffStart){if(tiffStart+8>bytes.length)return 1;let le2=(bytes[tiffStart]<<8|bytes[tiffStart+1])===18761,read16=pos=>le2?bytes[pos]|bytes[pos+1]<<8:bytes[pos]<<8|bytes[pos+1],ifdOffset=(pos=>le2?bytes[pos]|bytes[pos+1]<<8|bytes[pos+2]<<16|bytes[pos+3]<<24:(bytes[pos]<<24|bytes[pos+1]<<16|bytes[pos+2]<<8|bytes[pos+3])>>>0)(tiffStart+4),ifdStart=tiffStart+ifdOffset;if(ifdStart+2>bytes.length)return 1;let entryCount=read16(ifdStart);for(let i=0;i<entryCount;i++){let entryPos=ifdStart+2+i*12;if(entryPos+12>bytes.length)return 1;if(read16(entryPos)===274){let value2=read16(entryPos+8);return value2>=1&&value2<=8?value2:1}}return 1}function findJpegTiffOffset(bytes){let offset=2;for(;offset<bytes.length-1;){if(bytes[offset]!==255)return-1;let marker=bytes[offset+1];if(marker===255){offset++;continue}if(marker===225){if(offset+4>=bytes.length)return-1;let segmentStart=offset+4;if(segmentStart+6>bytes.length)return-1;if(hasExifHeader(bytes,segmentStart))return segmentStart+6}if(offset+4>bytes.length)return-1;let length=bytes[offset+2]<<8|bytes[offset+3];offset+=2+length}return-1}function findWebpTiffOffset(bytes){let offset=12;for(;offset+8<=bytes.length;){let chunkId=String.fromCharCode(bytes[offset],bytes[offset+1],bytes[offset+2],bytes[offset+3]),chunkSize=bytes[offset+4]|bytes[offset+5]<<8|bytes[offset+6]<<16|bytes[offset+7]<<24,dataStart=offset+8;if(chunkId==="EXIF")return dataStart+chunkSize>bytes.length?-1:chunkSize>=6&&hasExifHeader(bytes,dataStart)?dataStart+6:dataStart;offset=dataStart+chunkSize+chunkSize%2}return-1}function hasExifHeader(bytes,offset){return bytes[offset]===69&&bytes[offset+1]===120&&bytes[offset+2]===105&&bytes[offset+3]===102&&bytes[offset+4]===0&&bytes[offset+5]===0}function getExifOrientation(bytes){let tiffOffset=-1;return bytes.length>=2&&bytes[0]===255&&bytes[1]===216?tiffOffset=findJpegTiffOffset(bytes):bytes.length>=12&&bytes[0]===82&&bytes[1]===73&&bytes[2]===70&&bytes[3]===70&&bytes[8]===87&&bytes[9]===69&&bytes[10]===66&&bytes[11]===80&&(tiffOffset=findWebpTiffOffset(bytes)),tiffOffset===-1?1:readOrientationFromTiff(bytes,tiffOffset)}function rotate90(photon,image,dstIndex){let w=image.get_width(),h=image.get_height(),src=image.get_raw_pixels(),dst=new Uint8Array(src.length);for(let y2=0;y2<h;y2++)for(let x2=0;x2<w;x2++){let srcIdx=(y2*w+x2)*4,dstIdx=dstIndex(x2,y2,w,h)*4;dst[dstIdx]=src[srcIdx],dst[dstIdx+1]=src[srcIdx+1],dst[dstIdx+2]=src[srcIdx+2],dst[dstIdx+3]=src[srcIdx+3]}return new photon.PhotonImage(dst,h,w)}function applyExifOrientation(photon,image,originalBytes){let orientation=getExifOrientation(originalBytes);if(orientation===1)return image;switch(orientation){case 2:return photon.fliph(image),image;case 3:return photon.fliph(image),photon.flipv(image),image;case 4:return photon.flipv(image),image;case 5:{let rotated=rotate90(photon,image,(x2,y2,_w,h)=>x2*h+(h-1-y2));return photon.fliph(rotated),rotated}case 6:return rotate90(photon,image,(x2,y2,_w,h)=>x2*h+(h-1-y2));case 7:{let rotated=rotate90(photon,image,(x2,y2,w,h)=>(w-1-x2)*h+y2);return photon.fliph(rotated),rotated}case 8:return rotate90(photon,image,(x2,y2,w,h)=>(w-1-x2)*h+y2);default:return image}}import{createRequire as createRequire3}from"module";import*as path5 from"path";import{fileURLToPath as fileURLToPath4}from"url";var require2=createRequire3(import.meta.url),fs3=require2("fs"),WASM_FILENAME="photon_rs_bg.wasm",photonModule=null,loadPromise=null;function pathOrNull(file){return typeof file=="string"?file:file instanceof URL?fileURLToPath4(file):null}function getFallbackWasmPaths(){let execDir=path5.dirname(process.execPath);return[path5.join(execDir,WASM_FILENAME),path5.join(execDir,"photon",WASM_FILENAME),path5.join(process.cwd(),WASM_FILENAME)]}function patchPhotonWasmRead(){let originalReadFileSync=fs3.readFileSync.bind(fs3),fallbackPaths=getFallbackWasmPaths(),mutableFs=fs3,patchedReadFileSync=((...args)=>{let[file,options]=args;if(pathOrNull(file)?.endsWith(WASM_FILENAME))try{return originalReadFileSync(...args)}catch(error){let err2=error;if(err2?.code&&err2.code!=="ENOENT")throw error;for(let fallbackPath of fallbackPaths)if(fs3.existsSync(fallbackPath))return options===void 0?originalReadFileSync(fallbackPath):originalReadFileSync(fallbackPath,options);throw error}return originalReadFileSync(...args)});try{mutableFs.readFileSync=patchedReadFileSync}catch{Object.defineProperty(fs3,"readFileSync",{value:patchedReadFileSync,writable:!0,configurable:!0})}return()=>{try{mutableFs.readFileSync=originalReadFileSync}catch{Object.defineProperty(fs3,"readFileSync",{value:originalReadFileSync,writable:!0,configurable:!0})}}}async function loadPhoton(){return photonModule||loadPromise||(loadPromise=(async()=>{let restoreReadFileSync=patchPhotonWasmRead();try{return photonModule=await import("@silvia-odwyer/photon-node"),photonModule}catch{return photonModule=null,photonModule}finally{restoreReadFileSync()}})(),loadPromise)}async function convertImageBytesToPng(bytes){let photon=await loadPhoton();if(!photon)return null;try{let rawImage=photon.PhotonImage.new_from_byteslice(bytes),image=applyExifOrientation(photon,rawImage,bytes);image!==rawImage&&rawImage.free();try{return new Uint8Array(image.get_bytes())}finally{image.free()}}catch{return null}}async function convertToPng(base64Data,mimeType){if(mimeType==="image/png")return{data:base64Data,mimeType};let bytes=new Uint8Array(Buffer.from(base64Data,"base64")),pngBytes=await convertImageBytesToPng(bytes);return pngBytes?{data:Buffer.from(pngBytes).toString("base64"),mimeType:"image/png"}:null}import{Worker}from"node:worker_threads";var DEFAULT_MAX_BYTES=4.5*1024*1024,DEFAULT_OPTIONS={maxWidth:2e3,maxHeight:2e3,maxBytes:DEFAULT_MAX_BYTES,jpegQuality:80};function encodeCandidate(buffer,mimeType){let data=Buffer.from(buffer).toString("base64");return{data,encodedSize:Buffer.byteLength(data,"utf-8"),mimeType}}async function resizeImageInProcess(inputBytes,mimeType,options){let opts={...DEFAULT_OPTIONS,...options},inputBase64Size=Math.ceil(inputBytes.byteLength/3)*4,photon=await loadPhoton();if(!photon)return null;let image;try{let tryEncodings=function(width,height,jpegQualities){let resized=photon.resize(image,width,height,photon.SamplingFilter.Lanczos3);try{let candidates=[encodeCandidate(resized.get_bytes(),"image/png")];for(let quality of jpegQualities)candidates.push(encodeCandidate(resized.get_bytes_jpeg(quality),"image/jpeg"));return candidates}finally{resized.free()}},rawImage=photon.PhotonImage.new_from_byteslice(inputBytes);image=applyExifOrientation(photon,rawImage,inputBytes),image!==rawImage&&rawImage.free();let originalWidth=image.get_width(),originalHeight=image.get_height(),format=mimeType.split("/")[1]??"png";if(originalWidth<=opts.maxWidth&&originalHeight<=opts.maxHeight&&inputBase64Size<opts.maxBytes)return{data:Buffer.from(inputBytes).toString("base64"),mimeType:mimeType||`image/${format}`,originalWidth,originalHeight,width:originalWidth,height:originalHeight,wasResized:!1};let targetWidth=originalWidth,targetHeight=originalHeight;targetWidth>opts.maxWidth&&(targetHeight=Math.round(targetHeight*opts.maxWidth/targetWidth),targetWidth=opts.maxWidth),targetHeight>opts.maxHeight&&(targetWidth=Math.round(targetWidth*opts.maxHeight/targetHeight),targetHeight=opts.maxHeight);let qualitySteps=Array.from(new Set([opts.jpegQuality,85,70,55,40])),currentWidth=targetWidth,currentHeight=targetHeight;for(;;){let candidates=tryEncodings(currentWidth,currentHeight,qualitySteps);for(let candidate of candidates)if(candidate.encodedSize<opts.maxBytes)return{data:candidate.data,mimeType:candidate.mimeType,originalWidth,originalHeight,width:currentWidth,height:currentHeight,wasResized:!0};if(currentWidth===1&¤tHeight===1)break;let nextWidth=currentWidth===1?1:Math.max(1,Math.floor(currentWidth*.75)),nextHeight=currentHeight===1?1:Math.max(1,Math.floor(currentHeight*.75));if(nextWidth===currentWidth&&nextHeight===currentHeight)break;currentWidth=nextWidth,currentHeight=nextHeight}return null}catch{return null}finally{image&&image.free()}}function toTransferableBytes(input2){return new Uint8Array(input2)}function isResizeImageWorkerResponse(value2){return value2!==null&&typeof value2=="object"}function createResizeWorker(workerSpecifier){return new Worker(workerSpecifier)}async function resizeImageInWorker(workerSpecifier,inputBytes,mimeType,options){let worker=createResizeWorker(workerSpecifier);try{let inputBytesForWorker=toTransferableBytes(inputBytes);return await new Promise((resolve17,reject)=>{let settled=!1,settle=result2=>{settled||(settled=!0,resolve17(result2))},fail=error=>{settled||(settled=!0,reject(error))};worker.once("message",message=>{if(!isResizeImageWorkerResponse(message)){fail(new Error("Invalid image resize worker response"));return}if(message.error){fail(new Error(message.error));return}settle(message.result??null)}),worker.once("error",fail),worker.once("exit",code=>{settled||fail(new Error(`Image resize worker exited with code ${code}`))}),worker.postMessage({inputBytes:inputBytesForWorker,mimeType,options},[inputBytesForWorker.buffer])})}finally{worker.terminate().catch(()=>{})}}async function resizeImage(inputBytes,mimeType,options){let isTypeScriptRuntime=import.meta.url.endsWith(".ts"),workerUrl=new URL(isTypeScriptRuntime?"./image-resize-worker.ts":"./image-resize-worker.js",import.meta.url);if(typeof process.versions.bun=="string")try{return await resizeImageInWorker("./src/utils/image-resize-worker.ts",inputBytes,mimeType,options)}catch{}try{return await resizeImageInWorker(workerUrl,inputBytes,mimeType,options)}catch{return resizeImageInProcess(inputBytes,mimeType,options)}}function formatDimensionNote(result2){if(!result2.wasResized)return;let scale=result2.originalWidth/result2.width;return`[Image: original ${result2.originalWidth}x${result2.originalHeight}, displayed at ${result2.width}x${result2.height}. Multiply coordinates by ${scale.toFixed(2)} to map to original image.]`}import{open}from"node:fs/promises";var IMAGE_TYPE_SNIFF_BYTES=4100,PNG_SIGNATURE=[137,80,78,71,13,10,26,10];function detectSupportedImageMimeType(buffer){return startsWith(buffer,[255,216,255])?buffer[3]===247?null:"image/jpeg":startsWith(buffer,PNG_SIGNATURE)?isPng(buffer)&&!isAnimatedPng(buffer)?"image/png":null:startsWithAscii(buffer,0,"GIF87a")||startsWithAscii(buffer,0,"GIF89a")?"image/gif":startsWithAscii(buffer,0,"RIFF")&&startsWithAscii(buffer,8,"WEBP")?"image/webp":startsWithAscii(buffer,0,"BM")&&isBmp(buffer)?"image/bmp":null}async function detectSupportedImageMimeTypeFromFile(filePath){let fileHandle=await open(filePath,"r");try{let buffer=Buffer.alloc(IMAGE_TYPE_SNIFF_BYTES),{bytesRead}=await fileHandle.read(buffer,0,IMAGE_TYPE_SNIFF_BYTES,0);return detectSupportedImageMimeType(buffer.subarray(0,bytesRead))}finally{await fileHandle.close()}}function isPng(buffer){return buffer.length>=16&&readUint32BE(buffer,PNG_SIGNATURE.length)===13&&startsWithAscii(buffer,12,"IHDR")}function isAnimatedPng(buffer){let offset=PNG_SIGNATURE.length;for(;offset+8<=buffer.length;){let chunkLength=readUint32BE(buffer,offset),chunkTypeOffset=offset+4;if(startsWithAscii(buffer,chunkTypeOffset,"acTL"))return!0;if(startsWithAscii(buffer,chunkTypeOffset,"IDAT"))return!1;let nextOffset=offset+8+chunkLength+4;if(nextOffset<=offset||nextOffset>buffer.length)return!1;offset=nextOffset}return!1}function isBmp(buffer){if(buffer.length<26)return!1;let declaredFileSize=readUint32LE(buffer,2),pixelDataOffset=readUint32LE(buffer,10),dibHeaderSize=readUint32LE(buffer,14);if(declaredFileSize!==0&&declaredFileSize<26||pixelDataOffset<14+dibHeaderSize||declaredFileSize!==0&&pixelDataOffset>=declaredFileSize)return!1;let colorPlanes,bitsPerPixel;if(dibHeaderSize===12)colorPlanes=readUint16LE(buffer,22),bitsPerPixel=readUint16LE(buffer,24);else if(dibHeaderSize>=40&&dibHeaderSize<=124){if(buffer.length<30)return!1;colorPlanes=readUint16LE(buffer,26),bitsPerPixel=readUint16LE(buffer,28)}else return!1;return colorPlanes===1&&[1,4,8,16,24,32].includes(bitsPerPixel)}function readUint16LE(buffer,offset){return(buffer[offset]??0)+((buffer[offset+1]??0)<<8)}function readUint32BE(buffer,offset){return(buffer[offset]??0)*16777216+((buffer[offset+1]??0)<<16)+((buffer[offset+2]??0)<<8)+(buffer[offset+3]??0)}function readUint32LE(buffer,offset){return(buffer[offset]??0)+((buffer[offset+1]??0)<<8)+((buffer[offset+2]??0)<<16)+(buffer[offset+3]??0)*16777216}function startsWith(buffer,bytes){return buffer.length<bytes.length?!1:bytes.every((byte,index3)=>buffer[index3]===byte)}function startsWithAscii(buffer,offset,text2){if(buffer.length<offset+text2.length)return!1;for(let index3=0;index3<text2.length;index3++)if(buffer[offset+index3]!==text2.charCodeAt(index3))return!1;return!0}var import_ignore=__toESM(require_ignore(),1);import{createHash}from"node:crypto";import{chmodSync,existsSync as existsSync4,globSync,mkdirSync as mkdirSync3,readdirSync as readdirSync2,readFileSync as readFileSync4,rmSync,statSync as statSync4,writeFileSync as writeFileSync3}from"node:fs";import{homedir as homedir5}from"node:os";import{basename as basename3,dirname as dirname8,join as join13,relative as relative2,resolve as resolve2,sep as sep4}from"node:path";var import_semver=__toESM(require_semver2(),1);var import_hosted_git_info=__toESM(require_lib(),1);function splitRef(url){let scpLikeMatch=url.match(/^git@([^:]+):(.+)$/);if(scpLikeMatch){let pathWithMaybeRef2=scpLikeMatch[2]??"",refSeparator2=pathWithMaybeRef2.indexOf("@");if(refSeparator2<0)return{repo:url};let repoPath2=pathWithMaybeRef2.slice(0,refSeparator2),ref2=pathWithMaybeRef2.slice(refSeparator2+1);return!repoPath2||!ref2?{repo:url}:{repo:`git@${scpLikeMatch[1]??""}:${repoPath2}`,ref:ref2}}if(url.includes("://"))try{let parsed=new URL(url),pathWithMaybeRef2=parsed.pathname.replace(/^\/+/,""),refSeparator2=pathWithMaybeRef2.indexOf("@");if(refSeparator2<0)return{repo:url};let repoPath2=pathWithMaybeRef2.slice(0,refSeparator2),ref2=pathWithMaybeRef2.slice(refSeparator2+1);return!repoPath2||!ref2?{repo:url}:(parsed.pathname=`/${repoPath2}`,{repo:parsed.toString().replace(/\/$/,""),ref:ref2})}catch{return{repo:url}}let slashIndex=url.indexOf("/");if(slashIndex<0)return{repo:url};let host=url.slice(0,slashIndex),pathWithMaybeRef=url.slice(slashIndex+1),refSeparator=pathWithMaybeRef.indexOf("@");if(refSeparator<0)return{repo:url};let repoPath=pathWithMaybeRef.slice(0,refSeparator),ref=pathWithMaybeRef.slice(refSeparator+1);return!repoPath||!ref?{repo:url}:{repo:`${host}/${repoPath}`,ref}}function decodeForValidation(value2){try{return decodeURIComponent(value2)}catch{return null}}function hasUnsafeGitInstallPart(value2,allowSlash){let decoded=decodeForValidation(value2);if(decoded===null)return!0;let candidates=[value2,decoded];for(let candidate of candidates)if(candidate.includes("\0")||candidate.includes("\\")||candidate.startsWith("/")||!allowSlash&&candidate.includes("/")||candidate.split("/").includes(".."))return!0;return!1}function buildGitSource(args){if(args.path.startsWith("/"))return null;let normalizedPath=args.path.replace(/\.git$/,"").replace(/^\/+/,"");return!args.host||!normalizedPath||normalizedPath.split("/").length<2||hasUnsafeGitInstallPart(args.host,!1)||hasUnsafeGitInstallPart(normalizedPath,!0)?null:{type:"git",repo:args.repo,host:args.host,path:normalizedPath,ref:args.ref,pinned:!!args.ref}}function parseGenericGitUrl(url){let{repo:repoWithoutRef,ref}=splitRef(url),repo=repoWithoutRef,host="",path14="",scpLikeMatch=repoWithoutRef.match(/^git@([^:]+):(.+)$/);if(scpLikeMatch)host=scpLikeMatch[1]??"",path14=scpLikeMatch[2]??"";else if(repoWithoutRef.startsWith("https://")||repoWithoutRef.startsWith("http://")||repoWithoutRef.startsWith("ssh://")||repoWithoutRef.startsWith("git://"))try{let parsed=new URL(repoWithoutRef);host=parsed.hostname,path14=parsed.pathname.replace(/^\/+/,"")}catch{return null}else{let slashIndex=repoWithoutRef.indexOf("/");if(slashIndex<0||(host=repoWithoutRef.slice(0,slashIndex),path14=repoWithoutRef.slice(slashIndex+1),!host.includes(".")&&host!=="localhost"))return null;repo=`https://${repoWithoutRef}`}return buildGitSource({repo,host,path:path14,ref})}function parseGitUrl(source){let trimmed=source.trim(),hasGitPrefix=trimmed.startsWith("git:"),url=hasGitPrefix?trimmed.slice(4).trim():trimmed;if(!hasGitPrefix&&!/^(https?|ssh|git):\/\//i.test(url))return null;let split=splitRef(url),hostedCandidates=[split.ref?`${split.repo}#${split.ref}`:void 0,url].filter(value2=>!!value2);for(let candidate of hostedCandidates){let info=import_hosted_git_info.default.fromUrl(candidate);if(info){if(split.ref&&info.project?.includes("@"))continue;let useHttpsPrefix=!split.repo.startsWith("http://")&&!split.repo.startsWith("https://")&&!split.repo.startsWith("ssh://")&&!split.repo.startsWith("git://")&&!split.repo.startsWith("git@");return buildGitSource({repo:useHttpsPrefix?`https://${split.repo}`:split.repo,host:info.domain||"",path:`${info.user}/${info.project}`,ref:info.committish||split.ref||void 0})}}let httpsCandidates=[split.ref?`https://${split.repo}#${split.ref}`:void 0,`https://${url}`].filter(value2=>!!value2);for(let candidate of httpsCandidates){let info=import_hosted_git_info.default.fromUrl(candidate);if(info){if(split.ref&&info.project?.includes("@"))continue;return buildGitSource({repo:`https://${split.repo}`,host:info.domain||"",path:`${info.user}/${info.project}`,ref:info.committish||split.ref||void 0})}}return parseGenericGitUrl(url)}var stdoutTakeoverState;var rawStdoutWriteTail=Promise.resolve();function getRawStdoutWrite(){return stdoutTakeoverState?stdoutTakeoverState.rawStdoutWrite:process.stdout.write.bind(process.stdout)}async function writeRawStdoutChunk(text2){for(;;)try{await new Promise((resolve17,reject)=>{try{getRawStdoutWrite()(text2,error=>{error?reject(error):resolve17()})}catch(error){reject(error instanceof Error?error:new Error(String(error)))}});return}catch(error){let writeError=error instanceof Error?error:new Error(String(error)),code=writeError.code;if(code!=="ENOBUFS"&&code!=="EAGAIN"&&code!=="EWOULDBLOCK")throw writeError;await new Promise(resolve17=>setTimeout(resolve17,10))}}function takeOverStdout(){if(stdoutTakeoverState)return;let rawStdoutWrite=process.stdout.write.bind(process.stdout),rawStderrWrite=process.stderr.write.bind(process.stderr),originalStdoutWrite=process.stdout.write;process.stdout.write=((chunk,encodingOrCallback,callback)=>typeof encodingOrCallback=="function"?rawStderrWrite(String(chunk),encodingOrCallback):rawStderrWrite(String(chunk),callback)),stdoutTakeoverState={rawStdoutWrite,rawStderrWrite,originalStdoutWrite}}function restoreStdout(){stdoutTakeoverState&&(process.stdout.write=stdoutTakeoverState.originalStdoutWrite,stdoutTakeoverState=void 0)}function isStdoutTakenOver(){return stdoutTakeoverState!==void 0}function writeRawStdout(text2){text2.length!==0&&(rawStdoutWriteTail=rawStdoutWriteTail.then(()=>writeRawStdoutChunk(text2)),rawStdoutWriteTail.catch(()=>{process.exit(1)}))}async function waitForRawStdoutBackpressure(){for(;;){let tail=rawStdoutWriteTail;if(await tail,tail===rawStdoutWriteTail)return}}async function flushRawStdout(){await waitForRawStdoutBackpressure(),await writeRawStdoutChunk("")}import{readFileSync as readFileSync3}from"node:fs";var RESOURCE_FIELDS=["extensions","skills","prompts","themes"];function isObject(value2){return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)}function readPiManifest(packageJsonPath){try{let pkg2=JSON.parse(stripBom(readFileSync3(packageJsonPath,"utf-8")));if(!isObject(pkg2)||!isObject(pkg2.pi))return null;let manifest={};for(let field3 of RESOURCE_FIELDS){let entries=pkg2.pi[field3];Array.isArray(entries)&&entries.every(entry=>typeof entry=="string")&&(manifest[field3]=entries)}return manifest}catch{return null}}function getEnv(){if(process.platform!=="linux"||Object.keys(process.env).length>0)return process.env;try{let data=readFileSync4("/proc/self/environ","utf-8"),env2={};for(let entry of data.split("\0")){let idx=entry.indexOf("=");idx>0&&(env2[entry.slice(0,idx)]=entry.slice(idx+1))}return env2}catch{return process.env}}var NETWORK_TIMEOUT_MS=1e4,UPDATE_CHECK_CONCURRENCY=4,GIT_UPDATE_CONCURRENCY=4;function isOfflineModeEnabled(){let value2=process.env.PI_OFFLINE;return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}function isExactNpmVersion(version2){return(0,import_semver.valid)(version2??"")!==null}function getNpmVersionRange(version2){return version2?(0,import_semver.validRange)(version2)??void 0:void 0}function resourcePrecedenceRank(m2){return m2.origin==="package"?4:(m2.scope==="project"?0:2)+(m2.source==="local"?0:1)}var RESOURCE_TYPES=["extensions","skills","prompts","themes"],FILE_PATTERNS={extensions:/\.(ts|js)$/,skills:/\.md$/,prompts:/\.md$/,themes:/\.json$/},IGNORE_FILE_NAMES=[".gitignore",".ignore",".fdignore"];function toPosixPath(p){return p.split(sep4).join("/")}function getHomeDir(){return process.env.HOME||homedir5()}function getExtensionTempFolder(agentDir){let tempFolder=join13(agentDir,"tmp","extensions");return mkdirSync3(tempFolder,{recursive:!0,mode:448}),chmodSync(tempFolder,448),tempFolder}function prefixIgnorePattern(line,prefix){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#")&&!trimmed.startsWith("\\#"))return null;let pattern=line,negated=!1;pattern.startsWith("!")?(negated=!0,pattern=pattern.slice(1)):pattern.startsWith("\\!")&&(pattern=pattern.slice(1)),pattern.startsWith("/")&&(pattern=pattern.slice(1));let prefixed=prefix?`${prefix}${pattern}`:pattern;return negated?`!${prefixed}`:prefixed}function addIgnoreRules(ig,dir,rootDir){let relativeDir=relative2(rootDir,dir),prefix=relativeDir?`${toPosixPath(relativeDir)}/`:"";for(let filename of IGNORE_FILE_NAMES){let ignorePath=join13(dir,filename);if(existsSync4(ignorePath))try{let patterns=readFileSync4(ignorePath,"utf-8").split(/\r?\n/).map(line=>prefixIgnorePattern(line,prefix)).filter(line=>!!line);patterns.length>0&&ig.add(patterns)}catch{}}}function isPattern(s){return s.startsWith("!")||s.startsWith("+")||s.startsWith("-")||s.includes("*")||s.includes("?")}function isOverridePattern(s){return s.startsWith("!")||s.startsWith("+")||s.startsWith("-")}function hasGlobPattern(s){return s.includes("*")||s.includes("?")}function expandPackageGlob(pattern,root){return globSync(pattern,{cwd:root}).map(match2=>resolve2(root,match2)).filter(path14=>relative2(root,path14).split(sep4).every(segment2=>segment2===".."||!segment2.startsWith("."))).sort((a,b2)=>a<b2?-1:a>b2?1:0)}function splitPatterns(entries){let plain=[],patterns=[];for(let entry of entries)isPattern(entry)?patterns.push(entry):plain.push(entry);return{plain,patterns}}function collectFiles(dir,filePattern,skipNodeModules=!0,ignoreMatcher,rootDir){let files=[];if(!existsSync4(dir))return files;let root=rootDir??dir,ig=ignoreMatcher??(0,import_ignore.default)();addIgnoreRules(ig,dir,root);try{let entries=readdirSync2(dir,{withFileTypes:!0});for(let entry of entries){if(entry.name.startsWith(".")||skipNodeModules&&entry.name==="node_modules")continue;let fullPath=join13(dir,entry.name),isDir=entry.isDirectory(),isFile=entry.isFile();if(entry.isSymbolicLink())try{let stats=statSync4(fullPath);isDir=stats.isDirectory(),isFile=stats.isFile()}catch{continue}let relPath=toPosixPath(relative2(root,fullPath)),ignorePath=isDir?`${relPath}/`:relPath;ig.ignores(ignorePath)||(isDir?files.push(...collectFiles(fullPath,filePattern,skipNodeModules,ig,root)):isFile&&filePattern.test(entry.name)&&files.push(fullPath))}}catch{}return files}function collectSkillEntries(dir,mode,ignoreMatcher,rootDir){let entries=[];if(!existsSync4(dir))return entries;let root=rootDir??dir,ig=ignoreMatcher??(0,import_ignore.default)();addIgnoreRules(ig,dir,root);try{let dirEntries=readdirSync2(dir,{withFileTypes:!0});for(let entry of dirEntries){if(entry.name!=="SKILL.md")continue;let fullPath=join13(dir,entry.name),isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync4(fullPath).isFile()}catch{continue}let relPath=toPosixPath(relative2(root,fullPath));if(isFile&&!ig.ignores(relPath))return entries.push(fullPath),entries}for(let entry of dirEntries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join13(dir,entry.name),isDir=entry.isDirectory(),isFile=entry.isFile();if(entry.isSymbolicLink())try{let stats=statSync4(fullPath);isDir=stats.isDirectory(),isFile=stats.isFile()}catch{continue}let relPath=toPosixPath(relative2(root,fullPath));if(isFile&&entry.name.endsWith(".md")&&!ig.ignores(relPath)&&(mode==="pi"&&dir===root||mode==="agents"&&dir!==root)){entries.push(fullPath);continue}isDir&&(ig.ignores(`${relPath}/`)||entries.push(...collectSkillEntries(fullPath,mode,ig,root)))}}catch{}return entries}function collectAutoSkillEntries(dir,mode){return collectSkillEntries(dir,mode)}function findGitRepoRoot(startDir){let dir=resolve2(startDir);for(;;){if(existsSync4(join13(dir,".git")))return dir;let parent=dirname8(dir);if(parent===dir)return null;dir=parent}}function collectAncestorAgentsSkillDirs(startDir){let skillDirs=[],resolvedStartDir=resolve2(startDir),gitRepoRoot=findGitRepoRoot(resolvedStartDir),dir=resolvedStartDir;for(;skillDirs.push(join13(dir,".agents","skills")),!(gitRepoRoot&&dir===gitRepoRoot);){let parent=dirname8(dir);if(parent===dir)break;dir=parent}return skillDirs}function collectAutoPromptEntries(dir){let entries=[];if(!existsSync4(dir))return entries;let ig=(0,import_ignore.default)();addIgnoreRules(ig,dir,dir);try{let dirEntries=readdirSync2(dir,{withFileTypes:!0});for(let entry of dirEntries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join13(dir,entry.name),isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync4(fullPath).isFile()}catch{continue}let relPath=toPosixPath(relative2(dir,fullPath));ig.ignores(relPath)||isFile&&entry.name.endsWith(".md")&&entries.push(fullPath)}}catch{}return entries}function collectAutoThemeEntries(dir){let entries=[];if(!existsSync4(dir))return entries;let ig=(0,import_ignore.default)();addIgnoreRules(ig,dir,dir);try{let dirEntries=readdirSync2(dir,{withFileTypes:!0});for(let entry of dirEntries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join13(dir,entry.name),isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync4(fullPath).isFile()}catch{continue}let relPath=toPosixPath(relative2(dir,fullPath));ig.ignores(relPath)||isFile&&entry.name.endsWith(".json")&&entries.push(fullPath)}}catch{}return entries}function resolveExtensionEntries(dir){let packageJsonPath=join13(dir,"package.json");if(existsSync4(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=resolve2(dir,extPath);existsSync4(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=join13(dir,"index.ts"),indexJs=join13(dir,"index.js");return existsSync4(indexTs)?[indexTs]:existsSync4(indexJs)?[indexJs]:null}function collectAutoExtensionEntries(dir){let entries=[];if(!existsSync4(dir))return entries;let rootEntries=resolveExtensionEntries(dir);if(rootEntries)return rootEntries;let ig=(0,import_ignore.default)();addIgnoreRules(ig,dir,dir);try{let dirEntries=readdirSync2(dir,{withFileTypes:!0});for(let entry of dirEntries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join13(dir,entry.name),isDir=entry.isDirectory(),isFile=entry.isFile();if(entry.isSymbolicLink())try{let stats=statSync4(fullPath);isDir=stats.isDirectory(),isFile=stats.isFile()}catch{continue}let relPath=toPosixPath(relative2(dir,fullPath)),ignorePath=isDir?`${relPath}/`:relPath;if(!ig.ignores(ignorePath)){if(isFile&&(entry.name.endsWith(".ts")||entry.name.endsWith(".js")))entries.push(fullPath);else if(isDir){let resolvedEntries=resolveExtensionEntries(fullPath);resolvedEntries&&entries.push(...resolvedEntries)}}}}catch{}return entries}function collectResourceFiles(dir,resourceType){return resourceType==="skills"?collectSkillEntries(dir,"pi"):resourceType==="extensions"?collectAutoExtensionEntries(dir):collectFiles(dir,FILE_PATTERNS[resourceType])}function matchesAnyPattern(filePath,patterns,baseDir){let rel=toPosixPath(relative2(baseDir,filePath)),name=basename3(filePath),filePathPosix=toPosixPath(filePath),isSkillFile=name==="SKILL.md",parentDir=isSkillFile?dirname8(filePath):void 0,parentRel=isSkillFile?toPosixPath(relative2(baseDir,parentDir)):void 0,parentName=isSkillFile?basename3(parentDir):void 0,parentDirPosix=isSkillFile?toPosixPath(parentDir):void 0;return patterns.some(pattern=>{let normalizedPattern=toPosixPath(pattern);return minimatch(rel,normalizedPattern)||minimatch(name,normalizedPattern)||minimatch(filePathPosix,normalizedPattern)?!0:isSkillFile?minimatch(parentRel,normalizedPattern)||minimatch(parentName,normalizedPattern)||minimatch(parentDirPosix,normalizedPattern):!1})}function normalizeExactPattern(pattern){let normalized=pattern.startsWith("./")||pattern.startsWith(".\\")?pattern.slice(2):pattern;return toPosixPath(normalized)}function matchesAnyExactPattern(filePath,patterns,baseDir){if(patterns.length===0)return!1;let rel=toPosixPath(relative2(baseDir,filePath)),name=basename3(filePath),filePathPosix=toPosixPath(filePath),isSkillFile=name==="SKILL.md",parentDir=isSkillFile?dirname8(filePath):void 0,parentRel=isSkillFile?toPosixPath(relative2(baseDir,parentDir)):void 0,parentDirPosix=isSkillFile?toPosixPath(parentDir):void 0;return patterns.some(pattern=>{let normalized=normalizeExactPattern(pattern);return normalized===rel||normalized===filePathPosix?!0:isSkillFile?normalized===parentRel||normalized===parentDirPosix:!1})}function getOverridePatterns(entries){return entries.filter(pattern=>pattern.startsWith("!")||pattern.startsWith("+")||pattern.startsWith("-"))}function isEnabledByOverrides(filePath,patterns,baseDir){let overrides=getOverridePatterns(patterns),excludes=overrides.filter(pattern=>pattern.startsWith("!")).map(pattern=>pattern.slice(1)),forceIncludes=overrides.filter(pattern=>pattern.startsWith("+")).map(pattern=>pattern.slice(1)),forceExcludes=overrides.filter(pattern=>pattern.startsWith("-")).map(pattern=>pattern.slice(1)),enabled=!0;return excludes.length>0&&matchesAnyPattern(filePath,excludes,baseDir)&&(enabled=!1),forceIncludes.length>0&&matchesAnyExactPattern(filePath,forceIncludes,baseDir)&&(enabled=!0),forceExcludes.length>0&&matchesAnyExactPattern(filePath,forceExcludes,baseDir)&&(enabled=!1),enabled}function applyPatterns(allPaths,patterns,baseDir){let includes=[],excludes=[],forceIncludes=[],forceExcludes=[];for(let p of patterns)p.startsWith("+")?forceIncludes.push(p.slice(1)):p.startsWith("-")?forceExcludes.push(p.slice(1)):p.startsWith("!")?excludes.push(p.slice(1)):includes.push(p);let result2;if(includes.length===0?result2=[...allPaths]:result2=allPaths.filter(filePath=>matchesAnyPattern(filePath,includes,baseDir)),excludes.length>0&&(result2=result2.filter(filePath=>!matchesAnyPattern(filePath,excludes,baseDir))),forceIncludes.length>0)for(let filePath of allPaths)!result2.includes(filePath)&&matchesAnyExactPattern(filePath,forceIncludes,baseDir)&&result2.push(filePath);return forceExcludes.length>0&&(result2=result2.filter(filePath=>!matchesAnyExactPattern(filePath,forceExcludes,baseDir))),new Set(result2)}function applyAutoloadDisabledPatterns(allPaths,patterns,baseDir){let result2=new Map;for(let pattern of patterns){let target=pattern.slice(pattern.startsWith("+")||pattern.startsWith("-")||pattern.startsWith("!")?1:0),enabled=!pattern.startsWith("-")&&!pattern.startsWith("!"),exact=pattern.startsWith("+")||pattern.startsWith("-");for(let filePath of allPaths)(exact?matchesAnyExactPattern(filePath,[target],baseDir):matchesAnyPattern(filePath,[target],baseDir))&&result2.set(filePath,enabled)}return result2}var DefaultPackageManager=class{constructor(options){this.cwd=resolvePath(options.cwd),this.agentDir=resolvePath(options.agentDir),this.settingsManager=options.settingsManager}setProgressCallback(callback){this.progressCallback=callback}addSourceToSettings(source,options){let scope=options?.local?"project":"user",currentPackages=(scope==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[],normalizedSource=this.normalizePackageSourceForSettings(source,scope),matchIndex=currentPackages.findIndex(existing=>this.packageSourcesMatch(existing,source,scope));if(matchIndex!==-1){let existing=currentPackages[matchIndex];if(this.getPackageSourceString(existing)===normalizedSource)return!1;let nextPackages2=[...currentPackages];return nextPackages2[matchIndex]=typeof existing=="string"?normalizedSource:{...existing,source:normalizedSource},scope==="project"?this.settingsManager.setProjectPackages(nextPackages2):this.settingsManager.setPackages(nextPackages2),!0}let nextPackages=[...currentPackages,normalizedSource];return scope==="project"?this.settingsManager.setProjectPackages(nextPackages):this.settingsManager.setPackages(nextPackages),!0}removeSourceFromSettings(source,options){let scope=options?.local?"project":"user",currentPackages=(scope==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[],nextPackages=currentPackages.filter(existing=>!this.packageSourcesMatch(existing,source,scope));return nextPackages.length!==currentPackages.length?(scope==="project"?this.settingsManager.setProjectPackages(nextPackages):this.settingsManager.setPackages(nextPackages),!0):!1}getInstalledPath(source,scope){let parsed=this.parseSource(source);if(parsed.type==="npm"){let path14=this.getNpmInstallPath(parsed,scope);return existsSync4(path14)?path14:void 0}if(parsed.type==="git"){let path14=this.getGitInstallPath(parsed,scope);return existsSync4(path14)?path14:void 0}if(parsed.type==="local"){let baseDir=this.getBaseDirForScope(scope),path14=this.resolvePathFromBase(parsed.path,baseDir);return existsSync4(path14)?path14:void 0}}emitProgress(event){this.progressCallback?.(event)}async withProgress(action,source,message,operation){this.emitProgress({type:"start",action,source,message});try{await operation(),this.emitProgress({type:"complete",action,source})}catch(error){let errorMessage6=error instanceof Error?error.message:String(error);throw this.emitProgress({type:"error",action,source,message:errorMessage6}),error}}async resolve(onMissing){let accumulator=this.createAccumulator(),globalSettings=this.settingsManager.getGlobalSettings(),projectSettings=this.settingsManager.getProjectSettings(),allPackages=[];for(let pkg2 of projectSettings.packages??[])allPackages.push({pkg:pkg2,scope:"project"});for(let pkg2 of globalSettings.packages??[])allPackages.push({pkg:pkg2,scope:"user"});let packageSources=this.dedupePackages(allPackages);await this.resolvePackageSources(packageSources,accumulator,onMissing);let globalBaseDir=this.agentDir,projectBaseDir=join13(this.cwd,CONFIG_DIR_NAME);for(let resourceType of RESOURCE_TYPES){let target=this.getTargetMap(accumulator,resourceType),globalEntries=globalSettings[resourceType]??[],projectEntries=projectSettings[resourceType]??[];this.resolveLocalEntries(projectEntries,resourceType,target,{source:"local",scope:"project",origin:"top-level"},projectBaseDir),this.resolveLocalEntries(globalEntries,resourceType,target,{source:"local",scope:"user",origin:"top-level"},globalBaseDir)}return this.addAutoDiscoveredResources(accumulator,globalSettings,projectSettings,globalBaseDir,projectBaseDir),this.toResolvedPaths(accumulator)}async resolveExtensionSources(sources,options){let accumulator=this.createAccumulator(),scope=options?.temporary?"temporary":options?.local?"project":"user",packageSources=sources.map(source=>({pkg:source,scope}));return await this.resolvePackageSources(packageSources,accumulator),this.toResolvedPaths(accumulator)}listConfiguredPackages(){let globalSettings=this.settingsManager.getGlobalSettings(),projectSettings=this.settingsManager.getProjectSettings(),configuredPackages=[];for(let pkg2 of globalSettings.packages??[]){let source=typeof pkg2=="string"?pkg2:pkg2.source;configuredPackages.push({source,scope:"user",filtered:typeof pkg2=="object",installedPath:this.getInstalledPath(source,"user")})}for(let pkg2 of projectSettings.packages??[]){let source=typeof pkg2=="string"?pkg2:pkg2.source;configuredPackages.push({source,scope:"project",filtered:typeof pkg2=="object",installedPath:this.getInstalledPath(source,"project")})}return configuredPackages}async install(source,options){let parsed=this.parseSource(source),scope=options?.local?"project":"user";this.assertProjectTrustedForScope(scope),await this.withProgress("install",source,`Installing ${source}...`,async()=>{if(parsed.type==="npm"){await this.installNpm(parsed,scope,!1);return}if(parsed.type==="git"){await this.installGit(parsed,scope);return}if(parsed.type==="local"){let resolved=this.resolvePath(parsed.path);if(!existsSync4(resolved))throw new Error(`Path does not exist: ${resolved}`);return}throw new Error(`Unsupported install source: ${source}`)})}async installAndPersist(source,options){await this.install(source,options),this.addSourceToSettings(source,options)}async remove(source,options){let parsed=this.parseSource(source),scope=options?.local?"project":"user";this.assertProjectTrustedForScope(scope),await this.withProgress("remove",source,`Removing ${source}...`,async()=>{if(parsed.type==="npm"){await this.uninstallNpm(parsed,scope);return}if(parsed.type==="git"){await this.removeGit(parsed,scope);return}if(parsed.type!=="local")throw new Error(`Unsupported remove source: ${source}`)})}async removeAndPersist(source,options){return await this.remove(source,options),this.removeSourceFromSettings(source,options)}async update(source){let globalSettings=this.settingsManager.getGlobalSettings(),projectSettings=this.settingsManager.getProjectSettings(),identity=source?this.getPackageIdentity(source):void 0,matched=!1,updateSources=[];for(let pkg2 of globalSettings.packages??[]){let sourceStr=typeof pkg2=="string"?pkg2:pkg2.source;identity&&this.getPackageIdentity(sourceStr,"user")!==identity||(matched=!0,updateSources.push({source:sourceStr,scope:"user"}))}for(let pkg2 of projectSettings.packages??[]){let sourceStr=typeof pkg2=="string"?pkg2:pkg2.source;identity&&this.getPackageIdentity(sourceStr,"project")!==identity||(matched=!0,updateSources.push({source:sourceStr,scope:"project"}))}if(source&&!matched)throw new Error(this.buildNoMatchingPackageMessage(source,[...globalSettings.packages??[],...projectSettings.packages??[]]));await this.updateConfiguredSources(updateSources)}async updateConfiguredSources(sources){if(isOfflineModeEnabled()||sources.length===0)return;let npmCandidates=[],gitCandidates=[];for(let entry of sources){let parsed=this.parseSource(entry.source);parsed.type==="npm"?parsed.pinned||npmCandidates.push({...entry,parsed}):parsed.type==="git"&&gitCandidates.push({...entry,parsed})}let npmCheckTasks=npmCandidates.map(entry=>async()=>({entry,shouldUpdate:await this.shouldUpdateNpmSource(entry.parsed,entry.scope)})),npmCheckResults=await this.runWithConcurrency(npmCheckTasks,UPDATE_CHECK_CONCURRENCY),userNpmUpdates=[],projectNpmUpdates=[];for(let result2 of npmCheckResults)result2.shouldUpdate&&(result2.entry.scope==="user"?userNpmUpdates.push(result2.entry):projectNpmUpdates.push(result2.entry));let tasks=[];if(userNpmUpdates.length>0&&tasks.push(this.updateNpmBatch(userNpmUpdates,"user")),projectNpmUpdates.length>0&&tasks.push(this.updateNpmBatch(projectNpmUpdates,"project")),gitCandidates.length>0){let gitTasks=gitCandidates.map(entry=>async()=>this.withProgress("update",entry.source,`Updating ${entry.source}...`,async()=>{await this.updateGit(entry.parsed,entry.scope)}));tasks.push(this.runWithConcurrency(gitTasks,GIT_UPDATE_CONCURRENCY).then(()=>{}))}await Promise.all(tasks)}async shouldUpdateNpmSource(source,scope){let installedPath=this.getManagedNpmInstallPath(source,scope),installedVersion=existsSync4(installedPath)?this.getInstalledNpmVersion(installedPath):void 0;if(!installedVersion)return!0;try{let targetVersion=await this.getLatestNpmVersion(source.version?source.spec:source.name,source.range);return(0,import_semver.gt)(targetVersion,installedVersion)}catch{return!0}}async updateNpmBatch(sources,scope){if(sources.length===0)return;let sourceLabel=sources.length===1?sources[0].source:`${scope} npm packages`,message=sources.length===1?`Updating ${sources[0].source}...`:`Updating ${scope} npm packages...`,specs=sources.map(entry=>entry.parsed.version?entry.parsed.spec:`${entry.parsed.name}@latest`);await this.withProgress("update",sourceLabel,message,async()=>{await this.installNpmBatch(specs,scope)})}async installNpmBatch(specs,scope){let installRoot=this.getNpmInstallRoot(scope,!1);this.ensureNpmProject(installRoot),await this.runNpmCommand(this.getNpmInstallArgs(specs,installRoot))}async checkForAvailableUpdates(){if(isOfflineModeEnabled())return[];let globalSettings=this.settingsManager.getGlobalSettings(),projectSettings=this.settingsManager.getProjectSettings(),allPackages=[];for(let pkg2 of projectSettings.packages??[])allPackages.push({pkg:pkg2,scope:"project"});for(let pkg2 of globalSettings.packages??[])allPackages.push({pkg:pkg2,scope:"user"});let checks=this.dedupePackages(allPackages).filter(entry=>entry.scope!=="temporary").map(entry=>async()=>{let source=typeof entry.pkg=="string"?entry.pkg:entry.pkg.source,parsed=this.parseSource(source);if(parsed.type==="local"||parsed.pinned)return;if(parsed.type==="npm"){let installedPath2=this.getNpmInstallPath(parsed,entry.scope);return!existsSync4(installedPath2)||!await this.npmHasAvailableUpdate(parsed,installedPath2)?void 0:{source,displayName:parsed.name,type:"npm",scope:entry.scope}}let installedPath=this.getGitInstallPath(parsed,entry.scope);if(!(!existsSync4(installedPath)||!await this.gitHasAvailableUpdate(installedPath)))return{source,displayName:`${parsed.host}/${parsed.path}`,type:"git",scope:entry.scope}});return(await this.runWithConcurrency(checks,UPDATE_CHECK_CONCURRENCY)).filter(result2=>result2!==void 0)}async resolvePackageSources(sources,accumulator,onMissing){for(let{pkg:pkg2,scope}of sources){let sourceStr=typeof pkg2=="string"?pkg2:pkg2.source,filter2=typeof pkg2=="object"?pkg2:void 0,deltaBase=this.findAutoloadDeltaBase(pkg2,scope,sources),resolvedSource=deltaBase?.source??sourceStr,resolvedScope=deltaBase?.scope??scope,parsed=this.parseSource(resolvedSource),metadata={source:sourceStr,scope,origin:"package"};if(parsed.type==="local"){let baseDir=this.getBaseDirForScope(resolvedScope);this.resolveLocalExtensionSource(parsed,accumulator,filter2,metadata,baseDir);continue}let installMissing=async()=>{if(isOfflineModeEnabled())return!1;if(!onMissing)return await this.installParsedSource(parsed,resolvedScope),!0;let action=await onMissing(resolvedSource);if(action==="skip")return!1;if(action==="error")throw new Error(`Missing source: ${resolvedSource}`);return await this.installParsedSource(parsed,resolvedScope),!0};if(parsed.type==="npm"){let installedPath=this.getNpmInstallPath(parsed,resolvedScope);if(!existsSync4(installedPath)||!await this.installedNpmMatchesConfiguredVersion(parsed,installedPath)){if(!await installMissing())continue;installedPath=this.getNpmInstallPath(parsed,resolvedScope)}metadata.baseDir=installedPath,this.collectPackageResources(installedPath,accumulator,filter2,metadata);continue}if(parsed.type==="git"){let installedPath=this.getGitInstallPath(parsed,resolvedScope);if(existsSync4(installedPath))resolvedScope==="temporary"&&!parsed.pinned&&!isOfflineModeEnabled()&&await this.refreshTemporaryGitSource(parsed,resolvedSource);else if(!await installMissing())continue;metadata.baseDir=installedPath,this.collectPackageResources(installedPath,accumulator,filter2,metadata)}}}findAutoloadDeltaBase(pkg2,scope,sources){if(scope!=="project"||typeof pkg2!="object"||pkg2.autoload!==!1)return;let identity=this.getPackageIdentity(pkg2.source,scope),userEntry=sources.find(entry=>entry.scope==="user"&&this.getPackageIdentity(this.getPackageSourceString(entry.pkg),"user")===identity);return userEntry?{source:this.getPackageSourceString(userEntry.pkg),scope:"user"}:void 0}resolveLocalExtensionSource(source,accumulator,filter2,metadata,baseDir){let resolved=this.resolvePathFromBase(source.path,baseDir);if(existsSync4(resolved))try{let stats=statSync4(resolved);if(stats.isFile()){metadata.baseDir=dirname8(resolved),this.addResource(accumulator.extensions,resolved,metadata,!0);return}stats.isDirectory()&&(metadata.baseDir=resolved,this.collectPackageResources(resolved,accumulator,filter2,metadata)||this.addResource(accumulator.extensions,resolved,metadata,!0))}catch{return}}async installParsedSource(parsed,scope){if(parsed.type==="npm"){await this.installNpm(parsed,scope,scope==="temporary");return}if(parsed.type==="git"){await this.installGit(parsed,scope);return}}getPackageSourceString(pkg2){return typeof pkg2=="string"?pkg2:pkg2.source}getSourceMatchKeyForInput(source){let parsed=this.parseSource(source);return parsed.type==="npm"?`npm:${parsed.name}`:parsed.type==="git"?`git:${parsed.host}/${parsed.path}`:`local:${this.resolvePath(parsed.path)}`}getSourceMatchKeyForSettings(source,scope){let parsed=this.parseSource(source);if(parsed.type==="npm")return`npm:${parsed.name}`;if(parsed.type==="git")return`git:${parsed.host}/${parsed.path}`;let baseDir=this.getBaseDirForScope(scope);return`local:${this.resolvePathFromBase(parsed.path,baseDir)}`}buildNoMatchingPackageMessage(source,configuredPackages){let suggestion=this.findSuggestedConfiguredSource(source,configuredPackages);return suggestion?`No matching package found for ${source}. Did you mean ${suggestion}?`:`No matching package found for ${source}`}findSuggestedConfiguredSource(source,configuredPackages){let trimmedSource=source.trim(),suggestions=new Set;for(let pkg2 of configuredPackages){let sourceStr=this.getPackageSourceString(pkg2),parsed=this.parseSource(sourceStr);if(parsed.type==="npm"){(trimmedSource===parsed.name||trimmedSource===parsed.spec)&&suggestions.add(sourceStr);continue}if(parsed.type==="git"){let shorthand=`${parsed.host}/${parsed.path}`,shorthandWithRef=parsed.ref?`${shorthand}@${parsed.ref}`:void 0;(trimmedSource===shorthand||shorthandWithRef&&trimmedSource===shorthandWithRef)&&suggestions.add(sourceStr)}}return suggestions.values().next().value}packageSourcesMatch(existing,inputSource,scope){let left=this.getSourceMatchKeyForSettings(this.getPackageSourceString(existing),scope),right=this.getSourceMatchKeyForInput(inputSource);return left===right}normalizePackageSourceForSettings(source,scope){let parsed=this.parseSource(source);if(parsed.type!=="local")return source;let baseDir=this.getBaseDirForScope(scope),resolved=this.resolvePath(parsed.path);return relative2(baseDir,resolved)||"."}parseSource(source){if(source.startsWith("npm:")){let spec=source.slice(4).trim(),{name,version:version2}=this.parseNpmSpec(spec);return{type:"npm",spec,name,version:version2,range:getNpmVersionRange(version2),pinned:isExactNpmVersion(version2)}}if(isLocalPath(source))return{type:"local",path:source};let gitParsed=parseGitUrl(source);return gitParsed||{type:"local",path:source}}async installedNpmMatchesConfiguredVersion(source,installedPath){let installedVersion=this.getInstalledNpmVersion(installedPath);return installedVersion?source.range?(0,import_semver.satisfies)(installedVersion,source.range):!0:!1}async npmHasAvailableUpdate(source,installedPath){if(isOfflineModeEnabled())return!1;let installedVersion=this.getInstalledNpmVersion(installedPath);if(!installedVersion)return!1;try{let targetVersion=await this.getLatestNpmVersion(source.version?source.spec:source.name,source.range);return(0,import_semver.gt)(targetVersion,installedVersion)}catch{return!1}}getInstalledNpmVersion(installedPath){let packageJsonPath=join13(installedPath,"package.json");if(existsSync4(packageJsonPath))try{let content=readFileSync4(packageJsonPath,"utf-8");return JSON.parse(stripBom(content)).version}catch{return}}async getLatestNpmVersion(packageSpec,range2){let npmCommand=this.getNpmCommand(),raw=(await this.runCommandCapture(npmCommand.command,[...npmCommand.args,"view",packageSpec,"version","--json"],{cwd:this.cwd,timeoutMs:NETWORK_TIMEOUT_MS})).trim();if(!raw)throw new Error("Empty response from npm view");let parsed=JSON.parse(raw);if(typeof parsed=="string")return parsed;if(Array.isArray(parsed)){let versions=parsed.filter(value2=>typeof value2=="string"&&value2.length>0),latest=range2?(0,import_semver.maxSatisfying)(versions,range2):[...versions].sort(import_semver.rcompare)[0];if(latest)return latest}throw new Error("Unexpected response from npm view")}async gitHasAvailableUpdate(installedPath){if(isOfflineModeEnabled())return!1;try{let localHead=await this.runCommandCapture("git",["rev-parse","HEAD"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS}),remoteHead=await this.getRemoteGitHead(installedPath);return localHead.trim()!==remoteHead.trim()}catch{return!1}}async getRemoteGitHead(installedPath){let upstreamRef=await this.getGitUpstreamRef(installedPath);if(upstreamRef){let match3=(await this.runGitRemoteCommand(installedPath,["ls-remote","origin",upstreamRef])).match(/^([0-9a-f]{40})\s+/m);if(match3?.[1])return match3[1]}let match2=(await this.runGitRemoteCommand(installedPath,["ls-remote","origin","HEAD"])).match(/^([0-9a-f]{40})\s+HEAD$/m);if(!match2?.[1])throw new Error("Failed to determine remote HEAD");return match2[1]}async getLocalGitUpdateTarget(installedPath){try{let trimmedUpstream=(await this.runCommandCapture("git",["rev-parse","--abbrev-ref","@{upstream}"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS})).trim();if(!trimmedUpstream.startsWith("origin/"))throw new Error(`Unsupported upstream remote: ${trimmedUpstream}`);let branch=trimmedUpstream.slice(7);if(!branch)throw new Error("Missing upstream branch name");return{ref:"@{upstream}",head:await this.runCommandCapture("git",["rev-parse","@{upstream}"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS}),fetchArgs:["fetch","--prune","--no-tags","origin",`+refs/heads/${branch}:refs/remotes/origin/${branch}`]}}catch{await this.runCommand("git",["remote","set-head","origin","-a"],{cwd:installedPath}).catch(()=>{});let head=await this.runCommandCapture("git",["rev-parse","origin/HEAD"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS}),branch=(await this.runCommandCapture("git",["symbolic-ref","refs/remotes/origin/HEAD"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS}).catch(()=>"")).trim().replace(/^refs\/remotes\/origin\//,"");return branch?{ref:"origin/HEAD",head,fetchArgs:["fetch","--prune","--no-tags","origin",`+refs/heads/${branch}:refs/remotes/origin/${branch}`]}:{ref:"origin/HEAD",head,fetchArgs:["fetch","--prune","--no-tags","origin","+HEAD:refs/remotes/origin/HEAD"]}}}async getGitUpstreamRef(installedPath){try{let trimmed=(await this.runCommandCapture("git",["rev-parse","--abbrev-ref","@{upstream}"],{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS})).trim();if(!trimmed.startsWith("origin/"))return;let branch=trimmed.slice(7);return branch?`refs/heads/${branch}`:void 0}catch{return}}runGitRemoteCommand(installedPath,args){return this.runCommandCapture("git",args,{cwd:installedPath,timeoutMs:NETWORK_TIMEOUT_MS,env:{GIT_TERMINAL_PROMPT:"0"}})}async runWithConcurrency(tasks,limit){if(tasks.length===0)return[];let results=new Array(tasks.length),nextIndex=0,workerCount=Math.max(1,Math.min(limit,tasks.length)),worker=async()=>{for(;;){let index3=nextIndex;if(nextIndex+=1,index3>=tasks.length)return;results[index3]=await tasks[index3]()}};return await Promise.all(Array.from({length:workerCount},()=>worker())),results}getPackageIdentity(source,scope){let parsed=this.parseSource(source);if(parsed.type==="npm")return`npm:${parsed.name}`;if(parsed.type==="git")return`git:${parsed.host}/${parsed.path}`;if(scope){let baseDir=this.getBaseDirForScope(scope);return`local:${this.resolvePathFromBase(parsed.path,baseDir)}`}return`local:${this.resolvePath(parsed.path)}`}dedupePackages(packages){let result2=[],seen=new Map;for(let entry of packages){let identity=this.getPackageIdentity(this.getPackageSourceString(entry.pkg),entry.scope),index3=seen.get(identity);if(index3===void 0){seen.set(identity,result2.length),result2.push(entry);continue}let existing=result2[index3];existing?.scope==="project"&&entry.scope==="user"?typeof existing.pkg=="object"&&existing.pkg.autoload===!1&&result2.push(entry):entry.scope==="project"&&(result2[index3]=entry)}return result2}parseNpmSpec(spec){let match2=spec.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);if(!match2)return{name:spec};let name=match2[1]??spec,version2=match2[2];return{name,version:version2}}assertProjectTrustedForScope(scope){if(scope==="project"&&!this.settingsManager.isProjectTrusted())throw new Error("Project is not trusted; refusing to access project package storage")}getNpmCommand(){let configuredCommand=this.settingsManager.getNpmCommand();if(!configuredCommand||configuredCommand.length===0)return{command:"npm",args:[]};let[command,...args]=configuredCommand;if(!command)throw new Error("Invalid npmCommand: first array entry must be a non-empty command");return{command,args}}getPackageManagerName(){let npmCommand=this.getNpmCommand(),commandParts=[npmCommand.command,...npmCommand.args],separatorIndex=commandParts.lastIndexOf("--"),packageManagerCommand=separatorIndex>=0?commandParts[separatorIndex+1]:npmCommand.command;return packageManagerCommand?basename3(packageManagerCommand).replace(/\.(cmd|exe)$/i,""):""}async runNpmCommand(args,options){let npmCommand=this.getNpmCommand();await this.runCommand(npmCommand.command,[...npmCommand.args,...args],options)}getGitDependencyInstallArgs(){let configuredCommand=this.settingsManager.getNpmCommand();return configuredCommand&&configuredCommand.length>0?["install"]:["install","--omit=dev"]}runNpmCommandSync(args){let npmCommand=this.getNpmCommand();return this.runCommandSync(npmCommand.command,[...npmCommand.args,...args])}getNpmInstallArgs(specs,installRoot){let packageManagerName=this.getPackageManagerName();return packageManagerName==="bun"?["install",...specs,"--cwd",installRoot,"--omit=peer"]:packageManagerName==="pnpm"?["install",...specs,"--prefix",installRoot,"--config.auto-install-peers=false","--config.strict-peer-dependencies=false","--config.strict-dep-builds=false"]:["install",...specs,"--prefix",installRoot,"--legacy-peer-deps"]}async installNpm(source,scope,temporary){let installRoot=this.getNpmInstallRoot(scope,temporary);this.ensureNpmProject(installRoot),await this.runNpmCommand(this.getNpmInstallArgs([source.spec],installRoot))}async uninstallNpm(source,scope){let installRoot=this.getNpmInstallRoot(scope,!1);if(!existsSync4(installRoot))return;let packageManagerName=this.getPackageManagerName();if(packageManagerName==="bun"){await this.runNpmCommand(["uninstall",source.name,"--cwd",installRoot]);return}let args=["uninstall",source.name,"--prefix",installRoot];packageManagerName!=="pnpm"&&args.push("--legacy-peer-deps"),await this.runNpmCommand(args)}async installGit(source,scope){let targetDir=this.getGitInstallPath(source,scope);if(existsSync4(targetDir)){if(source.ref){await this.ensureGitRef(targetDir,["fetch","origin",source.ref],"FETCH_HEAD");return}let target=await this.getLocalGitUpdateTarget(targetDir);await this.ensureGitRef(targetDir,target.fetchArgs,target.ref);return}let gitRoot=this.getGitInstallRoot(scope);gitRoot&&this.ensureGitIgnore(gitRoot),mkdirSync3(dirname8(targetDir),{recursive:!0}),rmSync(this.getGitUpdateMarkerPath(targetDir),{force:!0});try{await this.runCommand("git",["clone",source.repo,targetDir]),source.ref&&await this.runCommand("git",["checkout",source.ref],{cwd:targetDir});let packageJsonPath=join13(targetDir,"package.json");existsSync4(packageJsonPath)&&await this.runNpmCommand(this.getGitDependencyInstallArgs(),{cwd:targetDir})}catch(error){throw rmSync(targetDir,{recursive:!0,force:!0}),this.pruneEmptyGitParents(targetDir,gitRoot),error}}async updateGit(source,scope){let targetDir=this.getGitInstallPath(source,scope);if(!existsSync4(targetDir)){await this.installGit(source,scope);return}if(source.ref){await this.ensureGitRef(targetDir,["fetch","origin",source.ref],"FETCH_HEAD");return}let target=await this.getLocalGitUpdateTarget(targetDir);await this.ensureGitRef(targetDir,target.fetchArgs,target.ref)}hasMissingGitDependencies(targetDir){let packageJsonPath=join13(targetDir,"package.json");if(!existsSync4(packageJsonPath))return!1;try{let manifest=JSON.parse(stripBom(readFileSync4(packageJsonPath,"utf-8")));if(!manifest.dependencies||typeof manifest.dependencies!="object"||Array.isArray(manifest.dependencies))return!1;let nodeModulesDir=resolve2(targetDir,"node_modules");return Object.keys(manifest.dependencies).some(name=>{let dependencyPath=resolve2(nodeModulesDir,name);return dependencyPath.startsWith(`${nodeModulesDir}${sep4}`)?!existsSync4(dependencyPath):!1})}catch{return!1}}async repairMissingGitDependencies(targetDir){this.hasMissingGitDependencies(targetDir)&&await this.runNpmCommand(this.getGitDependencyInstallArgs(),{cwd:targetDir})}getGitUpdateMarkerPath(targetDir){return join13(dirname8(targetDir),`.${basename3(targetDir)}.pi-update-incomplete`)}async cleanAndInstallGitDependencies(targetDir,markerPath){try{await this.runCommand("git",["clean","-fdx"],{cwd:targetDir})}catch(error){throw await this.repairMissingGitDependencies(targetDir).catch(()=>{}),error}let packageJsonPath=join13(targetDir,"package.json");existsSync4(packageJsonPath)&&await this.runNpmCommand(this.getGitDependencyInstallArgs(),{cwd:targetDir}),rmSync(markerPath,{force:!0})}async ensureGitRef(targetDir,fetchArgs,ref){await this.runCommand("git",fetchArgs,{cwd:targetDir});let localHead=await this.runCommandCapture("git",["rev-parse","HEAD"],{cwd:targetDir,timeoutMs:NETWORK_TIMEOUT_MS}),commitRef=`${ref}^{commit}`,targetHead=await this.runCommandCapture("git",["rev-parse",commitRef],{cwd:targetDir,timeoutMs:NETWORK_TIMEOUT_MS}),markerPath=this.getGitUpdateMarkerPath(targetDir);if(localHead.trim()===targetHead.trim()){existsSync4(markerPath)?await this.cleanAndInstallGitDependencies(targetDir,markerPath):await this.repairMissingGitDependencies(targetDir);return}writeFileSync3(markerPath,"","utf-8"),await this.runCommand("git",["reset","--hard",commitRef],{cwd:targetDir}),await this.cleanAndInstallGitDependencies(targetDir,markerPath)}async refreshTemporaryGitSource(source,sourceStr){if(!isOfflineModeEnabled())try{await this.withProgress("pull",sourceStr,`Refreshing ${sourceStr}...`,async()=>{await this.updateGit(source,"temporary")})}catch{}}async removeGit(source,scope){let targetDir=this.getGitInstallPath(source,scope);rmSync(targetDir,{recursive:!0,force:!0}),rmSync(this.getGitUpdateMarkerPath(targetDir),{force:!0}),this.pruneEmptyGitParents(targetDir,this.getGitInstallRoot(scope))}pruneEmptyGitParents(targetDir,installRoot){if(!installRoot)return;let resolvedRoot=resolve2(installRoot),current=dirname8(targetDir);for(;current.startsWith(resolvedRoot)&¤t!==resolvedRoot;){if(!existsSync4(current)){current=dirname8(current);continue}if(readdirSync2(current).length>0)break;try{rmSync(current,{recursive:!0,force:!0})}catch{break}current=dirname8(current)}}ensureNpmProject(installRoot){existsSync4(installRoot)||mkdirSync3(installRoot,{recursive:!0}),markPathIgnoredByCloudSync(installRoot),this.ensureGitIgnore(installRoot);let packageJsonPath=join13(installRoot,"package.json");existsSync4(packageJsonPath)||writeFileSync3(packageJsonPath,JSON.stringify({name:"pi-extensions",private:!0},null,2),"utf-8")}ensureGitIgnore(dir){existsSync4(dir)||mkdirSync3(dir,{recursive:!0});let ignorePath=join13(dir,".gitignore");existsSync4(ignorePath)||writeFileSync3(ignorePath,`*
|
|
633
633
|
!.gitignore
|
|
634
634
|
`,"utf-8")}getNpmInstallRoot(scope,temporary){return temporary?this.getTemporaryDir("npm"):scope==="project"?(this.assertProjectTrustedForScope(scope),join13(this.cwd,CONFIG_DIR_NAME,"npm")):join13(this.agentDir,"npm")}getGlobalNpmRoot(){let npmCommand=this.getNpmCommand(),commandKey=[npmCommand.command,...npmCommand.args].join("\0");if(this.globalNpmRoot&&this.globalNpmRootCommandKey===commandKey)return this.globalNpmRoot;if(this.getPackageManagerName()==="bun"){let binDir=this.runNpmCommandSync(["pm","bin","-g"]).trim();this.globalNpmRoot=join13(dirname8(binDir),"install","global","node_modules")}else this.globalNpmRoot=this.runNpmCommandSync(["root","-g"]).trim();return this.globalNpmRootCommandKey=commandKey,this.globalNpmRoot}getPnpmGlobalPackagePath(packageName){if(this.getPackageManagerName()!=="pnpm")return;let output=this.runNpmCommandSync(["list","-g","--depth","0","--json"]),entries=JSON.parse(output);for(let entry of entries){let path14=entry.dependencies?.[packageName]?.path;if(path14)return path14}}getManagedNpmInstallPath(source,scope){return scope==="temporary"?join13(this.getTemporaryDir("npm"),"node_modules",source.name):scope==="project"?(this.assertProjectTrustedForScope(scope),join13(this.cwd,CONFIG_DIR_NAME,"npm","node_modules",source.name)):join13(this.agentDir,"npm","node_modules",source.name)}getLegacyGlobalNpmInstallPath(source){try{return this.getPnpmGlobalPackagePath(source.name)??join13(this.getGlobalNpmRoot(),source.name)}catch{return}}getNpmInstallPath(source,scope){let managedPath=this.getManagedNpmInstallPath(source,scope);if(scope!=="user"||existsSync4(managedPath))return managedPath;let legacyPath=this.getLegacyGlobalNpmInstallPath(source);return legacyPath&&existsSync4(legacyPath)?legacyPath:managedPath}getGitInstallPath(source,scope){if(scope==="temporary")return this.getTemporaryDir(`git-${source.host}`,source.path);let installRoot=this.getGitInstallRoot(scope);if(!installRoot)throw new Error("Missing git install root");return this.resolveManagedPath(installRoot,source.host,source.path)}getGitInstallRoot(scope){if(scope!=="temporary")return scope==="project"?(this.assertProjectTrustedForScope(scope),join13(this.cwd,CONFIG_DIR_NAME,"git")):join13(this.agentDir,"git")}getTemporaryDir(prefix,suffix){let root=this.resolveManagedPath(getExtensionTempFolder(this.agentDir),prefix),hash=createHash("sha256").update(`${prefix}-${suffix??""}`).digest("hex").slice(0,8);return this.resolveManagedPath(root,hash,suffix??"")}resolveManagedPath(root,...parts){let resolvedRoot=resolve2(root),resolvedPath=resolve2(resolvedRoot,...parts);if(resolvedPath!==resolvedRoot&&!resolvedPath.startsWith(`${resolvedRoot}${sep4}`))throw new Error(`Refusing to use path outside package install root: ${resolvedPath}`);return resolvedPath}getBaseDirForScope(scope){return scope==="project"?(this.assertProjectTrustedForScope(scope),join13(this.cwd,CONFIG_DIR_NAME)):scope==="user"?this.agentDir:this.cwd}resolvePath(input2){return resolvePath(input2,this.cwd,{homeDir:getHomeDir(),trim:!0})}resolvePathFromBase(input2,baseDir){return resolvePath(input2,baseDir,{homeDir:getHomeDir(),trim:!0})}collectPackageResources(packageRoot,accumulator,filter2,metadata){if(filter2){for(let resourceType of RESOURCE_TYPES){let patterns=filter2[resourceType],target=this.getTargetMap(accumulator,resourceType);filter2.autoload===!1?this.applyPackageDeltaFilter(packageRoot,patterns??[],resourceType,target,metadata):patterns!==void 0?this.applyPackageFilter(packageRoot,patterns,resourceType,target,metadata):this.collectDefaultResources(packageRoot,resourceType,target,metadata)}return!0}let manifest=readPiManifest(join13(packageRoot,"package.json"));if(manifest){for(let resourceType of RESOURCE_TYPES){let entries=manifest[resourceType];this.addManifestEntries(entries,packageRoot,resourceType,this.getTargetMap(accumulator,resourceType),metadata)}return!0}let hasAnyDir=!1;for(let resourceType of RESOURCE_TYPES){let dir=join13(packageRoot,resourceType);if(existsSync4(dir)){let files=collectResourceFiles(dir,resourceType);for(let f2 of files)this.addResource(this.getTargetMap(accumulator,resourceType),f2,metadata,!0);hasAnyDir=!0}}return hasAnyDir}collectDefaultResources(packageRoot,resourceType,target,metadata){let entries=readPiManifest(join13(packageRoot,"package.json"))?.[resourceType];if(entries){this.addManifestEntries(entries,packageRoot,resourceType,target,metadata);return}let dir=join13(packageRoot,resourceType);if(existsSync4(dir)){let files=collectResourceFiles(dir,resourceType);for(let f2 of files)this.addResource(target,f2,metadata,!0)}}applyPackageFilter(packageRoot,userPatterns,resourceType,target,metadata){let{allFiles}=this.collectManifestFiles(packageRoot,resourceType);if(userPatterns.length===0){for(let f2 of allFiles)this.addResource(target,f2,metadata,!1);return}let enabledByUser=applyPatterns(allFiles,userPatterns,packageRoot);for(let f2 of allFiles){let enabled=enabledByUser.has(f2);this.addResource(target,f2,metadata,enabled)}}applyPackageDeltaFilter(packageRoot,userPatterns,resourceType,target,metadata){if(userPatterns.length===0)return;let{allFiles}=this.collectManifestFiles(packageRoot,resourceType),enabledByUser=applyAutoloadDisabledPatterns(allFiles,userPatterns,packageRoot);for(let[filePath,enabled]of enabledByUser)this.addResource(target,filePath,metadata,enabled)}collectManifestFiles(packageRoot,resourceType){let entries=readPiManifest(join13(packageRoot,"package.json"))?.[resourceType];if(entries&&entries.length>0){let allFiles2=this.collectFilesFromManifestEntries(entries,packageRoot,resourceType),manifestPatterns=entries.filter(isOverridePattern),enabledByManifest=manifestPatterns.length>0?applyPatterns(allFiles2,manifestPatterns,packageRoot):new Set(allFiles2);return{allFiles:Array.from(enabledByManifest),enabledByManifest}}let conventionDir=join13(packageRoot,resourceType);if(!existsSync4(conventionDir))return{allFiles:[],enabledByManifest:new Set};let allFiles=collectResourceFiles(conventionDir,resourceType);return{allFiles,enabledByManifest:new Set(allFiles)}}addManifestEntries(entries,root,resourceType,target,metadata){if(!entries)return;let allFiles=this.collectFilesFromManifestEntries(entries,root,resourceType),patterns=entries.filter(isOverridePattern),enabledPaths=applyPatterns(allFiles,patterns,root);for(let f2 of allFiles)enabledPaths.has(f2)&&this.addResource(target,f2,metadata,!0)}collectFilesFromManifestEntries(entries,root,resourceType){let resolved=entries.filter(entry=>!isOverridePattern(entry)).flatMap(entry=>hasGlobPattern(entry)?expandPackageGlob(entry,root):[resolve2(root,entry)]);return this.collectFilesFromPaths(resolved,resourceType)}resolveLocalEntries(entries,resourceType,target,metadata,baseDir){if(entries.length===0)return;let{plain,patterns}=splitPatterns(entries),resolvedPlain=plain.map(p=>this.resolvePathFromBase(p,baseDir)),allFiles=this.collectFilesFromPaths(resolvedPlain,resourceType),enabledPaths=applyPatterns(allFiles,patterns,baseDir);for(let f2 of allFiles)this.addResource(target,f2,metadata,enabledPaths.has(f2))}addAutoDiscoveredResources(accumulator,globalSettings,projectSettings,globalBaseDir,projectBaseDir){let userMetadata={source:"auto",scope:"user",origin:"top-level",baseDir:globalBaseDir},projectMetadata={source:"auto",scope:"project",origin:"top-level",baseDir:projectBaseDir},userOverrides={extensions:globalSettings.extensions??[],skills:globalSettings.skills??[],prompts:globalSettings.prompts??[],themes:globalSettings.themes??[]},projectOverrides={extensions:projectSettings.extensions??[],skills:projectSettings.skills??[],prompts:projectSettings.prompts??[],themes:projectSettings.themes??[]},userDirs={extensions:join13(globalBaseDir,"extensions"),skills:join13(globalBaseDir,"skills"),prompts:join13(globalBaseDir,"prompts"),themes:join13(globalBaseDir,"themes")},projectDirs={extensions:join13(projectBaseDir,"extensions"),skills:join13(projectBaseDir,"skills"),prompts:join13(projectBaseDir,"prompts"),themes:join13(projectBaseDir,"themes")},userAgentsSkillsDir=join13(getHomeDir(),".agents","skills"),projectTrusted=this.settingsManager.isProjectTrusted(),projectAgentsSkillDirs=projectTrusted?collectAncestorAgentsSkillDirs(this.cwd).filter(dir=>resolve2(dir)!==resolve2(userAgentsSkillsDir)):[],addResources=(resourceType,paths,metadata,overrides,baseDir)=>{let target=this.getTargetMap(accumulator,resourceType);for(let path14 of paths){let enabled=isEnabledByOverrides(path14,overrides,baseDir);this.addResource(target,path14,metadata,enabled)}};projectTrusted&&(addResources("extensions",collectAutoExtensionEntries(projectDirs.extensions),projectMetadata,projectOverrides.extensions,projectBaseDir),addResources("skills",collectAutoSkillEntries(projectDirs.skills,"pi"),projectMetadata,projectOverrides.skills,projectBaseDir));for(let agentsSkillsDir of projectAgentsSkillDirs){let agentsBaseDir=dirname8(agentsSkillsDir),agentsMetadata={...projectMetadata,baseDir:agentsBaseDir};addResources("skills",collectAutoSkillEntries(agentsSkillsDir,"agents"),agentsMetadata,projectOverrides.skills,agentsBaseDir)}projectTrusted&&(addResources("prompts",collectAutoPromptEntries(projectDirs.prompts),projectMetadata,projectOverrides.prompts,projectBaseDir),addResources("themes",collectAutoThemeEntries(projectDirs.themes),projectMetadata,projectOverrides.themes,projectBaseDir)),addResources("extensions",collectAutoExtensionEntries(userDirs.extensions),userMetadata,userOverrides.extensions,globalBaseDir),addResources("skills",collectAutoSkillEntries(userDirs.skills,"pi"),userMetadata,userOverrides.skills,globalBaseDir);let userAgentsBaseDir=dirname8(userAgentsSkillsDir),userAgentsMetadata={...userMetadata,baseDir:userAgentsBaseDir};addResources("skills",collectAutoSkillEntries(userAgentsSkillsDir,"agents"),userAgentsMetadata,userOverrides.skills,userAgentsBaseDir),addResources("prompts",collectAutoPromptEntries(userDirs.prompts),userMetadata,userOverrides.prompts,globalBaseDir),addResources("themes",collectAutoThemeEntries(userDirs.themes),userMetadata,userOverrides.themes,globalBaseDir)}collectFilesFromPaths(paths,resourceType){let files=[];for(let p of paths)if(existsSync4(p))try{let stats=statSync4(p);stats.isFile()?files.push(p):stats.isDirectory()&&files.push(...collectResourceFiles(p,resourceType))}catch{}return files}getTargetMap(accumulator,resourceType){switch(resourceType){case"extensions":return accumulator.extensions;case"skills":return accumulator.skills;case"prompts":return accumulator.prompts;case"themes":return accumulator.themes;default:throw new Error(`Unknown resource type: ${resourceType}`)}}addResource(map,path14,metadata,enabled){path14&&(map.has(path14)||map.set(path14,{metadata,enabled}))}createAccumulator(){return{extensions:new Map,skills:new Map,prompts:new Map,themes:new Map}}toResolvedPaths(accumulator){let mapToResolved=entries=>{let resolved=Array.from(entries.entries()).map(([path14,{metadata,enabled}])=>({path:path14,enabled,metadata}));resolved.sort((a,b2)=>resourcePrecedenceRank(a.metadata)-resourcePrecedenceRank(b2.metadata));let seen=new Set;return resolved.filter(entry=>{let canonicalPath=canonicalizePath(entry.path);return seen.has(canonicalPath)?!1:(seen.add(canonicalPath),!0)})};return{extensions:mapToResolved(accumulator.extensions),skills:mapToResolved(accumulator.skills),prompts:mapToResolved(accumulator.prompts),themes:mapToResolved(accumulator.themes)}}spawnCommand(command,args,options){let env2=getEnv();return spawnProcess(command,args,{cwd:options?.cwd,stdio:isStdoutTakenOver()?["ignore",2,2]:"inherit",env:env2})}spawnCaptureCommand(command,args,options){let baseEnv=getEnv(),env2=options?.env?{...baseEnv,...options.env}:baseEnv;return spawnProcess(command,args,{cwd:options?.cwd,stdio:["ignore","pipe","pipe"],env:env2})}runCommandCapture(command,args,options){return new Promise((resolvePromise,reject)=>{let child=this.spawnCaptureCommand(command,args,options),stdout="",stderr="",timedOut=!1,timeout=typeof options?.timeoutMs=="number"?setTimeout(()=>{timedOut=!0,child.kill()},options.timeoutMs):void 0;child.stdout?.on("data",data=>{stdout+=data.toString()}),child.stderr?.on("data",data=>{stderr+=data.toString()}),child.once("error",error=>{timeout&&clearTimeout(timeout),reject(error)}),child.once("close",(code,signal)=>{if(timeout&&clearTimeout(timeout),timedOut){reject(new Error(`${command} ${args.join(" ")} timed out after ${options?.timeoutMs}ms`));return}if(code===0){resolvePromise(stdout.trim());return}let exitStatus=code===null?`signal ${signal??"unknown"}`:`code ${code}`;reject(new Error(`${command} ${args.join(" ")} failed with ${exitStatus}: ${stderr||stdout}`))})})}runCommand(command,args,options){return new Promise((resolvePromise,reject)=>{let child=this.spawnCommand(command,args,options);child.on("error",reject),child.on("exit",code=>{code===0?resolvePromise():reject(new Error(`${command} ${args.join(" ")} failed with code ${code}`))})})}runCommandSync(command,args){let env2=getEnv(),result2=spawnProcessSync(command,args,{stdio:["ignore","pipe","pipe"],encoding:"utf-8",env:env2});if(result2.error||result2.status!==0)throw new Error(`Failed to run ${command} ${args.join(" ")}: ${result2.error?.message||result2.stderr||result2.stdout}`);return(result2.stdout||result2.stderr||"").trim()}};var import_proper_lockfile2=__toESM(require_proper_lockfile(),1);import{randomUUID}from"crypto";import{existsSync as existsSync5,mkdirSync as mkdirSync4,readFileSync as readFileSync5,writeFileSync as writeFileSync4}from"fs";import{dirname as dirname9,join as join14}from"path";function clampTriggerPercent(value2){return Number.isFinite(value2)?Math.min(95,Math.max(20,value2)):85}function triggerPercentBudget(contextWindow,triggerPercent,keepRecentTokens){let triggerTokens=contextWindow*clampTriggerPercent(triggerPercent)/100;return{reserveTokens:Math.max(1,Math.round(contextWindow-triggerTokens)),keepRecentTokens:Math.min(keepRecentTokens,Math.max(1,Math.floor(triggerTokens/2)))}}var DEFAULT_COMPACTION_TOKEN_SETTINGS={reserveTokens:16384,keepRecentTokens:2e4},CACHE_WARMING_MODES=["off","streaming","idle"];function isMergeableObject(value2){return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)}function deepMergeObjects(base,overrides){let result2={...base};for(let key of Object.keys(overrides)){let overrideValue=overrides[key];if(overrideValue===void 0)continue;let baseValue=base[key];result2[key]=isMergeableObject(baseValue)&&isMergeableObject(overrideValue)?deepMergeObjects(baseValue,overrideValue):overrideValue}return result2}function deepMergeSettings(base,overrides){return deepMergeObjects(base,overrides)}function parseTimeoutSetting(value2,settingName){let timeoutMs=parseHttpIdleTimeoutMs(value2);if(timeoutMs!==void 0)return timeoutMs;if(value2!==void 0)throw new Error(`Invalid ${settingName} setting: ${String(value2)}`)}function toSettingsError(scope,error,path14){return{scope,...path14?{path:path14}:{},error:error instanceof Error?error:new Error(String(error))}}var FileSettingsStorage=class{constructor(cwd,agentDir){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir);this.globalSettingsPath=join14(resolvedAgentDir,"settings.json"),this.projectSettingsPath=join14(resolvedCwd,CONFIG_DIR_NAME,"settings.json")}acquireLockSyncWithRetry(path14){let lastError;for(let attempt2=1;attempt2<=10;attempt2++)try{return import_proper_lockfile2.default.lockSync(path14,{realpath:!1})}catch(error){if((typeof error=="object"&&error!==null&&"code"in error?String(error.code):void 0)!=="ELOCKED"||attempt2===10)throw error;lastError=error;let start=Date.now();for(;Date.now()-start<20;);}throw lastError??new Error("Failed to acquire settings lock")}withLock(scope,fn){let path14=scope==="global"?this.globalSettingsPath:this.projectSettingsPath,dir=dirname9(path14),release2;try{let fileExists2=existsSync5(path14);fileExists2&&(release2=this.acquireLockSyncWithRetry(path14));let current=fileExists2?readFileSync5(path14,"utf-8"):void 0,next=fn(current);next!==void 0&&(existsSync5(dir)||mkdirSync4(dir,{recursive:!0}),release2||(release2=this.acquireLockSyncWithRetry(path14)),writeFileSync4(path14,next,"utf-8"))}finally{release2&&release2()}}},InMemorySettingsStorage=class{withLock(scope,fn){let current=scope==="global"?this.global:this.project,next=fn(current);next!==void 0&&(scope==="global"?this.global=next:this.project=next)}},SettingsManager=class _SettingsManager{constructor(storage,initialGlobal,initialProject,globalLoadError=null,projectLoadError=null,initialErrors=[],projectTrusted=!0,settingsPaths={}){this.modifiedFields=new Set,this.modifiedNestedFields=new Map,this.modifiedProjectFields=new Set,this.modifiedProjectNestedFields=new Map,this.globalSettingsLoadError=null,this.projectSettingsLoadError=null,this.writeQueue=Promise.resolve(),this.storage=storage,this.globalSettings=initialGlobal,this.projectSettings=initialProject,this.projectTrusted=projectTrusted,this.globalSettingsLoadError=globalLoadError,this.projectSettingsLoadError=projectLoadError,this.errors=[...initialErrors],this.settingsPaths=settingsPaths,this.settings=deepMergeSettings(this.globalSettings,this.projectSettings)}static create(cwd,agentDir=getAgentDir(),options={}){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),storage=new FileSettingsStorage(resolvedCwd,resolvedAgentDir);return _SettingsManager.fromStorageWithPaths(storage,options,{global:join14(resolvedAgentDir,"settings.json"),project:join14(resolvedCwd,CONFIG_DIR_NAME,"settings.json")})}static fromStorage(storage,options={}){return _SettingsManager.fromStorageWithPaths(storage,options)}static fromStorageWithPaths(storage,options,settingsPaths={}){let projectTrusted=options.projectTrusted??!0,globalLoad=_SettingsManager.tryLoadFromStorage(storage,"global"),projectLoad=_SettingsManager.tryLoadFromStorage(storage,"project",projectTrusted),initialErrors=[];return globalLoad.error&&initialErrors.push(toSettingsError("global",globalLoad.error,settingsPaths.global)),projectLoad.error&&initialErrors.push(toSettingsError("project",projectLoad.error,settingsPaths.project)),new _SettingsManager(storage,globalLoad.settings,projectLoad.settings,globalLoad.error,projectLoad.error,initialErrors,projectTrusted,settingsPaths)}static inMemory(settings2={},options={}){let storage=new InMemorySettingsStorage,initialSettings=_SettingsManager.migrateSettings(structuredClone(settings2));return storage.withLock("global",()=>JSON.stringify(initialSettings,null,2)),_SettingsManager.fromStorage(storage,options)}static loadFromStorage(storage,scope,projectTrusted=!0){if(scope==="project"&&!projectTrusted)return{};let content;if(storage.withLock(scope,current=>{content=current}),!content)return{};let settings2=JSON.parse(stripBom(content));return _SettingsManager.migrateSettings(settings2)}static tryLoadFromStorage(storage,scope,projectTrusted=!0){try{return{settings:_SettingsManager.loadFromStorage(storage,scope,projectTrusted),error:null}}catch(error){return{settings:{},error}}}static migrateSettings(settings2){if("queueMode"in settings2&&!("steeringMode"in settings2)&&(settings2.steeringMode=settings2.queueMode,delete settings2.queueMode),!("transport"in settings2)&&typeof settings2.websockets=="boolean"&&(settings2.transport=settings2.websockets?"websocket":"sse",delete settings2.websockets),"skills"in settings2&&typeof settings2.skills=="object"&&settings2.skills!==null&&!Array.isArray(settings2.skills)){let skillsSettings=settings2.skills;skillsSettings.enableSkillCommands!==void 0&&settings2.enableSkillCommands===void 0&&(settings2.enableSkillCommands=skillsSettings.enableSkillCommands),Array.isArray(skillsSettings.customDirectories)&&skillsSettings.customDirectories.length>0?settings2.skills=skillsSettings.customDirectories:delete settings2.skills}if("retry"in settings2&&typeof settings2.retry=="object"&&settings2.retry!==null&&!Array.isArray(settings2.retry)){let retrySettings=settings2.retry,providerSettings=typeof retrySettings.provider=="object"&&retrySettings.provider!==null?retrySettings.provider:void 0;typeof retrySettings.maxDelayMs=="number"&&(providerSettings?.maxRetryDelayMs===void 0||providerSettings?.maxRetryDelayMs===null)&&(retrySettings.provider={...providerSettings??{},maxRetryDelayMs:retrySettings.maxDelayMs}),delete retrySettings.maxDelayMs}return settings2}getGlobalSettings(){return structuredClone(this.globalSettings)}getProjectSettings(){return structuredClone(this.projectSettings)}isProjectTrusted(){return this.projectTrusted}setProjectTrusted(trusted){if(this.projectTrusted===trusted)return;if(this.projectTrusted=trusted,this.modifiedProjectFields.clear(),this.modifiedProjectNestedFields.clear(),!trusted){this.projectSettings={},this.projectSettingsLoadError=null,this.settings=deepMergeSettings(this.globalSettings,this.projectSettings);return}let projectLoad=_SettingsManager.tryLoadFromStorage(this.storage,"project",trusted);this.projectSettings=projectLoad.settings,this.projectSettingsLoadError=projectLoad.error,projectLoad.error&&this.recordError("project",projectLoad.error),this.settings=deepMergeSettings(this.globalSettings,this.projectSettings)}async reload(){await this.writeQueue;let globalLoad=_SettingsManager.tryLoadFromStorage(this.storage,"global");globalLoad.error?(this.globalSettingsLoadError=globalLoad.error,this.recordError("global",globalLoad.error)):(this.globalSettings=globalLoad.settings,this.globalSettingsLoadError=null),this.modifiedFields.clear(),this.modifiedNestedFields.clear(),this.modifiedProjectFields.clear(),this.modifiedProjectNestedFields.clear();let projectLoad=_SettingsManager.tryLoadFromStorage(this.storage,"project",this.projectTrusted);projectLoad.error?(this.projectSettingsLoadError=projectLoad.error,this.recordError("project",projectLoad.error)):(this.projectSettings=projectLoad.settings,this.projectSettingsLoadError=null),this.settings=deepMergeSettings(this.globalSettings,this.projectSettings)}applyOverrides(overrides){this.settings=deepMergeSettings(this.settings,overrides)}markModified(field3,nestedKey){this.modifiedFields.add(field3),nestedKey&&(this.modifiedNestedFields.has(field3)||this.modifiedNestedFields.set(field3,new Set),this.modifiedNestedFields.get(field3).add(nestedKey))}markProjectModified(field3,nestedKey){this.modifiedProjectFields.add(field3),nestedKey&&(this.modifiedProjectNestedFields.has(field3)||this.modifiedProjectNestedFields.set(field3,new Set),this.modifiedProjectNestedFields.get(field3).add(nestedKey))}assertProjectTrustedForWrite(){if(!this.projectTrusted)throw new Error("Project is not trusted; refusing to write project settings")}recordError(scope,error){this.errors.push(toSettingsError(scope,error,this.settingsPaths[scope]))}clearModifiedScope(scope){if(scope==="global"){this.modifiedFields.clear(),this.modifiedNestedFields.clear();return}this.modifiedProjectFields.clear(),this.modifiedProjectNestedFields.clear()}enqueueWrite(scope,task){this.writeQueue=this.writeQueue.then(()=>{scope==="project"&&this.assertProjectTrustedForWrite(),task(),this.clearModifiedScope(scope)}).catch(error=>{this.recordError(scope,error)})}cloneModifiedNestedFields(source){let snapshot=new Map;for(let[key,value2]of source.entries())snapshot.set(key,new Set(value2));return snapshot}persistScopedSettings(scope,snapshotSettings,modifiedFields,modifiedNestedFields){this.storage.withLock(scope,current=>{let currentFileSettings=current?_SettingsManager.migrateSettings(JSON.parse(stripBom(current))):{},mergedSettings={...currentFileSettings};for(let field3 of modifiedFields){let value2=snapshotSettings[field3];if(modifiedNestedFields.has(field3)&&typeof value2=="object"&&value2!==null){let nestedModified=modifiedNestedFields.get(field3),baseNested=currentFileSettings[field3]??{},inMemoryNested=value2,mergedNested={...baseNested};for(let nestedKey of nestedModified)mergedNested[nestedKey]=inMemoryNested[nestedKey];mergedSettings[field3]=mergedNested}else mergedSettings[field3]=value2}return JSON.stringify(mergedSettings,null,2)})}save(){if(this.settings=deepMergeSettings(this.globalSettings,this.projectSettings),this.globalSettingsLoadError)return;let snapshotGlobalSettings=structuredClone(this.globalSettings),modifiedFields=new Set(this.modifiedFields),modifiedNestedFields=this.cloneModifiedNestedFields(this.modifiedNestedFields);this.enqueueWrite("global",()=>{this.persistScopedSettings("global",snapshotGlobalSettings,modifiedFields,modifiedNestedFields)})}saveProjectSettings(settings2){if(this.assertProjectTrustedForWrite(),this.projectSettings=structuredClone(settings2),this.settings=deepMergeSettings(this.globalSettings,this.projectSettings),this.projectSettingsLoadError)return;let snapshotProjectSettings=structuredClone(this.projectSettings),modifiedFields=new Set(this.modifiedProjectFields),modifiedNestedFields=this.cloneModifiedNestedFields(this.modifiedProjectNestedFields);this.enqueueWrite("project",()=>{this.persistScopedSettings("project",snapshotProjectSettings,modifiedFields,modifiedNestedFields)})}updateProjectSettings(field3,update){this.assertProjectTrustedForWrite();let projectSettings=structuredClone(this.projectSettings);update(projectSettings),this.markProjectModified(field3),this.saveProjectSettings(projectSettings)}async flush(){await this.writeQueue}drainErrors(){let drained=[...this.errors];return this.errors=[],drained}getLastChangelogVersion(){return this.settings.lastChangelogVersion}setLastChangelogVersion(version2){this.globalSettings.lastChangelogVersion=version2,this.markModified("lastChangelogVersion"),this.save()}getSessionDir(){let sessionDir=this.settings.sessionDir;return sessionDir&&normalizePath(sessionDir)}getDefaultProvider(){return this.settings.defaultProvider}getDefaultModel(){return this.settings.defaultModel}setDefaultProvider(provider){this.globalSettings.defaultProvider=provider,this.markModified("defaultProvider"),this.save()}setDefaultModel(modelId2){this.globalSettings.defaultModel=modelId2,this.markModified("defaultModel"),this.save()}setDefaultModelAndProvider(provider,modelId2){this.globalSettings.defaultProvider=provider,this.globalSettings.defaultModel=modelId2,this.markModified("defaultProvider"),this.markModified("defaultModel"),this.save()}getSteeringMode(){return this.settings.steeringMode||"one-at-a-time"}setSteeringMode(mode){this.globalSettings.steeringMode=mode,this.markModified("steeringMode"),this.save()}getFollowUpMode(){return this.settings.followUpMode||"one-at-a-time"}setFollowUpMode(mode){this.globalSettings.followUpMode=mode,this.markModified("followUpMode"),this.save()}getThemeSetting(){let value2=this.settings.theme;if(typeof value2=="string")return value2}getTheme(){let theme2=this.getThemeSetting();return theme2?.includes("/")?void 0:theme2}setTheme(theme2){this.globalSettings.theme=theme2,this.markModified("theme"),this.save()}getDefaultThinkingLevel(){return this.settings.defaultThinkingLevel}setDefaultThinkingLevel(level){this.globalSettings.defaultThinkingLevel=level,this.markModified("defaultThinkingLevel"),this.save()}getModelThinkingLevel(provider,modelId2){return this.settings.modelThinkingLevels?.[`${provider}/${modelId2}`]}getAllModelThinkingLevels(){return{...this.settings.modelThinkingLevels??{}}}setModelThinkingLevel(provider,modelId2,level){this.globalSettings.modelThinkingLevels||(this.globalSettings.modelThinkingLevels={}),this.globalSettings.modelThinkingLevels[`${provider}/${modelId2}`]=level,this.markModified("modelThinkingLevels"),this.save()}removeModelThinkingLevel(provider,modelId2){this.globalSettings.modelThinkingLevels&&(delete this.globalSettings.modelThinkingLevels[`${provider}/${modelId2}`],Object.keys(this.globalSettings.modelThinkingLevels).length===0&&delete this.globalSettings.modelThinkingLevels,this.markModified("modelThinkingLevels"),this.save())}getTransport(){return this.settings.transport??"auto"}setTransport(transport){this.globalSettings.transport=transport,this.markModified("transport"),this.save()}getCompactionEnabled(){return this.settings.compaction?.enabled??!0}setCompactionEnabled(enabled){this.globalSettings.compaction||(this.globalSettings.compaction={}),this.globalSettings.compaction.enabled=enabled,this.markModified("compaction","enabled"),this.save()}getConfiguredCompactionTokenSetting(field3,model){let compaction=this.settings.compaction,ordinary=compaction?.[field3];if(ordinary!==void 0&&(typeof ordinary!="number"||!Number.isSafeInteger(ordinary)||ordinary<0))throw new Error(`Invalid compaction.${field3} setting: ${String(ordinary)}. Expected a non-negative safe integer.`);let modelKey=model?`${model.provider}/${model.id}`:void 0,entry=modelKey!==void 0?compaction?.modelOverrides?.[modelKey]:void 0;if(entry!==void 0&&!isMergeableObject(entry))throw new Error(`Invalid compaction.modelOverrides["${modelKey}"] setting: ${String(entry)}. Expected an object.`);let override=entry?.[field3];if(override!==void 0&&(typeof override!="number"||!Number.isSafeInteger(override)||override<0))throw new Error(`Invalid compaction.modelOverrides["${modelKey}"].${field3} setting: ${String(override)}. Expected a non-negative safe integer.`);return override??ordinary}getCompactionTokenSetting(field3,model){return this.getConfiguredCompactionTokenSetting(field3,model)??DEFAULT_COMPACTION_TOKEN_SETTINGS[field3]}getCompactionReserveTokens(model){return this.getCompactionTokenSetting("reserveTokens",model)}getCompactionKeepRecentTokens(model){return this.getCompactionTokenSetting("keepRecentTokens",model)}getCompactionTriggerPercent(){return clampTriggerPercent(this.settings.compaction?.triggerPercent??85)}getCompactionSettings(model){let enabled=this.getCompactionEnabled(),keepRecentTokens=this.getCompactionKeepRecentTokens(model),configuredReserve=this.getConfiguredCompactionTokenSetting("reserveTokens",model);return configuredReserve!==void 0||model?.contextWindow===void 0?{enabled,reserveTokens:configuredReserve??DEFAULT_COMPACTION_TOKEN_SETTINGS.reserveTokens,keepRecentTokens}:{enabled,...triggerPercentBudget(model.contextWindow,this.getCompactionTriggerPercent(),keepRecentTokens)}}getBranchSummarySettings(){return{reserveTokens:this.settings.branchSummary?.reserveTokens??16384,skipPrompt:this.settings.branchSummary?.skipPrompt??!1}}getBranchSummarySkipPrompt(){return this.settings.branchSummary?.skipPrompt??!1}getRetryEnabled(){return this.settings.retry?.enabled??!0}setRetryEnabled(enabled){this.globalSettings.retry||(this.globalSettings.retry={}),this.globalSettings.retry.enabled=enabled,this.markModified("retry","enabled"),this.save()}getRetrySettings(){return{enabled:this.getRetryEnabled(),maxRetries:this.settings.retry?.maxRetries??3,baseDelayMs:this.settings.retry?.baseDelayMs??2e3,maxAgentDelayMs:this.settings.retry?.maxAgentDelayMs??DEFAULT_MAX_AGENT_RETRY_DELAY_MS}}getHttpIdleTimeoutMs(){return parseTimeoutSetting(this.settings.httpIdleTimeoutMs,"httpIdleTimeoutMs")??DEFAULT_HTTP_IDLE_TIMEOUT_MS}setHttpIdleTimeoutMs(timeoutMs){if(!Number.isFinite(timeoutMs)||timeoutMs<0)throw new Error(`Invalid httpIdleTimeoutMs setting: ${String(timeoutMs)}`);this.globalSettings.httpIdleTimeoutMs=Math.floor(timeoutMs),this.markModified("httpIdleTimeoutMs"),this.save()}getCacheWarmingMode(){let mode=this.globalSettings.cacheWarming;return mode!==void 0&&CACHE_WARMING_MODES.includes(mode)?mode:"streaming"}setCacheWarmingMode(mode){this.globalSettings.cacheWarming=mode,this.markModified("cacheWarming"),this.save()}getProviderRetrySettings(){return{timeoutMs:this.settings.retry?.provider?.timeoutMs,maxRetries:this.settings.retry?.provider?.maxRetries,maxRetryDelayMs:this.settings.retry?.provider?.maxRetryDelayMs??6e4}}getWebSocketConnectTimeoutMs(){return parseTimeoutSetting(this.settings.websocketConnectTimeoutMs,"websocketConnectTimeoutMs")}getHideThinkingBlock(){return this.settings.hideThinkingBlock??!1}getShowCacheMissNotices(){return this.settings.showCacheMissNotices??!1}getExternalEditorCommand(){let configuredEditor=this.settings.externalEditor;if(typeof configuredEditor=="string"&&configuredEditor.trim()!=="")return configuredEditor;let environmentEditor=process.env.VISUAL||process.env.EDITOR;return environmentEditor||(process.platform==="win32"?"notepad":"nano")}setHideThinkingBlock(hide){this.globalSettings.hideThinkingBlock=hide,this.markModified("hideThinkingBlock"),this.save()}setShowCacheMissNotices(show){this.globalSettings.showCacheMissNotices=show,this.markModified("showCacheMissNotices"),this.save()}getShellPath(){let shellPath=this.settings.shellPath;return shellPath&&normalizePath(shellPath)}setShellPath(path14){this.globalSettings.shellPath=path14,this.markModified("shellPath"),this.save()}getQuietStartup(){return this.settings.quietStartup??!1}setQuietStartup(quiet){this.globalSettings.quietStartup=quiet,this.markModified("quietStartup"),this.save()}getDefaultProjectTrust(){let value2=this.globalSettings.defaultProjectTrust;return value2==="always"||value2==="never"?value2:"ask"}setDefaultProjectTrust(defaultProjectTrust){this.globalSettings.defaultProjectTrust=defaultProjectTrust,this.markModified("defaultProjectTrust"),this.save()}getShellCommandPrefix(){return this.settings.shellCommandPrefix}setShellCommandPrefix(prefix){this.globalSettings.shellCommandPrefix=prefix,this.markModified("shellCommandPrefix"),this.save()}getNpmCommand(){return this.settings.npmCommand?[...this.settings.npmCommand]:void 0}setNpmCommand(command){this.globalSettings.npmCommand=command?[...command]:void 0,this.markModified("npmCommand"),this.save()}getCollapseChangelog(){return this.settings.collapseChangelog??!1}setCollapseChangelog(collapse){this.globalSettings.collapseChangelog=collapse,this.markModified("collapseChangelog"),this.save()}getEnableInstallTelemetry(){return this.settings.enableInstallTelemetry??!0}setEnableInstallTelemetry(enabled){this.globalSettings.enableInstallTelemetry=enabled,this.markModified("enableInstallTelemetry"),this.save()}getEnableAnalytics(){return this.settings.enableAnalytics??!1}getTrackingId(){return this.settings.trackingId}setEnableAnalytics(enabled){this.globalSettings.enableAnalytics=enabled,this.markModified("enableAnalytics"),enabled&&!this.globalSettings.trackingId&&(this.globalSettings.trackingId=randomUUID(),this.markModified("trackingId")),this.save()}getPackages(){return[...this.settings.packages??[]]}setPackages(packages){this.globalSettings.packages=packages,this.markModified("packages"),this.save()}setProjectPackages(packages){this.updateProjectSettings("packages",settings2=>{settings2.packages=packages})}getExtensionPaths(){return[...this.settings.extensions??[]]}setExtensionPaths(paths){this.globalSettings.extensions=paths,this.markModified("extensions"),this.save()}setProjectExtensionPaths(paths){this.updateProjectSettings("extensions",settings2=>{settings2.extensions=paths})}getSkillPaths(){return[...this.settings.skills??[]]}setSkillPaths(paths){this.globalSettings.skills=paths,this.markModified("skills"),this.save()}setProjectSkillPaths(paths){this.updateProjectSettings("skills",settings2=>{settings2.skills=paths})}getPromptTemplatePaths(){return[...this.settings.prompts??[]]}setPromptTemplatePaths(paths){this.globalSettings.prompts=paths,this.markModified("prompts"),this.save()}setProjectPromptTemplatePaths(paths){this.updateProjectSettings("prompts",settings2=>{settings2.prompts=paths})}getThemePaths(){return[...this.settings.themes??[]]}setThemePaths(paths){this.globalSettings.themes=paths,this.markModified("themes"),this.save()}setProjectThemePaths(paths){this.updateProjectSettings("themes",settings2=>{settings2.themes=paths})}getEnableSkillCommands(){return this.settings.enableSkillCommands??!0}setEnableSkillCommands(enabled){this.globalSettings.enableSkillCommands=enabled,this.markModified("enableSkillCommands"),this.save()}getThinkingBudgets(){return this.settings.thinkingBudgets}getTerminalCapabilityOverrides(){let terminal=this.settings.terminal,images=terminal?.images;return{...images==="kitty"||images==="iterm2"?{images}:images===!1?{images:null}:{},...typeof terminal?.trueColor=="boolean"?{trueColor:terminal.trueColor}:{},...typeof terminal?.hyperlinks=="boolean"?{hyperlinks:terminal.hyperlinks}:{}}}getShowImages(){return this.settings.terminal?.showImages??!0}setShowImages(show){this.globalSettings.terminal||(this.globalSettings.terminal={}),this.globalSettings.terminal.showImages=show,this.markModified("terminal","showImages"),this.save()}getImageWidthCells(){let width=this.settings.terminal?.imageWidthCells;return typeof width!="number"||!Number.isFinite(width)?60:Math.max(1,Math.floor(width))}setImageWidthCells(width){this.globalSettings.terminal||(this.globalSettings.terminal={}),this.globalSettings.terminal.imageWidthCells=Math.max(1,Math.floor(width)),this.markModified("terminal","imageWidthCells"),this.save()}getClearOnShrink(){return this.settings.terminal?.clearOnShrink!==void 0?this.settings.terminal.clearOnShrink:process.env.PI_CLEAR_ON_SHRINK==="1"}setClearOnShrink(enabled){this.globalSettings.terminal||(this.globalSettings.terminal={}),this.globalSettings.terminal.clearOnShrink=enabled,this.markModified("terminal","clearOnShrink"),this.save()}getShowTerminalProgress(){return this.settings.terminal?.showTerminalProgress??!1}setShowTerminalProgress(enabled){this.globalSettings.terminal||(this.globalSettings.terminal={}),this.globalSettings.terminal.showTerminalProgress=enabled,this.markModified("terminal","showTerminalProgress"),this.save()}getTuiMode(){return this.settings.tuiMode==="regular"?"regular":"fullscreen"}setTuiMode(mode){this.globalSettings.tuiMode=mode,this.markModified("tuiMode"),this.save()}getFullscreenExitOutput(){return this.settings.fullscreenExitOutput==="resume-hint"?"resume-hint":"transcript"}setFullscreenExitOutput(output){this.globalSettings.fullscreenExitOutput=output,this.markModified("fullscreenExitOutput"),this.save()}getFullscreenScrollbar(){let mode=this.settings.fullscreenScrollbar;return mode==="always"||mode==="hidden"?mode:"auto"}setFullscreenScrollbar(mode){this.globalSettings.fullscreenScrollbar=mode,this.markModified("fullscreenScrollbar"),this.save()}getFullscreenCopyOnSelect(){return this.settings.fullscreenCopyOnSelect??!0}setFullscreenCopyOnSelect(enabled){this.globalSettings.fullscreenCopyOnSelect=enabled,this.markModified("fullscreenCopyOnSelect"),this.save()}getImageAutoResize(){return this.settings.images?.autoResize??!0}setImageAutoResize(enabled){this.globalSettings.images||(this.globalSettings.images={}),this.globalSettings.images.autoResize=enabled,this.markModified("images","autoResize"),this.save()}getBlockImages(){return this.settings.images?.blockImages??!1}setBlockImages(blocked){this.globalSettings.images||(this.globalSettings.images={}),this.globalSettings.images.blockImages=blocked,this.markModified("images","blockImages"),this.save()}getEnabledModels(){return this.settings.enabledModels}getDefaultTools(){let tools=this.settings.defaultTools;return tools?[...tools]:void 0}setEnabledModels(patterns){this.globalSettings.enabledModels=patterns,this.markModified("enabledModels"),this.save()}getDoubleEscapeAction(){return this.settings.doubleEscapeAction??"tree"}setDoubleEscapeAction(action){this.globalSettings.doubleEscapeAction=action,this.markModified("doubleEscapeAction"),this.save()}getTreeFilterMode(){let mode=this.settings.treeFilterMode;return mode&&["default","no-tools","user-only","labeled-only","all"].includes(mode)?mode:"default"}setTreeFilterMode(mode){this.globalSettings.treeFilterMode=mode,this.markModified("treeFilterMode"),this.save()}getShowHardwareCursor(){return this.settings.showHardwareCursor??process.env.PI_HARDWARE_CURSOR==="1"}setShowHardwareCursor(enabled){this.globalSettings.showHardwareCursor=enabled,this.markModified("showHardwareCursor"),this.save()}getEditorPaddingX(){return this.settings.editorPaddingX??0}setEditorPaddingX(padding){this.globalSettings.editorPaddingX=Math.max(0,Math.min(3,Math.floor(padding))),this.markModified("editorPaddingX"),this.save()}getOutputPad(){return this.settings.outputPad===0?0:1}setOutputPad(padding){this.globalSettings.outputPad=padding,this.markModified("outputPad"),this.save()}getAutocompleteMaxVisible(){return this.settings.autocompleteMaxVisible??5}setAutocompleteMaxVisible(maxVisible){this.globalSettings.autocompleteMaxVisible=Math.max(3,Math.min(20,Math.floor(maxVisible))),this.markModified("autocompleteMaxVisible"),this.save()}getCodeBlockIndent(){return this.settings.markdown?.codeBlockIndent??" "}getMermaidRenderingMode(){let mode=this.settings.markdown?.mermaid;return mode==="off"||mode==="final"?mode:"streaming"}setMermaidRenderingMode(mode){this.globalSettings.markdown??={},this.globalSettings.markdown.mermaid=mode,this.markModified("markdown","mermaid"),this.save()}getWarnings(){return{...this.settings.warnings??{}}}setWarnings(warnings){this.globalSettings.warnings={...warnings},this.markModified("warnings"),this.save()}};import*as fs4 from"node:fs";import*as path6 from"node:path";import{watch}from"node:fs";var FS_WATCH_RETRY_DELAY_MS=5e3;function closeWatcher(watcher){if(watcher)try{watcher.close()}catch{}}function watchWithErrorHandler(path14,listener,onError){try{let watcher=watch(path14,listener);return watcher.on("error",onError),watcher}catch{return onError(),null}}var import_lib=__toESM(require_lib2(),1);function decodeCodePoint(codePoint){if(!(!Number.isInteger(codePoint)||codePoint<0||codePoint>1114111))return String.fromCodePoint(codePoint)}function decodeHtmlEntity(entity){switch(entity){case"amp":return"&";case"lt":return"<";case"gt":return">";case"quot":return'"';case"apos":return"'"}if(entity.startsWith("#x")||entity.startsWith("#X"))return decodeCodePoint(Number.parseInt(entity.slice(2),16));if(entity.startsWith("#"))return decodeCodePoint(Number.parseInt(entity.slice(1),10))}function decodeHtmlEntityAt(html,index3){let semicolonIndex=html.indexOf(";",index3+1);if(semicolonIndex===-1||semicolonIndex-index3>16)return;let entity=html.slice(index3+1,semicolonIndex),decoded=decodeHtmlEntity(entity);if(decoded!==void 0)return{text:decoded,length:semicolonIndex-index3+1}}var SPAN_CLOSE="</span>",HIGHLIGHT_CLASS_PREFIX="hljs-";function getScopeFromSpanTag(tag){let match2=/\sclass\s*=\s*(?:"([^"]*)"|'([^']*)')/.exec(tag),classValue=match2?.[1]??match2?.[2];if(classValue){for(let className of classValue.split(/\s+/))if(className.startsWith(HIGHLIGHT_CLASS_PREFIX))return className.slice(HIGHLIGHT_CLASS_PREFIX.length)}}function getScopeFormatter(scope,theme2){let exact=theme2[scope];if(exact)return exact;let dotIndex=scope.indexOf(".");if(dotIndex!==-1){let prefixFormatter=theme2[scope.slice(0,dotIndex)];if(prefixFormatter)return prefixFormatter}let dashIndex=scope.indexOf("-");if(dashIndex!==-1){let prefixFormatter=theme2[scope.slice(0,dashIndex)];if(prefixFormatter)return prefixFormatter}}function getActiveFormatter(scopes,theme2){for(let i=scopes.length-1;i>=0;i--){let scope=scopes[i];if(!scope)continue;let formatter=getScopeFormatter(scope,theme2);if(formatter)return formatter}return theme2.default}function isSpanOpenTagStart(html,index3){if(!html.startsWith("<span",index3))return!1;let nextChar=html[index3+5];return nextChar===">"||nextChar===" "||nextChar===" "||nextChar===`
|
|
635
|
-
`||nextChar==="\r"}function renderHighlightedHtml(html,theme2={}){let output="",textBuffer="",scopes=[],flushText=()=>{if(!textBuffer)return;let formatter=getActiveFormatter(scopes,theme2);output+=formatter?formatter(textBuffer):textBuffer,textBuffer=""},index3=0;for(;index3<html.length;){if(isSpanOpenTagStart(html,index3)){let tagEndIndex=html.indexOf(">",index3+5);if(tagEndIndex!==-1){flushText();let tag=html.slice(index3,tagEndIndex+1),scope=getScopeFromSpanTag(tag);scopes.push(scope),index3=tagEndIndex+1;continue}}if(html.startsWith(SPAN_CLOSE,index3)){flushText(),scopes.length>0&&scopes.pop(),index3+=SPAN_CLOSE.length;continue}if(html[index3]==="&"){let decoded=decodeHtmlEntityAt(html,index3);if(decoded){textBuffer+=decoded.text,index3+=decoded.length;continue}}textBuffer+=html[index3],index3++}return flushText(),output}function highlight(code,options={}){let html=options.language?import_lib.default.highlight(code,{language:options.language,ignoreIllegals:options.ignoreIllegals}).value:import_lib.default.highlightAuto(code,options.languageSubset).value;return renderHighlightedHtml(html,options.theme)}function supportsLanguage(name){return import_lib.default.getLanguage(name)!==void 0}async function loadAllHighlightLanguages(){}var themeJsonValidator;function setThemeJsonValidator(validator){themeJsonValidator=validator}var THEME_BACKGROUND_KEYS=new Set(["selectedBg","searchMatchBg","userMessageBg","customMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg"]);function hexToRgb2(hex){let cleaned=hex.replace("#","");if(cleaned.length!==6)throw new Error(`Invalid hex color: ${hex}`);let r=parseInt(cleaned.substring(0,2),16),g=parseInt(cleaned.substring(2,4),16),b2=parseInt(cleaned.substring(4,6),16);if(Number.isNaN(r)||Number.isNaN(g)||Number.isNaN(b2))throw new Error(`Invalid hex color: ${hex}`);return{r,g,b:b2}}var CUBE_VALUES=[0,95,135,175,215,255],GRAY_VALUES=Array.from({length:24},(_2,i)=>8+i*10);function findClosestCubeIndex(value2){let minDist=1/0,minIdx=0;for(let i=0;i<CUBE_VALUES.length;i++){let dist=Math.abs(value2-CUBE_VALUES[i]);dist<minDist&&(minDist=dist,minIdx=i)}return minIdx}function findClosestGrayIndex(gray){let minDist=1/0,minIdx=0;for(let i=0;i<GRAY_VALUES.length;i++){let dist=Math.abs(gray-GRAY_VALUES[i]);dist<minDist&&(minDist=dist,minIdx=i)}return minIdx}function colorDistance(r1,g1,b1,r2,g2,b2){let dr=r1-r2,dg=g1-g2,db=b1-b2;return dr*dr*.299+dg*dg*.587+db*db*.114}function rgbTo256(r,g,b2){let rIdx=findClosestCubeIndex(r),gIdx=findClosestCubeIndex(g),bIdx=findClosestCubeIndex(b2),cubeR=CUBE_VALUES[rIdx],cubeG=CUBE_VALUES[gIdx],cubeB=CUBE_VALUES[bIdx],cubeIndex=16+36*rIdx+6*gIdx+bIdx,cubeDist=colorDistance(r,g,b2,cubeR,cubeG,cubeB),gray=Math.round(.299*r+.587*g+.114*b2),grayIdx=findClosestGrayIndex(gray),grayValue=GRAY_VALUES[grayIdx],grayIndex=232+grayIdx,grayDist=colorDistance(r,g,b2,grayValue,grayValue,grayValue),maxC=Math.max(r,g,b2),minC=Math.min(r,g,b2);return maxC-minC<10&&grayDist<cubeDist?grayIndex:cubeIndex}function hexTo256(hex){let{r,g,b:b2}=hexToRgb2(hex);return rgbTo256(r,g,b2)}function fgAnsi(color2,mode){if(color2==="")return"\x1B[39m";if(typeof color2=="number")return`\x1B[38;5;${color2}m`;if(color2.startsWith("#"))if(mode==="truecolor"){let{r,g,b:b2}=hexToRgb2(color2);return`\x1B[38;2;${r};${g};${b2}m`}else return`\x1B[38;5;${hexTo256(color2)}m`;throw new Error(`Invalid color value: ${color2}`)}function bgAnsi(color2,mode){if(color2==="")return"\x1B[49m";if(typeof color2=="number")return`\x1B[48;5;${color2}m`;if(color2.startsWith("#"))if(mode==="truecolor"){let{r,g,b:b2}=hexToRgb2(color2);return`\x1B[48;2;${r};${g};${b2}m`}else return`\x1B[48;5;${hexTo256(color2)}m`;throw new Error(`Invalid color value: ${color2}`)}function resolveVarRefs(value2,vars,visited2=new Set){if(typeof value2=="number"||value2===""||value2.startsWith("#"))return value2;if(visited2.has(value2))throw new Error(`Circular variable reference detected: ${value2}`);if(!(value2 in vars))throw new Error(`Variable reference not found: ${value2}`);return visited2.add(value2),resolveVarRefs(vars[value2],vars,visited2)}function resolveThemeColors(colors,vars={}){let resolved={};for(let[key,value2]of Object.entries(colors))resolved[key]=resolveVarRefs(value2,vars);return resolved}function withThemeColorFallbacks(colors){return{...colors,scrollbarTrack:colors.scrollbarTrack??colors.muted,scrollbarThumb:colors.scrollbarThumb??colors.text,thinkingMax:colors.thinkingMax??colors.thinkingXhigh,searchMatchBg:colors.searchMatchBg??colors.selectedBg,searchMatchText:colors.searchMatchText??colors.text}}var Theme=class{constructor(fgColors,bgColors,mode,options={}){this.name=options.name,this.sourcePath=options.sourcePath,this.sourceInfo=options.sourceInfo,this.mode=mode,this.fgColors=new Map;let colors={...fgColors,scrollbarTrack:fgColors.scrollbarTrack??fgColors.muted,scrollbarThumb:fgColors.scrollbarThumb??fgColors.text,thinkingMax:fgColors.thinkingMax??fgColors.thinkingXhigh,searchMatchText:fgColors.searchMatchText??fgColors.text};for(let[key,value2]of Object.entries(colors))this.fgColors.set(key,fgAnsi(value2,mode));this.bgColors=new Map;let backgrounds={...bgColors,searchMatchBg:bgColors.searchMatchBg??bgColors.selectedBg};for(let[key,value2]of Object.entries(backgrounds))this.bgColors.set(key,bgAnsi(value2,mode))}fg(color2,text2){let ansi=this.fgColors.get(color2);if(!ansi)throw new Error(`Unknown theme color: ${color2}`);return`${ansi}${text2.replaceAll("\x1B[39m",ansi)}\x1B[39m`}bg(color2,text2){let ansi=this.bgColors.get(color2);if(!ansi)throw new Error(`Unknown theme background color: ${color2}`);return`${ansi}${text2.replaceAll("\x1B[49m",ansi)}\x1B[49m`}bold(text2){return source_default.bold(text2)}italic(text2){return source_default.italic(text2)}underline(text2){return source_default.underline(text2)}inverse(text2){return source_default.inverse(text2)}strikethrough(text2){return source_default.strikethrough(text2)}getFgAnsi(color2){let ansi=this.fgColors.get(color2);if(!ansi)throw new Error(`Unknown theme color: ${color2}`);return ansi}getBgAnsi(color2){let ansi=this.bgColors.get(color2);if(!ansi)throw new Error(`Unknown theme background color: ${color2}`);return ansi}getColorMode(){return this.mode}getThinkingBorderColor(level){switch(level){case"off":return str2=>this.fg("thinkingOff",str2);case"minimal":return str2=>this.fg("thinkingMinimal",str2);case"low":return str2=>this.fg("thinkingLow",str2);case"medium":return str2=>this.fg("thinkingMedium",str2);case"high":return str2=>this.fg("thinkingHigh",str2);case"xhigh":return str2=>this.fg("thinkingXhigh",str2);case"max":return str2=>this.fg("thinkingMax",str2);default:return str2=>this.fg("thinkingOff",str2)}}getBashModeBorderColor(){return str2=>this.fg("bashMode",str2)}},BUILTIN_THEME_NAMES=["dark","light","ice-cream-dark","ice-cream-light"],BUILTIN_THEMES;function getBuiltinThemes(){if(!BUILTIN_THEMES){let themesDir=getThemesDir();BUILTIN_THEMES={};for(let name of BUILTIN_THEME_NAMES){let themePath=path6.join(themesDir,`${name}.json`);BUILTIN_THEMES[name]=JSON.parse(stripBom(fs4.readFileSync(themePath,"utf-8")))}}return BUILTIN_THEMES}function getAvailableThemes(){return getAvailableThemesWithPaths().map(({name})=>name)}function getAvailableThemesWithPaths(){let themesDir=getThemesDir(),result2=[],seen=new Set,addTheme=themeInfo=>{seen.has(themeInfo.name)||(seen.add(themeInfo.name),result2.push(themeInfo))};for(let name of Object.keys(getBuiltinThemes()))addTheme({name,path:path6.join(themesDir,`${name}.json`)});for(let themeInfo of getCustomThemeInfos())addTheme(themeInfo);for(let[name,theme2]of registeredThemes.entries())addTheme({name,path:theme2.sourcePath});return result2.sort((a,b2)=>a.name.localeCompare(b2.name))}function getCustomThemeInfos(){let customThemesDir=getCustomThemesDir(),result2=[];if(!fs4.existsSync(customThemesDir))return result2;for(let file of fs4.readdirSync(customThemesDir)){if(!file.endsWith(".json"))continue;let themePath=path6.join(customThemesDir,file);try{let customTheme=loadThemeFromPath(themePath);customTheme.name&&result2.push({name:customTheme.name,path:themePath})}catch{}}return result2}function assertThemeNameIsValid(name){if(name.includes("/"))throw new Error(`Invalid theme name "${name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`)}function parseThemeJson(label,json){if(themeJsonValidator)return themeJsonValidator(label,json);if(typeof json!="object"||json===null||!("colors"in json))throw new Error(`Invalid theme "${label}": expected an object with a "colors" map.`);return json}function parseThemeJsonContent(label,content){let json;try{json=JSON.parse(stripBom(content))}catch(error){throw new Error(`Failed to parse theme ${label}: ${error}`)}return parseThemeJson(label,json)}function loadThemeJson(name){let builtinThemes=getBuiltinThemes();if(name in builtinThemes)return builtinThemes[name];let registeredTheme=registeredThemes.get(name);if(registeredTheme?.sourcePath){let content2=fs4.readFileSync(registeredTheme.sourcePath,"utf-8");return parseThemeJsonContent(registeredTheme.sourcePath,content2)}if(registeredTheme)throw new Error(`Theme "${name}" does not have a source path for export`);let customThemesDir=getCustomThemesDir(),themePath=path6.join(customThemesDir,`${name}.json`);if(!fs4.existsSync(themePath))throw new Error(`Theme not found: ${name}`);let content=fs4.readFileSync(themePath,"utf-8");return parseThemeJsonContent(name,content)}function createTheme(themeJson,mode,sourcePath){let colorMode=mode??(getCapabilities().trueColor?"truecolor":"256color"),resolvedColors=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),fgColors={},bgColors={};for(let[key,value2]of Object.entries(resolvedColors))THEME_BACKGROUND_KEYS.has(key)?bgColors[key]=value2:fgColors[key]=value2;return new Theme(fgColors,bgColors,colorMode,{name:themeJson.name,sourcePath})}function loadThemeFromPath(themePath,mode){let content=fs4.readFileSync(themePath,"utf-8"),themeJson=parseThemeJsonContent(themePath,content);return createTheme(themeJson,mode,themePath)}function loadTheme(name,mode){let registeredTheme=registeredThemes.get(name);if(registeredTheme)return registeredTheme;let themeJson=loadThemeJson(name);return createTheme(themeJson,mode)}function getThemeByName(name){try{return loadTheme(name)}catch{return}}function parseAutoThemeSetting(themeSetting){if(!themeSetting)return;let slashIndex=themeSetting.indexOf("/");if(slashIndex===-1||themeSetting.indexOf("/",slashIndex+1)!==-1)return;let lightTheme=themeSetting.slice(0,slashIndex).trim(),darkTheme=themeSetting.slice(slashIndex+1).trim();if(!(!lightTheme||!darkTheme))return{lightTheme,darkTheme}}function resolveThemeSetting(themeSetting,terminalTheme){let autoTheme=parseAutoThemeSetting(themeSetting);if(autoTheme)return terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;if(!themeSetting?.includes("/")&&typeof themeSetting=="string")return themeSetting}function getColorFgBgBackgroundIndex(colorfgbg){let parts=colorfgbg.split(";");for(let i=parts.length-1;i>=0;i--){let bg=parseInt(parts[i].trim(),10);if(Number.isInteger(bg)&&bg>=0&&bg<=255)return bg}}function getRgbColorLuminance({r,g,b:b2}){let toLinear=channel=>{let value2=channel/255;return value2<=.03928?value2/12.92:((value2+.055)/1.055)**2.4};return .2126*toLinear(r)+.7152*toLinear(g)+.0722*toLinear(b2)}function getAnsiColorLuminance(index3){return getRgbColorLuminance(hexToRgb2(ansi256ToHex(index3)))}function getThemeForRgbColor(rgb2){return getRgbColorLuminance(rgb2)>=.5?"light":"dark"}function detectTerminalBackgroundFromEnv(options={}){let colorfgbg=(options.env??process.env).COLORFGBG||"",bg=getColorFgBgBackgroundIndex(colorfgbg);return bg!==void 0?{theme:getAnsiColorLuminance(bg)>=.5?"light":"dark",source:"COLORFGBG",detail:`background color index ${bg}`,confidence:"high"}:{theme:"dark",source:"fallback",detail:"no terminal background hint found",confidence:"low"}}async function detectTerminalBackgroundTheme({ui,timeoutMs,env:env2}){try{let rgb2=await ui.queryTerminalBackgroundColor({timeoutMs});if(rgb2)return{theme:getThemeForRgbColor(rgb2),source:"terminal background",detail:`OSC 11 background rgb(${rgb2.r}, ${rgb2.g}, ${rgb2.b})`,confidence:"high"}}catch{}return detectTerminalBackgroundFromEnv({env:env2})}async function detectTerminalThemeForAuto({ui,timeoutMs,env:env2}){let colorSchemePromise;try{colorSchemePromise=ui.queryTerminalColorScheme?.({timeoutMs})}catch{}let backgroundThemePromise=detectTerminalBackgroundTheme({ui,timeoutMs,env:env2});try{let colorScheme=await colorSchemePromise;if(colorScheme)return colorScheme}catch{}return(await backgroundThemePromise).theme}function getDefaultTheme(){return detectTerminalBackgroundFromEnv().theme}var THEME_KEY=Symbol.for("@earendil-works/pi-coding-agent:theme"),THEME_KEY_OLD=Symbol.for("@mariozechner/pi-coding-agent:theme"),theme=new Proxy({},{get(_target,prop){let t=globalThis[THEME_KEY];if(!t)throw new Error("Theme not initialized. Call initTheme() first.");return t[prop]}});function setGlobalTheme(t){globalThis[THEME_KEY]=t,globalThis[THEME_KEY_OLD]=t}var currentThemeName,themeWatcher,themeReloadTimer,onThemeChangeCallback,registeredThemes=new Map;function setRegisteredThemes(themes){registeredThemes.clear();for(let theme2 of themes)theme2.name&&(assertThemeNameIsValid(theme2.name),registeredThemes.set(theme2.name,theme2))}function initTheme(themeName,enableWatcher=!1){let name=themeName??getDefaultTheme();currentThemeName=name;try{setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher()}catch{currentThemeName="dark",setGlobalTheme(loadTheme("dark"))}}function setTheme(name,enableWatcher=!1){currentThemeName=name;try{return setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback(),{success:!0}}catch(error){return currentThemeName="dark",setGlobalTheme(loadTheme("dark")),{success:!1,error:error instanceof Error?error.message:String(error)}}}function setThemeInstance(themeInstance){setGlobalTheme(themeInstance),currentThemeName="<in-memory>",stopThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback()}function onThemeChange(callback){onThemeChangeCallback=callback}function startThemeWatcher(){if(stopThemeWatcher(),!currentThemeName||currentThemeName in getBuiltinThemes())return;let customThemesDir=getCustomThemesDir(),watchedThemeName=currentThemeName,watchedFileName=`${watchedThemeName}.json`,themeFile=path6.join(customThemesDir,watchedFileName);if(!fs4.existsSync(themeFile))return;let scheduleReload=()=>{themeReloadTimer&&clearTimeout(themeReloadTimer),themeReloadTimer=setTimeout(()=>{if(themeReloadTimer=void 0,currentThemeName===watchedThemeName&&fs4.existsSync(themeFile))try{let reloadedTheme=loadThemeFromPath(themeFile);registeredThemes.set(watchedThemeName,reloadedTheme),setGlobalTheme(reloadedTheme),onThemeChangeCallback&&onThemeChangeCallback()}catch{}},100)};themeWatcher=watchWithErrorHandler(customThemesDir,(_eventType,filename)=>{if(currentThemeName===watchedThemeName){if(!filename){scheduleReload();return}filename===watchedFileName&&scheduleReload()}},()=>{closeWatcher(themeWatcher),themeWatcher=void 0})??void 0}function stopThemeWatcher(){themeReloadTimer&&(clearTimeout(themeReloadTimer),themeReloadTimer=void 0),closeWatcher(themeWatcher),themeWatcher=void 0}function ansi256ToHex(index3){let basicColors=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];if(index3<16)return basicColors[index3];if(index3<232){let cubeIndex=index3-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex%36/6),b2=cubeIndex%6,toHex=n=>(n===0?0:55+n*40).toString(16).padStart(2,"0");return`#${toHex(r)}${toHex(g)}${toHex(b2)}`}let grayHex=(8+(index3-232)*10).toString(16).padStart(2,"0");return`#${grayHex}${grayHex}${grayHex}`}function getResolvedThemeColors(themeName){let name=themeName??currentThemeName??getDefaultTheme(),themeJson=loadThemeJson(name),resolved=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),resolvedText=resolved.text,defaultText=typeof resolvedText=="number"?ansi256ToHex(resolvedText):resolvedText||(name==="light"||name==="ice-cream-light"?"#000000":"#e5e5e7"),cssColors={};for(let[key,value2]of Object.entries(resolved))typeof value2=="number"?cssColors[key]=ansi256ToHex(value2):value2===""?cssColors[key]=THEME_BACKGROUND_KEYS.has(key)?"transparent":defaultText:cssColors[key]=value2;return cssColors}function getThemeExportColors(themeName){let name=themeName??currentThemeName??getDefaultTheme();try{let themeJson=loadThemeJson(name),exportSection=themeJson.export;if(!exportSection)return{};let vars=themeJson.vars??{},resolve17=value2=>{if(value2===void 0)return;let resolved=resolveVarRefs(value2,vars);if(typeof resolved=="number")return ansi256ToHex(resolved);if(resolved!=="")return resolved};return{pageBg:resolve17(exportSection.pageBg),cardBg:resolve17(exportSection.cardBg),infoBg:resolve17(exportSection.infoBg)}}catch{return{}}}var cachedHighlightThemeFor,cachedCliHighlightTheme;function buildCliHighlightTheme(t){return{keyword:s=>t.fg("syntaxKeyword",s),built_in:s=>t.fg("syntaxType",s),literal:s=>t.fg("syntaxNumber",s),number:s=>t.fg("syntaxNumber",s),regexp:s=>t.fg("syntaxString",s),string:s=>t.fg("syntaxString",s),comment:s=>t.fg("syntaxComment",s),doctag:s=>t.fg("syntaxComment",s),meta:s=>t.fg("muted",s),function:s=>t.fg("syntaxFunction",s),title:s=>t.fg("syntaxFunction",s),class:s=>t.fg("syntaxType",s),type:s=>t.fg("syntaxType",s),tag:s=>t.fg("syntaxPunctuation",s),name:s=>t.fg("syntaxKeyword",s),attr:s=>t.fg("syntaxVariable",s),variable:s=>t.fg("syntaxVariable",s),params:s=>t.fg("syntaxVariable",s),operator:s=>t.fg("syntaxOperator",s),punctuation:s=>t.fg("syntaxPunctuation",s),emphasis:s=>t.italic(s),strong:s=>t.bold(s),link:s=>t.underline(s),addition:s=>t.fg("toolDiffAdded",s),deletion:s=>t.fg("toolDiffRemoved",s)}}function getCliHighlightTheme(t){return(cachedHighlightThemeFor!==t||!cachedCliHighlightTheme)&&(cachedHighlightThemeFor=t,cachedCliHighlightTheme=buildCliHighlightTheme(t)),cachedCliHighlightTheme}function highlightCode(code,lang){let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`
|
|
635
|
+
`||nextChar==="\r"}function renderHighlightedHtml(html,theme2={}){let output="",textBuffer="",scopes=[],flushText=()=>{if(!textBuffer)return;let formatter=getActiveFormatter(scopes,theme2);output+=formatter?formatter(textBuffer):textBuffer,textBuffer=""},index3=0;for(;index3<html.length;){if(isSpanOpenTagStart(html,index3)){let tagEndIndex=html.indexOf(">",index3+5);if(tagEndIndex!==-1){flushText();let tag=html.slice(index3,tagEndIndex+1),scope=getScopeFromSpanTag(tag);scopes.push(scope),index3=tagEndIndex+1;continue}}if(html.startsWith(SPAN_CLOSE,index3)){flushText(),scopes.length>0&&scopes.pop(),index3+=SPAN_CLOSE.length;continue}if(html[index3]==="&"){let decoded=decodeHtmlEntityAt(html,index3);if(decoded){textBuffer+=decoded.text,index3+=decoded.length;continue}}textBuffer+=html[index3],index3++}return flushText(),output}function highlight(code,options={}){let html=options.language?import_lib.default.highlight(code,{language:options.language,ignoreIllegals:options.ignoreIllegals}).value:import_lib.default.highlightAuto(code,options.languageSubset).value;return renderHighlightedHtml(html,options.theme)}function supportsLanguage(name){return import_lib.default.getLanguage(name)!==void 0}async function loadAllHighlightLanguages(){}var themeJsonValidator;function setThemeJsonValidator(validator){themeJsonValidator=validator}var THEME_BACKGROUND_KEYS=new Set(["selectedBg","searchMatchBg","userMessageBg","customMessageBg","toolPendingBg","toolSuccessBg","toolErrorBg"]);function hexToRgb2(hex){let cleaned=hex.replace("#","");if(cleaned.length!==6)throw new Error(`Invalid hex color: ${hex}`);let r=parseInt(cleaned.substring(0,2),16),g=parseInt(cleaned.substring(2,4),16),b2=parseInt(cleaned.substring(4,6),16);if(Number.isNaN(r)||Number.isNaN(g)||Number.isNaN(b2))throw new Error(`Invalid hex color: ${hex}`);return{r,g,b:b2}}var CUBE_VALUES=[0,95,135,175,215,255],GRAY_VALUES=Array.from({length:24},(_2,i)=>8+i*10);function findClosestCubeIndex(value2){let minDist=1/0,minIdx=0;for(let i=0;i<CUBE_VALUES.length;i++){let dist=Math.abs(value2-CUBE_VALUES[i]);dist<minDist&&(minDist=dist,minIdx=i)}return minIdx}function findClosestGrayIndex(gray){let minDist=1/0,minIdx=0;for(let i=0;i<GRAY_VALUES.length;i++){let dist=Math.abs(gray-GRAY_VALUES[i]);dist<minDist&&(minDist=dist,minIdx=i)}return minIdx}function colorDistance(r1,g1,b1,r2,g2,b2){let dr=r1-r2,dg=g1-g2,db=b1-b2;return dr*dr*.299+dg*dg*.587+db*db*.114}function rgbTo256(r,g,b2){let rIdx=findClosestCubeIndex(r),gIdx=findClosestCubeIndex(g),bIdx=findClosestCubeIndex(b2),cubeR=CUBE_VALUES[rIdx],cubeG=CUBE_VALUES[gIdx],cubeB=CUBE_VALUES[bIdx],cubeIndex=16+36*rIdx+6*gIdx+bIdx,cubeDist=colorDistance(r,g,b2,cubeR,cubeG,cubeB),gray=Math.round(.299*r+.587*g+.114*b2),grayIdx=findClosestGrayIndex(gray),grayValue=GRAY_VALUES[grayIdx],grayIndex=232+grayIdx,grayDist=colorDistance(r,g,b2,grayValue,grayValue,grayValue),maxC=Math.max(r,g,b2),minC=Math.min(r,g,b2);return maxC-minC<10&&grayDist<cubeDist?grayIndex:cubeIndex}function hexTo256(hex){let{r,g,b:b2}=hexToRgb2(hex);return rgbTo256(r,g,b2)}function fgAnsi(color2,mode){if(color2==="")return"\x1B[39m";if(typeof color2=="number")return`\x1B[38;5;${color2}m`;if(color2.startsWith("#"))if(mode==="truecolor"){let{r,g,b:b2}=hexToRgb2(color2);return`\x1B[38;2;${r};${g};${b2}m`}else return`\x1B[38;5;${hexTo256(color2)}m`;throw new Error(`Invalid color value: ${color2}`)}function bgAnsi(color2,mode){if(color2==="")return"\x1B[49m";if(typeof color2=="number")return`\x1B[48;5;${color2}m`;if(color2.startsWith("#"))if(mode==="truecolor"){let{r,g,b:b2}=hexToRgb2(color2);return`\x1B[48;2;${r};${g};${b2}m`}else return`\x1B[48;5;${hexTo256(color2)}m`;throw new Error(`Invalid color value: ${color2}`)}function resolveVarRefs(value2,vars,visited2=new Set){if(typeof value2=="number"||value2===""||value2.startsWith("#"))return value2;if(visited2.has(value2))throw new Error(`Circular variable reference detected: ${value2}`);if(!(value2 in vars))throw new Error(`Variable reference not found: ${value2}`);return visited2.add(value2),resolveVarRefs(vars[value2],vars,visited2)}function resolveThemeColors(colors,vars={}){let resolved={};for(let[key,value2]of Object.entries(colors))resolved[key]=resolveVarRefs(value2,vars);return resolved}function withThemeColorFallbacks(colors){return{...colors,scrollbarTrack:colors.scrollbarTrack??colors.muted,scrollbarThumb:colors.scrollbarThumb??colors.text,thinkingMax:colors.thinkingMax??colors.thinkingXhigh,searchMatchBg:colors.searchMatchBg??colors.selectedBg,searchMatchText:colors.searchMatchText??colors.text}}var Theme=class{constructor(fgColors,bgColors,mode,options={}){this.name=options.name,this.sourcePath=options.sourcePath,this.sourceInfo=options.sourceInfo,this.mode=mode,this.fgColors=new Map;let colors={...fgColors,scrollbarTrack:fgColors.scrollbarTrack??fgColors.muted,scrollbarThumb:fgColors.scrollbarThumb??fgColors.text,thinkingMax:fgColors.thinkingMax??fgColors.thinkingXhigh,searchMatchText:fgColors.searchMatchText??fgColors.text};for(let[key,value2]of Object.entries(colors))this.fgColors.set(key,fgAnsi(value2,mode));this.bgColors=new Map;let backgrounds={...bgColors,searchMatchBg:bgColors.searchMatchBg??bgColors.selectedBg};for(let[key,value2]of Object.entries(backgrounds))this.bgColors.set(key,bgAnsi(value2,mode))}fg(color2,text2){let ansi=this.fgColors.get(color2);if(!ansi)throw new Error(`Unknown theme color: ${color2}`);return`${ansi}${text2}\x1B[39m`}bg(color2,text2){let ansi=this.bgColors.get(color2);if(!ansi)throw new Error(`Unknown theme background color: ${color2}`);return`${ansi}${text2}\x1B[49m`}bold(text2){return source_default.bold(text2)}italic(text2){return source_default.italic(text2)}underline(text2){return source_default.underline(text2)}inverse(text2){return source_default.inverse(text2)}strikethrough(text2){return source_default.strikethrough(text2)}getFgAnsi(color2){let ansi=this.fgColors.get(color2);if(!ansi)throw new Error(`Unknown theme color: ${color2}`);return ansi}getBgAnsi(color2){let ansi=this.bgColors.get(color2);if(!ansi)throw new Error(`Unknown theme background color: ${color2}`);return ansi}getColorMode(){return this.mode}getThinkingBorderColor(level){switch(level){case"off":return str2=>this.fg("thinkingOff",str2);case"minimal":return str2=>this.fg("thinkingMinimal",str2);case"low":return str2=>this.fg("thinkingLow",str2);case"medium":return str2=>this.fg("thinkingMedium",str2);case"high":return str2=>this.fg("thinkingHigh",str2);case"xhigh":return str2=>this.fg("thinkingXhigh",str2);case"max":return str2=>this.fg("thinkingMax",str2);default:return str2=>this.fg("thinkingOff",str2)}}getBashModeBorderColor(){return str2=>this.fg("bashMode",str2)}},BUILTIN_THEME_NAMES=["dark","light","ice-cream-dark","ice-cream-light"],BUILTIN_THEMES;function getBuiltinThemes(){if(!BUILTIN_THEMES){let themesDir=getThemesDir();BUILTIN_THEMES={};for(let name of BUILTIN_THEME_NAMES){let themePath=path6.join(themesDir,`${name}.json`);BUILTIN_THEMES[name]=JSON.parse(stripBom(fs4.readFileSync(themePath,"utf-8")))}}return BUILTIN_THEMES}function getAvailableThemes(){return getAvailableThemesWithPaths().map(({name})=>name)}function getAvailableThemesWithPaths(){let themesDir=getThemesDir(),result2=[],seen=new Set,addTheme=themeInfo=>{seen.has(themeInfo.name)||(seen.add(themeInfo.name),result2.push(themeInfo))};for(let name of Object.keys(getBuiltinThemes()))addTheme({name,path:path6.join(themesDir,`${name}.json`)});for(let themeInfo of getCustomThemeInfos())addTheme(themeInfo);for(let[name,theme2]of registeredThemes.entries())addTheme({name,path:theme2.sourcePath});return result2.sort((a,b2)=>a.name.localeCompare(b2.name))}function getCustomThemeInfos(){let customThemesDir=getCustomThemesDir(),result2=[];if(!fs4.existsSync(customThemesDir))return result2;for(let file of fs4.readdirSync(customThemesDir)){if(!file.endsWith(".json"))continue;let themePath=path6.join(customThemesDir,file);try{let customTheme=loadThemeFromPath(themePath);customTheme.name&&result2.push({name:customTheme.name,path:themePath})}catch{}}return result2}function assertThemeNameIsValid(name){if(name.includes("/"))throw new Error(`Invalid theme name "${name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`)}function parseThemeJson(label,json){if(themeJsonValidator)return themeJsonValidator(label,json);if(typeof json!="object"||json===null||!("colors"in json))throw new Error(`Invalid theme "${label}": expected an object with a "colors" map.`);return json}function parseThemeJsonContent(label,content){let json;try{json=JSON.parse(stripBom(content))}catch(error){throw new Error(`Failed to parse theme ${label}: ${error}`)}return parseThemeJson(label,json)}function loadThemeJson(name){let builtinThemes=getBuiltinThemes();if(name in builtinThemes)return builtinThemes[name];let registeredTheme=registeredThemes.get(name);if(registeredTheme?.sourcePath){let content2=fs4.readFileSync(registeredTheme.sourcePath,"utf-8");return parseThemeJsonContent(registeredTheme.sourcePath,content2)}if(registeredTheme)throw new Error(`Theme "${name}" does not have a source path for export`);let customThemesDir=getCustomThemesDir(),themePath=path6.join(customThemesDir,`${name}.json`);if(!fs4.existsSync(themePath))throw new Error(`Theme not found: ${name}`);let content=fs4.readFileSync(themePath,"utf-8");return parseThemeJsonContent(name,content)}function createTheme(themeJson,mode,sourcePath){let colorMode=mode??(getCapabilities().trueColor?"truecolor":"256color"),resolvedColors=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),fgColors={},bgColors={};for(let[key,value2]of Object.entries(resolvedColors))THEME_BACKGROUND_KEYS.has(key)?bgColors[key]=value2:fgColors[key]=value2;return new Theme(fgColors,bgColors,colorMode,{name:themeJson.name,sourcePath})}function loadThemeFromPath(themePath,mode){let content=fs4.readFileSync(themePath,"utf-8"),themeJson=parseThemeJsonContent(themePath,content);return createTheme(themeJson,mode,themePath)}function loadTheme(name,mode){let registeredTheme=registeredThemes.get(name);if(registeredTheme)return registeredTheme;let themeJson=loadThemeJson(name);return createTheme(themeJson,mode)}function getThemeByName(name){try{return loadTheme(name)}catch{return}}function parseAutoThemeSetting(themeSetting){if(!themeSetting)return;let slashIndex=themeSetting.indexOf("/");if(slashIndex===-1||themeSetting.indexOf("/",slashIndex+1)!==-1)return;let lightTheme=themeSetting.slice(0,slashIndex).trim(),darkTheme=themeSetting.slice(slashIndex+1).trim();if(!(!lightTheme||!darkTheme))return{lightTheme,darkTheme}}function resolveThemeSetting(themeSetting,terminalTheme){let autoTheme=parseAutoThemeSetting(themeSetting);if(autoTheme)return terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;if(!themeSetting?.includes("/")&&typeof themeSetting=="string")return themeSetting}function getColorFgBgBackgroundIndex(colorfgbg){let parts=colorfgbg.split(";");for(let i=parts.length-1;i>=0;i--){let bg=parseInt(parts[i].trim(),10);if(Number.isInteger(bg)&&bg>=0&&bg<=255)return bg}}function getRgbColorLuminance({r,g,b:b2}){let toLinear=channel=>{let value2=channel/255;return value2<=.03928?value2/12.92:((value2+.055)/1.055)**2.4};return .2126*toLinear(r)+.7152*toLinear(g)+.0722*toLinear(b2)}function getAnsiColorLuminance(index3){return getRgbColorLuminance(hexToRgb2(ansi256ToHex(index3)))}function getThemeForRgbColor(rgb2){return getRgbColorLuminance(rgb2)>=.5?"light":"dark"}function detectTerminalBackgroundFromEnv(options={}){let colorfgbg=(options.env??process.env).COLORFGBG||"",bg=getColorFgBgBackgroundIndex(colorfgbg);return bg!==void 0?{theme:getAnsiColorLuminance(bg)>=.5?"light":"dark",source:"COLORFGBG",detail:`background color index ${bg}`,confidence:"high"}:{theme:"dark",source:"fallback",detail:"no terminal background hint found",confidence:"low"}}async function detectTerminalBackgroundTheme({ui,timeoutMs,env:env2}){try{let rgb2=await ui.queryTerminalBackgroundColor({timeoutMs});if(rgb2)return{theme:getThemeForRgbColor(rgb2),source:"terminal background",detail:`OSC 11 background rgb(${rgb2.r}, ${rgb2.g}, ${rgb2.b})`,confidence:"high"}}catch{}return detectTerminalBackgroundFromEnv({env:env2})}async function detectTerminalThemeForAuto({ui,timeoutMs,env:env2}){let colorSchemePromise;try{colorSchemePromise=ui.queryTerminalColorScheme?.({timeoutMs})}catch{}let backgroundThemePromise=detectTerminalBackgroundTheme({ui,timeoutMs,env:env2});try{let colorScheme=await colorSchemePromise;if(colorScheme)return colorScheme}catch{}return(await backgroundThemePromise).theme}function getDefaultTheme(){return detectTerminalBackgroundFromEnv().theme}var THEME_KEY=Symbol.for("@earendil-works/pi-coding-agent:theme"),THEME_KEY_OLD=Symbol.for("@mariozechner/pi-coding-agent:theme"),theme=new Proxy({},{get(_target,prop){let t=globalThis[THEME_KEY];if(!t)throw new Error("Theme not initialized. Call initTheme() first.");return t[prop]}});function setGlobalTheme(t){globalThis[THEME_KEY]=t,globalThis[THEME_KEY_OLD]=t}var currentThemeName,themeWatcher,themeReloadTimer,onThemeChangeCallback,registeredThemes=new Map;function setRegisteredThemes(themes){registeredThemes.clear();for(let theme2 of themes)theme2.name&&(assertThemeNameIsValid(theme2.name),registeredThemes.set(theme2.name,theme2))}function initTheme(themeName,enableWatcher=!1){let name=themeName??getDefaultTheme();currentThemeName=name;try{setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher()}catch{currentThemeName="dark",setGlobalTheme(loadTheme("dark"))}}function setTheme(name,enableWatcher=!1){currentThemeName=name;try{return setGlobalTheme(loadTheme(name)),enableWatcher&&startThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback(),{success:!0}}catch(error){return currentThemeName="dark",setGlobalTheme(loadTheme("dark")),{success:!1,error:error instanceof Error?error.message:String(error)}}}function setThemeInstance(themeInstance){setGlobalTheme(themeInstance),currentThemeName="<in-memory>",stopThemeWatcher(),onThemeChangeCallback&&onThemeChangeCallback()}function onThemeChange(callback){onThemeChangeCallback=callback}function startThemeWatcher(){if(stopThemeWatcher(),!currentThemeName||currentThemeName in getBuiltinThemes())return;let customThemesDir=getCustomThemesDir(),watchedThemeName=currentThemeName,watchedFileName=`${watchedThemeName}.json`,themeFile=path6.join(customThemesDir,watchedFileName);if(!fs4.existsSync(themeFile))return;let scheduleReload=()=>{themeReloadTimer&&clearTimeout(themeReloadTimer),themeReloadTimer=setTimeout(()=>{if(themeReloadTimer=void 0,currentThemeName===watchedThemeName&&fs4.existsSync(themeFile))try{let reloadedTheme=loadThemeFromPath(themeFile);registeredThemes.set(watchedThemeName,reloadedTheme),setGlobalTheme(reloadedTheme),onThemeChangeCallback&&onThemeChangeCallback()}catch{}},100)};themeWatcher=watchWithErrorHandler(customThemesDir,(_eventType,filename)=>{if(currentThemeName===watchedThemeName){if(!filename){scheduleReload();return}filename===watchedFileName&&scheduleReload()}},()=>{closeWatcher(themeWatcher),themeWatcher=void 0})??void 0}function stopThemeWatcher(){themeReloadTimer&&(clearTimeout(themeReloadTimer),themeReloadTimer=void 0),closeWatcher(themeWatcher),themeWatcher=void 0}function ansi256ToHex(index3){let basicColors=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];if(index3<16)return basicColors[index3];if(index3<232){let cubeIndex=index3-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex%36/6),b2=cubeIndex%6,toHex=n=>(n===0?0:55+n*40).toString(16).padStart(2,"0");return`#${toHex(r)}${toHex(g)}${toHex(b2)}`}let grayHex=(8+(index3-232)*10).toString(16).padStart(2,"0");return`#${grayHex}${grayHex}${grayHex}`}function getResolvedThemeColors(themeName){let name=themeName??currentThemeName??getDefaultTheme(),themeJson=loadThemeJson(name),resolved=resolveThemeColors(withThemeColorFallbacks(themeJson.colors),themeJson.vars),resolvedText=resolved.text,defaultText=typeof resolvedText=="number"?ansi256ToHex(resolvedText):resolvedText||(name==="light"||name==="ice-cream-light"?"#000000":"#e5e5e7"),cssColors={};for(let[key,value2]of Object.entries(resolved))typeof value2=="number"?cssColors[key]=ansi256ToHex(value2):value2===""?cssColors[key]=THEME_BACKGROUND_KEYS.has(key)?"transparent":defaultText:cssColors[key]=value2;return cssColors}function getThemeExportColors(themeName){let name=themeName??currentThemeName??getDefaultTheme();try{let themeJson=loadThemeJson(name),exportSection=themeJson.export;if(!exportSection)return{};let vars=themeJson.vars??{},resolve17=value2=>{if(value2===void 0)return;let resolved=resolveVarRefs(value2,vars);if(typeof resolved=="number")return ansi256ToHex(resolved);if(resolved!=="")return resolved};return{pageBg:resolve17(exportSection.pageBg),cardBg:resolve17(exportSection.cardBg),infoBg:resolve17(exportSection.infoBg)}}catch{return{}}}var cachedHighlightThemeFor,cachedCliHighlightTheme;function buildCliHighlightTheme(t){return{keyword:s=>t.fg("syntaxKeyword",s),built_in:s=>t.fg("syntaxType",s),literal:s=>t.fg("syntaxNumber",s),number:s=>t.fg("syntaxNumber",s),regexp:s=>t.fg("syntaxString",s),string:s=>t.fg("syntaxString",s),comment:s=>t.fg("syntaxComment",s),doctag:s=>t.fg("syntaxComment",s),meta:s=>t.fg("muted",s),function:s=>t.fg("syntaxFunction",s),title:s=>t.fg("syntaxFunction",s),class:s=>t.fg("syntaxType",s),type:s=>t.fg("syntaxType",s),tag:s=>t.fg("syntaxPunctuation",s),name:s=>t.fg("syntaxKeyword",s),attr:s=>t.fg("syntaxVariable",s),variable:s=>t.fg("syntaxVariable",s),params:s=>t.fg("syntaxVariable",s),operator:s=>t.fg("syntaxOperator",s),punctuation:s=>t.fg("syntaxPunctuation",s),emphasis:s=>t.italic(s),strong:s=>t.bold(s),link:s=>t.underline(s),addition:s=>t.fg("toolDiffAdded",s),deletion:s=>t.fg("toolDiffRemoved",s)}}function getCliHighlightTheme(t){return(cachedHighlightThemeFor!==t||!cachedCliHighlightTheme)&&(cachedHighlightThemeFor=t,cachedCliHighlightTheme=buildCliHighlightTheme(t)),cachedCliHighlightTheme}function highlightCode(code,lang){let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`
|
|
636
636
|
`).map(line=>theme.fg("mdCodeBlock",line));let opts={language:validLang,ignoreIllegals:!0,theme:getCliHighlightTheme(theme)};try{return highlight(code,opts).split(`
|
|
637
637
|
`)}catch{return code.split(`
|
|
638
638
|
`)}}function getLanguageFromPath(filePath){let ext2=filePath.split(".").pop()?.toLowerCase();return ext2?{ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",mjs:"javascript",cjs:"javascript",py:"python",rb:"ruby",rs:"rust",go:"go",java:"java",kt:"kotlin",swift:"swift",c:"c",h:"c",cpp:"cpp",cc:"cpp",cxx:"cpp",hpp:"cpp",cs:"csharp",php:"php",sh:"bash",bash:"bash",zsh:"bash",fish:"fish",ps1:"powershell",sql:"sql",html:"html",htm:"html",css:"css",scss:"scss",sass:"sass",less:"less",json:"json",yaml:"yaml",yml:"yaml",toml:"toml",xml:"xml",md:"markdown",markdown:"markdown",dockerfile:"dockerfile",makefile:"makefile",cmake:"cmake",lua:"lua",perl:"perl",r:"r",scala:"scala",clj:"clojure",ex:"elixir",exs:"elixir",erl:"erlang",hs:"haskell",ml:"ocaml",vim:"vim",graphql:"graphql",proto:"protobuf",tf:"hcl",hcl:"hcl"}[ext2]:void 0}function getMarkdownTheme(){return{heading:text2=>theme.fg("mdHeading",text2),link:text2=>theme.fg("mdLink",text2),linkUrl:text2=>theme.fg("mdLinkUrl",text2),code:text2=>theme.fg("mdCode",text2),codeBlock:text2=>theme.fg("mdCodeBlock",text2),codeBlockBorder:text2=>theme.fg("mdCodeBlockBorder",text2),quote:text2=>theme.fg("mdQuote",text2),quoteBorder:text2=>theme.fg("mdQuoteBorder",text2),hr:text2=>theme.fg("mdHr",text2),listBullet:text2=>theme.fg("mdListBullet",text2),bold:text2=>theme.bold(text2),italic:text2=>theme.italic(text2),underline:text2=>theme.underline(text2),strikethrough:text2=>source_default.strikethrough(text2),highlightCode:(code,lang)=>{let validLang=lang&&supportsLanguage(lang)?lang:void 0;if(!validLang)return code.split(`
|
|
@@ -640,7 +640,7 @@ File: ${path14}`)}let config=parsed,providers=new Map;for(let[providerId,provide
|
|
|
640
640
|
`)}catch{return code.split(`
|
|
641
641
|
`).map(line=>theme.fg("mdCodeBlock",line))}}}}function getSelectListTheme(){return{selectedPrefix:text2=>theme.fg("accent",text2),selectedText:text2=>theme.fg("accent",text2),description:text2=>theme.fg("muted",text2),scrollInfo:text2=>theme.fg("muted",text2),noMatch:text2=>theme.fg("muted",text2)}}function getEditorTheme(){return{borderColor:text2=>theme.fg("borderMuted",text2),selectList:getSelectListTheme()}}function getSettingsListTheme(){return{label:(text2,selected)=>selected?theme.fg("accent",text2):text2,value:(text2,selected)=>selected?theme.fg("accent",text2):theme.fg("muted",text2),description:text2=>theme.fg("dim",text2),cursor:theme.fg("accent","\u2192 "),hint:text2=>theme.fg("dim",text2)}}var DynamicBorder=class{constructor(color2=str2=>theme.fg("border",str2)){this.color=color2}invalidate(){}render(width){return[this.color("\u2500".repeat(Math.max(1,width)))]}};function formatKeyPart(part,options){let displayPart=process.platform==="darwin"&&part.toLowerCase()==="alt"?"option":part;return options.capitalize?displayPart.charAt(0).toUpperCase()+displayPart.slice(1):displayPart}function formatKeyText(key,options={}){return key.split("/").map(k2=>k2.split("+").map(part=>formatKeyPart(part,options)).join("+")).join("/")}function formatKeys(keys,options={}){return keys.length===0?"":formatKeyText(keys.join("/"),options)}function formatKeyLabelPart(part){switch(part.toLowerCase()){case"alt":return process.platform==="darwin"?"Option":"Alt";case"ctrl":return"Ctrl";case"shift":return"Shift";case"escape":case"esc":return"Esc";case"enter":case"return":return"Enter";case"space":return"Space";case"tab":return"Tab";case"left":return"\u2190";case"right":return"\u2192";case"up":return"\u2191";case"down":return"\u2193";case"pageup":return"PgUp";case"pagedown":return"PgDn";default:return part.length===1?part.toUpperCase():part.charAt(0).toUpperCase()+part.slice(1)}}function formatKeyLabel(key){if(!key)return"";let modifiers=[],remaining=key;for(;;){let match2=/^(ctrl|shift|alt)\+/i.exec(remaining);if(!match2)break;modifiers.push(formatKeyLabelPart(match2[1])),remaining=remaining.slice(match2[0].length)}let keyPart=formatKeyLabelPart(remaining||"+");return[...modifiers,keyPart].join("+")}function keyLabel(keybinding,options={}){let key=(options.keybindings??getKeybindings()).getKeys(keybinding)[0];return key!==void 0?formatKeyLabel(key):options.fallback?formatKeyLabel(options.fallback):""}function keyText(keybinding){return formatKeys(getKeybindings().getKeys(keybinding))}function keyDisplayText(keybinding){return formatKeys(getKeybindings().getKeys(keybinding),{capitalize:!0})}function keyHint(keybinding,description){return theme.fg("dim",keyText(keybinding))+theme.fg("muted",` ${description}`)}function rawKeyHint(key,description){return theme.fg("dim",formatKeyText(key))+theme.fg("muted",` ${description}`)}var CountdownTimer=class{constructor(timeoutMs,tui,onTick,onExpire){this.tui=tui,this.onTick=onTick,this.onExpire=onExpire,this.remainingSeconds=Math.ceil(timeoutMs/1e3),this.onTick(this.remainingSeconds),this.intervalId=setInterval(()=>{this.remainingSeconds--,this.onTick(this.remainingSeconds),this.tui?.requestRender(),this.remainingSeconds<=0&&(this.dispose(),this.onExpire())},1e3)}dispose(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0)}};var ExtensionInputComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.input.focused=value2}constructor(title,_placeholder,onSubmit,onCancel,opts){super(),this._focused=!1,this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",title),1,0),this.addChild(this.titleText),opts?.description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",opts.description),1,0))),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",`${this.baseTitle} (${s}s)`)),()=>this.onCancelCallback())),this.input=new Input,opts?.initialValue&&this.input.setValue(opts.initialValue),this.addChild(this.input),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyHint("tui.select.confirm","submit")} ${keyHint("tui.select.cancel","cancel")}`,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
642
642
|
`?this.onSubmitCallback(this.input.getValue()):kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():this.input.handleInput(keyData)}dispose(){this.countdown?.dispose()}};var ExtensionSelectorComponent=class extends Container{constructor(title,options,onSelect,onCancel,opts){super(),this.selectedIndex=0,this.options=options,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.onToggleToolsExpanded=opts?.onToggleToolsExpanded,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",theme.bold(title)),1,0),this.addChild(this.titleText),opts?.description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",opts.description),1,0))),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",theme.bold(`${this.baseTitle} (${s}s)`))),()=>this.onCancelCallback())),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1));let navigationKeys=[keyLabel("tui.select.up"),keyLabel("tui.select.down")].filter(Boolean).join("/"),confirmKey=keyLabel("tui.select.confirm"),cancelKey=keyLabel("tui.select.cancel"),hints=[navigationKeys?rawKeyHint(navigationKeys,"navigate"):"",confirmKey?rawKeyHint(confirmKey,"select"):"",cancelKey?rawKeyHint(cancelKey,"cancel"):""].filter(Boolean);this.addChild(new Text(hints.join(theme.fg("muted"," \u2022 ")),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}updateList(){this.listContainer.clear();for(let i=0;i<this.options.length;i++){let text2=i===this.selectedIndex?theme.fg("accent","\u2192 ")+theme.fg("accent",this.options[i]):` ${theme.fg("text",this.options[i])}`;this.listContainer.addChild(new Text(text2,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.tools.expand"))this.onToggleToolsExpanded?.();else if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.options.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
643
|
-
`){let selected=this.options[this.selectedIndex];selected&&this.onSelectCallback(selected)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}dispose(){this.countdown?.dispose()}};import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync8}from"node:fs";import{unlink}from"node:fs/promises";import*as os3 from"node:os";import{existsSync as existsSync7,readFileSync as readFileSync7}from"fs";import{join as join16}from"path";var registered={};function sameDefinition(left,right){return JSON.stringify(left)===JSON.stringify(right)}function registerKeybindings(definitions){for(let[id,definition]of Object.entries(definitions)){let existing=registered[id];if(existing&&!sameDefinition(existing,definition))throw new Error(`Keybinding ${id} is already registered with a different definition`);registered[id]=definition}}function getRegisteredKeybindings(){return{...registered}}function useWindowsKeybindings(platform3=process.platform,env2=process.env){return platform3==="win32"||platform3==="linux"&&!!(env2.WSL_DISTRO_NAME||env2.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.clipboard.pasteImage":{defaultKeys:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste image from clipboard (text fallback)"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}function toKeybindingsConfig(value2){let config={};for(let[key,binding]of Object.entries(value2)){if(typeof binding=="string"){config[key]=binding;continue}Array.isArray(binding)&&binding.every(entry=>typeof entry=="string")&&(config[key]=binding)}return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value2]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&Object.hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value2}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))Object.hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!Object.hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path14){if(existsSync7(path14))try{let parsed=JSON.parse(stripBom(readFileSync7(path14,"utf-8")));return typeof parsed!="object"||parsed===null?void 0:parsed}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super({...KEYBINDINGS,...getRegisteredKeybindings()},userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join16(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path14){let rawConfig=loadRawConfig(path14);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};function normalizeWhitespaceLower(text2){return text2.toLowerCase().replace(/\s+/g," ").trim()}function getSessionSearchText(session){return`${session.id} ${session.name??""} ${session.allMessagesText} ${session.cwd}`}function hasSessionName(session){return!!session.name?.trim()}function matchesNameFilter(session,filter2){return filter2==="all"?!0:hasSessionName(session)}function parseSearchQuery(query){let trimmed=query.trim();if(!trimmed)return{mode:"tokens",tokens:[],regex:null};if(trimmed.startsWith("re:")){let pattern=trimmed.slice(3).trim();if(!pattern)return{mode:"regex",tokens:[],regex:null,error:"Empty regex"};try{return{mode:"regex",tokens:[],regex:new RegExp(pattern,"i")}}catch(err2){let msg=err2 instanceof Error?err2.message:String(err2);return{mode:"regex",tokens:[],regex:null,error:msg}}}let tokens2=[],buf="",inQuote=!1,hadUnclosedQuote=!1,flush=kind=>{let v2=buf.trim();buf="",v2&&tokens2.push({kind,value:v2})};for(let i=0;i<trimmed.length;i++){let ch=trimmed[i];if(ch==='"'){inQuote?(flush("phrase"),inQuote=!1):(flush("fuzzy"),inQuote=!0);continue}if(!inQuote&&/\s/.test(ch)){flush("fuzzy");continue}buf+=ch}return inQuote&&(hadUnclosedQuote=!0),hadUnclosedQuote?{mode:"tokens",tokens:trimmed.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0).map(t=>({kind:"fuzzy",value:t})),regex:null}:(flush(inQuote?"phrase":"fuzzy"),{mode:"tokens",tokens:tokens2,regex:null})}function matchSession(session,parsed){let text2=getSessionSearchText(session);if(parsed.mode==="regex"){if(!parsed.regex)return{matches:!1,score:0};let idx=text2.search(parsed.regex);return idx<0?{matches:!1,score:0}:{matches:!0,score:idx*.1}}if(parsed.tokens.length===0)return{matches:!0,score:0};let totalScore=0,normalizedText=null;for(let token of parsed.tokens){if(token.kind==="phrase"){normalizedText===null&&(normalizedText=normalizeWhitespaceLower(text2));let phrase=normalizeWhitespaceLower(token.value);if(!phrase)continue;let idx=normalizedText.indexOf(phrase);if(idx<0)return{matches:!1,score:0};totalScore+=idx*.1;continue}let m2=fuzzyMatch(token.value,text2);if(!m2.matches)return{matches:!1,score:0};totalScore+=m2.score}return{matches:!0,score:totalScore}}function filterAndSortSessions(sessions,query,sortMode,nameFilter="all"){let nameFiltered=nameFilter==="all"?sessions:sessions.filter(session=>matchesNameFilter(session,nameFilter));if(!query.trim())return nameFiltered;let parsed=parseSearchQuery(query);if(parsed.error)return[];if(sortMode==="recent"){let filtered=[];for(let s of nameFiltered)matchSession(s,parsed).matches&&filtered.push(s);return filtered}let scored=[];for(let s of nameFiltered){let res=matchSession(s,parsed);res.matches&&scored.push({session:s,score:res.score})}return scored.sort((a,b2)=>a.score!==b2.score?a.score-b2.score:b2.session.modified.getTime()-a.session.modified.getTime()),scored.map(r=>r.session)}function shortenPath(path14){let home=os3.homedir();return path14&&(path14.startsWith(home)?`~${path14.slice(home.length)}`:path14)}function formatSessionDate(date){let diffMs=new Date().getTime()-date.getTime(),diffMins=Math.floor(diffMs/6e4),diffHours=Math.floor(diffMs/36e5),diffDays=Math.floor(diffMs/864e5);return diffMins<1?"now":diffMins<60?`${diffMins}m`:diffHours<24?`${diffHours}h`:diffDays<7?`${diffDays}d`:diffDays<30?`${Math.floor(diffDays/7)}w`:diffDays<365?`${Math.floor(diffDays/30)}mo`:`${Math.floor(diffDays/365)}y`}function canonicalizePath2(path14){return path14&&canonicalizePath(path14)}var SessionSelectorHeader=class{constructor(scope,sortMode,nameFilter,requestRender){this.loading=!1,this.loadProgress=null,this.showPath=!1,this.confirmingDeletePath=null,this.statusMessage=null,this.statusTimeout=null,this.showRenameHint=!1,this.scope=scope,this.sortMode=sortMode,this.nameFilter=nameFilter,this.requestRender=requestRender}setScope(scope){this.scope=scope}setSortMode(sortMode){this.sortMode=sortMode}setNameFilter(nameFilter){this.nameFilter=nameFilter}setLoading(loading){this.loading=loading,this.loadProgress=null}setProgress(loaded,total){this.loadProgress={loaded,total}}setShowPath(showPath){this.showPath=showPath}setShowRenameHint(show){this.showRenameHint=show}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14}clearStatusTimeout(){this.statusTimeout&&(clearTimeout(this.statusTimeout),this.statusTimeout=null)}setStatusMessage(msg,autoHideMs){this.clearStatusTimeout(),this.statusMessage=msg,!(!msg||!autoHideMs)&&(this.statusTimeout=setTimeout(()=>{this.statusMessage=null,this.statusTimeout=null,this.requestRender()},autoHideMs))}invalidate(){}render(width){let title=this.scope==="current"?"Resume Session (Current Folder)":"Resume Session (All)",leftText=theme.bold(title),sortLabel=this.sortMode==="threaded"?"Threaded":this.sortMode==="recent"?"Recent":"Fuzzy",sortText=theme.fg("muted","Sort: ")+theme.fg("accent",sortLabel),nameLabel=this.nameFilter==="all"?"All":"Named",nameText=theme.fg("muted","Name: ")+theme.fg("accent",nameLabel),scopeText;if(this.loading){let progressText=this.loadProgress?`${this.loadProgress.loaded}/${this.loadProgress.total}`:"...";scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent",`Loading ${progressText}`)}`}else this.scope==="current"?scopeText=`${theme.fg("accent","\u25C9 Current Folder")}${theme.fg("muted"," | \u25CB All")}`:scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent","\u25C9 All")}`;let rightText=truncateToWidth(`${scopeText} ${nameText} ${sortText}`,width,""),availableLeft=Math.max(0,width-visibleWidth(rightText)-1),left=truncateToWidth(leftText,availableLeft,""),spacing=Math.max(0,width-visibleWidth(left)-visibleWidth(rightText)),hintLine1,hintLine2;if(this.confirmingDeletePath!==null){let confirmHint=`Delete session? ${keyHint("tui.select.confirm","confirm")} \xB7 ${keyHint("tui.select.cancel","cancel")}`;hintLine1=theme.fg("error",truncateToWidth(confirmHint,width,"\u2026")),hintLine2=""}else if(this.statusMessage){let color2=this.statusMessage.type==="error"?"error":"accent";hintLine1=theme.fg(color2,truncateToWidth(this.statusMessage.message,width,"\u2026")),hintLine2=""}else{let pathState=this.showPath?"(on)":"(off)",sep12=theme.fg("muted"," \xB7 "),hint1=keyHint("tui.input.tab","scope")+sep12+theme.fg("muted",'re:<pattern> regex \xB7 "phrase" exact'),hint2Parts=[keyHint("app.session.toggleSort","sort"),keyHint("app.session.toggleNamedFilter","named"),keyHint("app.session.delete","delete"),keyHint("app.session.togglePath",`path ${pathState}`)];this.showRenameHint&&hint2Parts.push(keyHint("app.session.rename","rename"));let hint2=hint2Parts.join(sep12);hintLine1=truncateToWidth(hint1,width,"\u2026"),hintLine2=truncateToWidth(hint2,width,"\u2026")}return[`${left}${" ".repeat(spacing)}${rightText}`,hintLine1,hintLine2]}};function buildSessionTree(sessions){let byPath=new Map;for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path;byPath.set(sessionPath,{session,children:[],latestActivity:session.modified.getTime()})}let roots=[];for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path,node=byPath.get(sessionPath),parentPath=canonicalizePath2(session.parentSessionPath);parentPath&&byPath.has(parentPath)?byPath.get(parentPath).children.push(node):roots.push(node)}let updateLatestActivity=node=>{let latestActivity=node.session.modified.getTime();for(let child of node.children)latestActivity=Math.max(latestActivity,updateLatestActivity(child));return node.latestActivity=latestActivity,latestActivity};for(let root of roots)updateLatestActivity(root);let sortNodes=nodes=>{nodes.sort((a,b2)=>b2.latestActivity-a.latestActivity);for(let node of nodes)sortNodes(node.children)};return sortNodes(roots),roots}function flattenSessionTree(roots){let result2=[],walk=(node,depth,ancestorContinues,isLast)=>{result2.push({session:node.session,depth,isLast,ancestorContinues});for(let i=0;i<node.children.length;i++){let childIsLast=i===node.children.length-1,continues=depth>0?!isLast:!1;walk(node.children[i],depth+1,[...ancestorContinues,continues],childIsLast)}};for(let i=0;i<roots.length;i++)walk(roots[i],0,[],i===roots.length-1);return result2}var SessionList=class{getSelectedSessionPath(){return this.filteredSessions[this.selectedIndex]?.session.path}get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(sessions,showCwd,sortMode,nameFilter,keybindings,currentSessionFilePath){this.allSessions=[],this.filteredSessions=[],this.selectedIndex=0,this.selectionTouched=!1,this.showCwd=!1,this.sortMode="threaded",this.nameFilter="all",this.showPath=!1,this.confirmingDeletePath=null,this.onExit=()=>{},this.maxVisible=10,this._focused=!1,this.allSessions=sessions,this.filteredSessions=[],this.searchInput=new Input,this.showCwd=showCwd,this.sortMode=sortMode,this.nameFilter=nameFilter,this.keybindings=keybindings,this.currentSessionCanonicalPath=canonicalizePath2(currentSessionFilePath),this.filterSessions(""),this.searchInput.onSubmit=()=>{if(this.filteredSessions[this.selectedIndex]){let selected=this.filteredSessions[this.selectedIndex];this.onSelect&&this.onSelect(selected.session.path)}}}setSortMode(sortMode){this.sortMode=sortMode,this.filterSessions(this.searchInput.getValue())}setNameFilter(nameFilter){this.nameFilter=nameFilter,this.filterSessions(this.searchInput.getValue())}setSessions(sessions,showCwd){let selectedPath=this.selectionTouched?this.getSelectedSessionPath():void 0;if(this.allSessions=sessions,this.showCwd=showCwd,this.filterSessions(this.searchInput.getValue()),!this.selectionTouched)this.selectedIndex=0;else if(selectedPath){let selectedIndex=this.filteredSessions.findIndex(node=>node.session.path===selectedPath);selectedIndex>=0&&(this.selectedIndex=selectedIndex)}}filterSessions(query){let trimmed=query.trim(),nameFiltered=this.nameFilter==="all"?this.allSessions:this.allSessions.filter(session=>hasSessionName(session));if(this.sortMode==="threaded"&&!trimmed){let roots=buildSessionTree(nameFiltered);this.filteredSessions=flattenSessionTree(roots)}else{let filtered=filterAndSortSessions(nameFiltered,query,this.sortMode,"all");this.filteredSessions=filtered.map(session=>({session,depth:0,isLast:!0,ancestorContinues:[]}))}this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredSessions.length-1))}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14,this.onDeleteConfirmationChange?.(path14)}startDeleteConfirmationForSelectedSession(){let selected=this.filteredSessions[this.selectedIndex];if(selected){if(this.isCurrentSessionPath(selected.session.path)){this.onError?.("Cannot delete the currently active session");return}this.setConfirmingDeletePath(selected.session.path)}}isCurrentSessionPath(path14){return this.currentSessionCanonicalPath?(canonicalizePath2(path14)??path14)===this.currentSessionCanonicalPath:!1}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredSessions.length===0){let emptyMessage;if(this.nameFilter==="named"){let toggleKey=keyText("app.session.toggleNamedFilter");this.showCwd?emptyMessage=` No named sessions found. Press ${toggleKey} to show all.`:emptyMessage=` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`}else this.showCwd?emptyMessage=" No sessions found":emptyMessage=" No sessions in current folder. Press Tab to view all.";return lines.push(theme.fg("muted",truncateToWidth(emptyMessage,width,"\u2026"))),lines}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredSessions.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredSessions.length);for(let i=startIndex;i<endIndex;i++){let node=this.filteredSessions[i],session=node.session,isSelected=i===this.selectedIndex,isConfirmingDelete=session.path===this.confirmingDeletePath,isCurrent=this.isCurrentSessionPath(session.path),prefix=this.buildTreePrefix(node),hasName=!!session.name,normalizedMessage=(session.name??session.firstMessage).replace(/[\x00-\x1f\x7f]/g," ").trim(),age=formatSessionDate(session.modified),rightPart=`${String(session.messageCount)} ${age}`;this.showCwd&&session.cwd&&(rightPart=`${shortenPath(session.cwd)} ${rightPart}`),this.showPath&&(rightPart=`${shortenPath(session.path)} ${rightPart}`);let cursor=isSelected?theme.fg("accent","\u203A "):" ",prefixWidth=visibleWidth(prefix),rightWidth=visibleWidth(rightPart)+2,availableForMsg=width-2-prefixWidth-rightWidth,truncatedMsg=truncateToWidth(normalizedMessage,Math.max(10,availableForMsg),"\u2026"),messageColor=null;isConfirmingDelete?messageColor="error":isCurrent?messageColor="accent":hasName&&(messageColor="warning");let styledMsg=messageColor?theme.fg(messageColor,truncatedMsg):truncatedMsg;isSelected&&(styledMsg=theme.bold(styledMsg));let leftPart=cursor+theme.fg("dim",prefix)+styledMsg,leftWidth=visibleWidth(leftPart),spacing=Math.max(1,width-leftWidth-visibleWidth(rightPart)),styledRight=theme.fg(isConfirmingDelete?"error":"dim",rightPart),line=leftPart+" ".repeat(spacing)+styledRight;isSelected&&(line=theme.bg("selectedBg",line)),lines.push(truncateToWidth(line,width))}if(startIndex>0||endIndex<this.filteredSessions.length){let scrollText=` (${this.selectedIndex+1}/${this.filteredSessions.length})`,scrollInfo=theme.fg("muted",truncateToWidth(scrollText,width,""));lines.push(scrollInfo)}return lines}buildTreePrefix(node){if(node.depth===0)return"";let parts=node.ancestorContinues.map(continues=>continues?"\u2502 ":" "),branch=node.isLast?"\u2514\u2500 ":"\u251C\u2500 ";return parts.join("")+branch}handleInput(keyData){let kb=getKeybindings();if(this.confirmingDeletePath!==null){if(kb.matches(keyData,"tui.select.confirm")){let pathToDelete=this.confirmingDeletePath;this.setConfirmingDeletePath(null),this.onDeleteSession?.(pathToDelete);return}if(kb.matches(keyData,"tui.select.cancel")){this.setConfirmingDeletePath(null);return}return}if(kb.matches(keyData,"tui.input.tab")){this.onToggleScope&&this.onToggleScope();return}if(kb.matches(keyData,"app.session.toggleSort")){this.onToggleSort?.();return}if(this.keybindings.matches(keyData,"app.session.toggleNamedFilter")){this.onToggleNameFilter?.();return}if(kb.matches(keyData,"app.session.togglePath")){this.showPath=!this.showPath,this.onTogglePath?.(this.showPath);return}if(kb.matches(keyData,"app.session.delete")){this.startDeleteConfirmationForSelectedSession();return}if(kb.matches(keyData,"app.session.rename")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onRenameSession?.(selected.session.path);return}if(kb.matches(keyData,"app.session.deleteNoninvasive")){if(this.searchInput.getValue().length>0){this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue());return}this.startDeleteConfirmationForSelectedSession();return}if(this.selectionTouched=!0,kb.matches(keyData,"tui.select.up"))this.selectedIndex=Math.max(0,this.selectedIndex-1);else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+1);else if(kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisible);else if(kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+this.maxVisible);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.session.path)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel&&this.onCancel():(this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue()))}};async function deleteSessionFile(sessionPath){let trashArgs=sessionPath.startsWith("-")?["--",sessionPath]:[sessionPath],trashResult=spawnSync3("trash",trashArgs,{encoding:"utf-8"}),getTrashErrorHint=()=>{let parts=[];trashResult.error&&parts.push(trashResult.error.message);let stderr=trashResult.stderr?.trim();return stderr&&parts.push(stderr.split(`
|
|
643
|
+
`){let selected=this.options[this.selectedIndex];selected&&this.onSelectCallback(selected)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}dispose(){this.countdown?.dispose()}};import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync8}from"node:fs";import{unlink}from"node:fs/promises";import*as os3 from"node:os";import{existsSync as existsSync7,readFileSync as readFileSync7}from"fs";import{join as join16}from"path";var registered={};function sameDefinition(left,right){return JSON.stringify(left)===JSON.stringify(right)}function registerKeybindings(definitions){for(let[id,definition]of Object.entries(definitions)){let existing=registered[id];if(existing&&!sameDefinition(existing,definition))throw new Error(`Keybinding ${id} is already registered with a different definition`);registered[id]=definition}}function getRegisteredKeybindings(){return{...registered}}function useWindowsKeybindings(platform3=process.platform,env2=process.env){return platform3==="win32"||platform3==="linux"&&!!(env2.WSL_DISTRO_NAME||env2.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.question.pageUp":{defaultKeys:"alt+up",description:"Page up in question details"},"app.question.pageDown":{defaultKeys:"alt+down",description:"Page down in question details"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.clipboard.pasteImage":{defaultKeys:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste image from clipboard (text fallback)"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}function toKeybindingsConfig(value2){let config={};for(let[key,binding]of Object.entries(value2)){if(typeof binding=="string"){config[key]=binding;continue}Array.isArray(binding)&&binding.every(entry=>typeof entry=="string")&&(config[key]=binding)}return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value2]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&Object.hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value2}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))Object.hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!Object.hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path14){if(existsSync7(path14))try{let parsed=JSON.parse(stripBom(readFileSync7(path14,"utf-8")));return typeof parsed!="object"||parsed===null?void 0:parsed}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super({...KEYBINDINGS,...getRegisteredKeybindings()},userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join16(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path14){let rawConfig=loadRawConfig(path14);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};function normalizeWhitespaceLower(text2){return text2.toLowerCase().replace(/\s+/g," ").trim()}function getSessionSearchText(session){return`${session.id} ${session.name??""} ${session.allMessagesText} ${session.cwd}`}function hasSessionName(session){return!!session.name?.trim()}function matchesNameFilter(session,filter2){return filter2==="all"?!0:hasSessionName(session)}function parseSearchQuery(query){let trimmed=query.trim();if(!trimmed)return{mode:"tokens",tokens:[],regex:null};if(trimmed.startsWith("re:")){let pattern=trimmed.slice(3).trim();if(!pattern)return{mode:"regex",tokens:[],regex:null,error:"Empty regex"};try{return{mode:"regex",tokens:[],regex:new RegExp(pattern,"i")}}catch(err2){let msg=err2 instanceof Error?err2.message:String(err2);return{mode:"regex",tokens:[],regex:null,error:msg}}}let tokens2=[],buf="",inQuote=!1,hadUnclosedQuote=!1,flush=kind=>{let v2=buf.trim();buf="",v2&&tokens2.push({kind,value:v2})};for(let i=0;i<trimmed.length;i++){let ch=trimmed[i];if(ch==='"'){inQuote?(flush("phrase"),inQuote=!1):(flush("fuzzy"),inQuote=!0);continue}if(!inQuote&&/\s/.test(ch)){flush("fuzzy");continue}buf+=ch}return inQuote&&(hadUnclosedQuote=!0),hadUnclosedQuote?{mode:"tokens",tokens:trimmed.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0).map(t=>({kind:"fuzzy",value:t})),regex:null}:(flush(inQuote?"phrase":"fuzzy"),{mode:"tokens",tokens:tokens2,regex:null})}function matchSession(session,parsed){let text2=getSessionSearchText(session);if(parsed.mode==="regex"){if(!parsed.regex)return{matches:!1,score:0};let idx=text2.search(parsed.regex);return idx<0?{matches:!1,score:0}:{matches:!0,score:idx*.1}}if(parsed.tokens.length===0)return{matches:!0,score:0};let totalScore=0,normalizedText=null;for(let token of parsed.tokens){if(token.kind==="phrase"){normalizedText===null&&(normalizedText=normalizeWhitespaceLower(text2));let phrase=normalizeWhitespaceLower(token.value);if(!phrase)continue;let idx=normalizedText.indexOf(phrase);if(idx<0)return{matches:!1,score:0};totalScore+=idx*.1;continue}let m2=fuzzyMatch(token.value,text2);if(!m2.matches)return{matches:!1,score:0};totalScore+=m2.score}return{matches:!0,score:totalScore}}function filterAndSortSessions(sessions,query,sortMode,nameFilter="all"){let nameFiltered=nameFilter==="all"?sessions:sessions.filter(session=>matchesNameFilter(session,nameFilter));if(!query.trim())return nameFiltered;let parsed=parseSearchQuery(query);if(parsed.error)return[];if(sortMode==="recent"){let filtered=[];for(let s of nameFiltered)matchSession(s,parsed).matches&&filtered.push(s);return filtered}let scored=[];for(let s of nameFiltered){let res=matchSession(s,parsed);res.matches&&scored.push({session:s,score:res.score})}return scored.sort((a,b2)=>a.score!==b2.score?a.score-b2.score:b2.session.modified.getTime()-a.session.modified.getTime()),scored.map(r=>r.session)}function shortenPath(path14){let home=os3.homedir();return path14&&(path14.startsWith(home)?`~${path14.slice(home.length)}`:path14)}function formatSessionDate(date){let diffMs=new Date().getTime()-date.getTime(),diffMins=Math.floor(diffMs/6e4),diffHours=Math.floor(diffMs/36e5),diffDays=Math.floor(diffMs/864e5);return diffMins<1?"now":diffMins<60?`${diffMins}m`:diffHours<24?`${diffHours}h`:diffDays<7?`${diffDays}d`:diffDays<30?`${Math.floor(diffDays/7)}w`:diffDays<365?`${Math.floor(diffDays/30)}mo`:`${Math.floor(diffDays/365)}y`}function canonicalizePath2(path14){return path14&&canonicalizePath(path14)}var SessionSelectorHeader=class{constructor(scope,sortMode,nameFilter,requestRender){this.loading=!1,this.loadProgress=null,this.showPath=!1,this.confirmingDeletePath=null,this.statusMessage=null,this.statusTimeout=null,this.showRenameHint=!1,this.scope=scope,this.sortMode=sortMode,this.nameFilter=nameFilter,this.requestRender=requestRender}setScope(scope){this.scope=scope}setSortMode(sortMode){this.sortMode=sortMode}setNameFilter(nameFilter){this.nameFilter=nameFilter}setLoading(loading){this.loading=loading,this.loadProgress=null}setProgress(loaded,total){this.loadProgress={loaded,total}}setShowPath(showPath){this.showPath=showPath}setShowRenameHint(show){this.showRenameHint=show}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14}clearStatusTimeout(){this.statusTimeout&&(clearTimeout(this.statusTimeout),this.statusTimeout=null)}setStatusMessage(msg,autoHideMs){this.clearStatusTimeout(),this.statusMessage=msg,!(!msg||!autoHideMs)&&(this.statusTimeout=setTimeout(()=>{this.statusMessage=null,this.statusTimeout=null,this.requestRender()},autoHideMs))}invalidate(){}render(width){let title=this.scope==="current"?"Resume Session (Current Folder)":"Resume Session (All)",leftText=theme.bold(title),sortLabel=this.sortMode==="threaded"?"Threaded":this.sortMode==="recent"?"Recent":"Fuzzy",sortText=theme.fg("muted","Sort: ")+theme.fg("accent",sortLabel),nameLabel=this.nameFilter==="all"?"All":"Named",nameText=theme.fg("muted","Name: ")+theme.fg("accent",nameLabel),scopeText;if(this.loading){let progressText=this.loadProgress?`${this.loadProgress.loaded}/${this.loadProgress.total}`:"...";scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent",`Loading ${progressText}`)}`}else this.scope==="current"?scopeText=`${theme.fg("accent","\u25C9 Current Folder")}${theme.fg("muted"," | \u25CB All")}`:scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent","\u25C9 All")}`;let rightText=truncateToWidth(`${scopeText} ${nameText} ${sortText}`,width,""),availableLeft=Math.max(0,width-visibleWidth(rightText)-1),left=truncateToWidth(leftText,availableLeft,""),spacing=Math.max(0,width-visibleWidth(left)-visibleWidth(rightText)),hintLine1,hintLine2;if(this.confirmingDeletePath!==null){let confirmHint=`Delete session? ${keyHint("tui.select.confirm","confirm")} \xB7 ${keyHint("tui.select.cancel","cancel")}`;hintLine1=theme.fg("error",truncateToWidth(confirmHint,width,"\u2026")),hintLine2=""}else if(this.statusMessage){let color2=this.statusMessage.type==="error"?"error":"accent";hintLine1=theme.fg(color2,truncateToWidth(this.statusMessage.message,width,"\u2026")),hintLine2=""}else{let pathState=this.showPath?"(on)":"(off)",sep12=theme.fg("muted"," \xB7 "),hint1=keyHint("tui.input.tab","scope")+sep12+theme.fg("muted",'re:<pattern> regex \xB7 "phrase" exact'),hint2Parts=[keyHint("app.session.toggleSort","sort"),keyHint("app.session.toggleNamedFilter","named"),keyHint("app.session.delete","delete"),keyHint("app.session.togglePath",`path ${pathState}`)];this.showRenameHint&&hint2Parts.push(keyHint("app.session.rename","rename"));let hint2=hint2Parts.join(sep12);hintLine1=truncateToWidth(hint1,width,"\u2026"),hintLine2=truncateToWidth(hint2,width,"\u2026")}return[`${left}${" ".repeat(spacing)}${rightText}`,hintLine1,hintLine2]}};function buildSessionTree(sessions){let byPath=new Map;for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path;byPath.set(sessionPath,{session,children:[],latestActivity:session.modified.getTime()})}let roots=[];for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path,node=byPath.get(sessionPath),parentPath=canonicalizePath2(session.parentSessionPath);parentPath&&byPath.has(parentPath)?byPath.get(parentPath).children.push(node):roots.push(node)}let updateLatestActivity=node=>{let latestActivity=node.session.modified.getTime();for(let child of node.children)latestActivity=Math.max(latestActivity,updateLatestActivity(child));return node.latestActivity=latestActivity,latestActivity};for(let root of roots)updateLatestActivity(root);let sortNodes=nodes=>{nodes.sort((a,b2)=>b2.latestActivity-a.latestActivity);for(let node of nodes)sortNodes(node.children)};return sortNodes(roots),roots}function flattenSessionTree(roots){let result2=[],walk=(node,depth,ancestorContinues,isLast)=>{result2.push({session:node.session,depth,isLast,ancestorContinues});for(let i=0;i<node.children.length;i++){let childIsLast=i===node.children.length-1,continues=depth>0?!isLast:!1;walk(node.children[i],depth+1,[...ancestorContinues,continues],childIsLast)}};for(let i=0;i<roots.length;i++)walk(roots[i],0,[],i===roots.length-1);return result2}var SessionList=class{getSelectedSessionPath(){return this.filteredSessions[this.selectedIndex]?.session.path}get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(sessions,showCwd,sortMode,nameFilter,keybindings,currentSessionFilePath){this.allSessions=[],this.filteredSessions=[],this.selectedIndex=0,this.selectionTouched=!1,this.showCwd=!1,this.sortMode="threaded",this.nameFilter="all",this.showPath=!1,this.confirmingDeletePath=null,this.onExit=()=>{},this.maxVisible=10,this._focused=!1,this.allSessions=sessions,this.filteredSessions=[],this.searchInput=new Input,this.showCwd=showCwd,this.sortMode=sortMode,this.nameFilter=nameFilter,this.keybindings=keybindings,this.currentSessionCanonicalPath=canonicalizePath2(currentSessionFilePath),this.filterSessions(""),this.searchInput.onSubmit=()=>{if(this.filteredSessions[this.selectedIndex]){let selected=this.filteredSessions[this.selectedIndex];this.onSelect&&this.onSelect(selected.session.path)}}}setSortMode(sortMode){this.sortMode=sortMode,this.filterSessions(this.searchInput.getValue())}setNameFilter(nameFilter){this.nameFilter=nameFilter,this.filterSessions(this.searchInput.getValue())}setSessions(sessions,showCwd){let selectedPath=this.selectionTouched?this.getSelectedSessionPath():void 0;if(this.allSessions=sessions,this.showCwd=showCwd,this.filterSessions(this.searchInput.getValue()),!this.selectionTouched)this.selectedIndex=0;else if(selectedPath){let selectedIndex=this.filteredSessions.findIndex(node=>node.session.path===selectedPath);selectedIndex>=0&&(this.selectedIndex=selectedIndex)}}filterSessions(query){let trimmed=query.trim(),nameFiltered=this.nameFilter==="all"?this.allSessions:this.allSessions.filter(session=>hasSessionName(session));if(this.sortMode==="threaded"&&!trimmed){let roots=buildSessionTree(nameFiltered);this.filteredSessions=flattenSessionTree(roots)}else{let filtered=filterAndSortSessions(nameFiltered,query,this.sortMode,"all");this.filteredSessions=filtered.map(session=>({session,depth:0,isLast:!0,ancestorContinues:[]}))}this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredSessions.length-1))}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14,this.onDeleteConfirmationChange?.(path14)}startDeleteConfirmationForSelectedSession(){let selected=this.filteredSessions[this.selectedIndex];if(selected){if(this.isCurrentSessionPath(selected.session.path)){this.onError?.("Cannot delete the currently active session");return}this.setConfirmingDeletePath(selected.session.path)}}isCurrentSessionPath(path14){return this.currentSessionCanonicalPath?(canonicalizePath2(path14)??path14)===this.currentSessionCanonicalPath:!1}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredSessions.length===0){let emptyMessage;if(this.nameFilter==="named"){let toggleKey=keyText("app.session.toggleNamedFilter");this.showCwd?emptyMessage=` No named sessions found. Press ${toggleKey} to show all.`:emptyMessage=` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`}else this.showCwd?emptyMessage=" No sessions found":emptyMessage=" No sessions in current folder. Press Tab to view all.";return lines.push(theme.fg("muted",truncateToWidth(emptyMessage,width,"\u2026"))),lines}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredSessions.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredSessions.length);for(let i=startIndex;i<endIndex;i++){let node=this.filteredSessions[i],session=node.session,isSelected=i===this.selectedIndex,isConfirmingDelete=session.path===this.confirmingDeletePath,isCurrent=this.isCurrentSessionPath(session.path),prefix=this.buildTreePrefix(node),hasName=!!session.name,normalizedMessage=(session.name??session.firstMessage).replace(/[\x00-\x1f\x7f]/g," ").trim(),age=formatSessionDate(session.modified),rightPart=`${String(session.messageCount)} ${age}`;this.showCwd&&session.cwd&&(rightPart=`${shortenPath(session.cwd)} ${rightPart}`),this.showPath&&(rightPart=`${shortenPath(session.path)} ${rightPart}`);let cursor=isSelected?theme.fg("accent","\u203A "):" ",prefixWidth=visibleWidth(prefix),rightWidth=visibleWidth(rightPart)+2,availableForMsg=width-2-prefixWidth-rightWidth,truncatedMsg=truncateToWidth(normalizedMessage,Math.max(10,availableForMsg),"\u2026"),messageColor=null;isConfirmingDelete?messageColor="error":isCurrent?messageColor="accent":hasName&&(messageColor="warning");let styledMsg=messageColor?theme.fg(messageColor,truncatedMsg):truncatedMsg;isSelected&&(styledMsg=theme.bold(styledMsg));let leftPart=cursor+theme.fg("dim",prefix)+styledMsg,leftWidth=visibleWidth(leftPart),spacing=Math.max(1,width-leftWidth-visibleWidth(rightPart)),styledRight=theme.fg(isConfirmingDelete?"error":"dim",rightPart),line=leftPart+" ".repeat(spacing)+styledRight;isSelected&&(line=theme.bg("selectedBg",line)),lines.push(truncateToWidth(line,width))}if(startIndex>0||endIndex<this.filteredSessions.length){let scrollText=` (${this.selectedIndex+1}/${this.filteredSessions.length})`,scrollInfo=theme.fg("muted",truncateToWidth(scrollText,width,""));lines.push(scrollInfo)}return lines}buildTreePrefix(node){if(node.depth===0)return"";let parts=node.ancestorContinues.map(continues=>continues?"\u2502 ":" "),branch=node.isLast?"\u2514\u2500 ":"\u251C\u2500 ";return parts.join("")+branch}handleInput(keyData){let kb=getKeybindings();if(this.confirmingDeletePath!==null){if(kb.matches(keyData,"tui.select.confirm")){let pathToDelete=this.confirmingDeletePath;this.setConfirmingDeletePath(null),this.onDeleteSession?.(pathToDelete);return}if(kb.matches(keyData,"tui.select.cancel")){this.setConfirmingDeletePath(null);return}return}if(kb.matches(keyData,"tui.input.tab")){this.onToggleScope&&this.onToggleScope();return}if(kb.matches(keyData,"app.session.toggleSort")){this.onToggleSort?.();return}if(this.keybindings.matches(keyData,"app.session.toggleNamedFilter")){this.onToggleNameFilter?.();return}if(kb.matches(keyData,"app.session.togglePath")){this.showPath=!this.showPath,this.onTogglePath?.(this.showPath);return}if(kb.matches(keyData,"app.session.delete")){this.startDeleteConfirmationForSelectedSession();return}if(kb.matches(keyData,"app.session.rename")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onRenameSession?.(selected.session.path);return}if(kb.matches(keyData,"app.session.deleteNoninvasive")){if(this.searchInput.getValue().length>0){this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue());return}this.startDeleteConfirmationForSelectedSession();return}if(this.selectionTouched=!0,kb.matches(keyData,"tui.select.up"))this.selectedIndex=Math.max(0,this.selectedIndex-1);else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+1);else if(kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisible);else if(kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+this.maxVisible);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.session.path)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel&&this.onCancel():(this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue()))}};async function deleteSessionFile(sessionPath){let trashArgs=sessionPath.startsWith("-")?["--",sessionPath]:[sessionPath],trashResult=spawnSync3("trash",trashArgs,{encoding:"utf-8"}),getTrashErrorHint=()=>{let parts=[];trashResult.error&&parts.push(trashResult.error.message);let stderr=trashResult.stderr?.trim();return stderr&&parts.push(stderr.split(`
|
|
644
644
|
`)[0]??stderr),parts.length===0?null:`trash: ${parts.join(" \xB7 ").slice(0,200)}`};if(trashResult.status===0||!existsSync8(sessionPath))return{ok:!0,method:"trash"};try{return await unlink(sessionPath),{ok:!0,method:"unlink"}}catch(err2){let unlinkError=err2 instanceof Error?err2.message:String(err2),trashErrorHint=getTrashErrorHint();return{ok:!1,method:"unlink",error:trashErrorHint?`${unlinkError} (${trashErrorHint})`:unlinkError}}}var SessionSelectorComponent=class extends Container{handleInput(data){if(this.mode==="rename"){if(getKeybindings().matches(data,"tui.select.cancel")){this.exitRenameMode();return}this.renameInput.handleInput(data);return}this.sessionList.handleInput(data)}get focused(){return this._focused}set focused(value2){this._focused=value2,this.sessionList.focused=value2,this.renameInput.focused=value2,value2&&this.mode==="rename"&&(this.renameInput.focused=!0)}buildBaseLayout(content,options){this.clear(),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s))),this.addChild(new Spacer(1)),(options?.showHeader??!0)&&(this.addChild(this.header),this.addChild(new Spacer(1))),this.addChild(content),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s)))}constructor(currentSessionsLoader,allSessionsLoader,onSelect,onCancel,onExit,requestRender,options,currentSessionFilePath){super(),this.canRename=!0,this.scope="current",this.sortMode="threaded",this.nameFilter="all",this.currentSessions=null,this.allSessions=null,this.currentLoad=null,this.allLoad=null,this.mode="list",this.renameInput=new Input,this.renameTargetPath=null,this._focused=!1,this.keybindings=options?.keybindings??KeybindingsManager2.create(),this.currentSessionsLoader=currentSessionsLoader,this.allSessionsLoader=allSessionsLoader,this.requestRender=requestRender,this.header=new SessionSelectorHeader(this.scope,this.sortMode,this.nameFilter,this.requestRender);let renameSession=options?.renameSession;this.renameSession=renameSession,this.canRename=!!renameSession,this.header.setShowRenameHint(options?.showRenameHint??this.canRename),this.sessionList=new SessionList([],!1,this.sortMode,this.nameFilter,this.keybindings,currentSessionFilePath),this.buildBaseLayout(this.sessionList),this.renameInput.onSubmit=value2=>{this.confirmRename(value2)};let clearStatusMessage=()=>this.header.setStatusMessage(null);this.sessionList.onSelect=sessionPath=>{clearStatusMessage(),this.cancelLoads(),onSelect(sessionPath)},this.sessionList.onCancel=()=>{clearStatusMessage(),this.cancelLoads(),onCancel()},this.sessionList.onExit=()=>{clearStatusMessage(),this.cancelLoads(),onExit()},this.sessionList.onToggleScope=()=>this.toggleScope(),this.sessionList.onToggleSort=()=>this.toggleSortMode(),this.sessionList.onToggleNameFilter=()=>this.toggleNameFilter(),this.sessionList.onRenameSession=sessionPath=>{if(!renameSession||(this.scope==="current"?this.currentLoad:this.allLoad))return;let session=(this.scope==="all"?this.allSessions??[]:this.currentSessions??[]).find(s=>s.path===sessionPath);this.enterRenameMode(sessionPath,session?.name)},this.sessionList.onTogglePath=showPath=>{this.header.setShowPath(showPath),this.requestRender()},this.sessionList.onDeleteConfirmationChange=path14=>{this.header.setConfirmingDeletePath(path14),this.requestRender()},this.sessionList.onError=msg=>{this.header.setStatusMessage({type:"error",message:msg},3e3),this.requestRender()},this.sessionList.onDeleteSession=async sessionPath=>{let result2=await deleteSessionFile(sessionPath);if(result2.ok){this.currentSessions&&(this.currentSessions=this.currentSessions.filter(s=>s.path!==sessionPath)),this.allSessions&&(this.allSessions=this.allSessions.filter(s=>s.path!==sessionPath));let sessions=this.scope==="all"?this.allSessions??[]:this.currentSessions??[],showCwd=this.scope==="all";this.sessionList.setSessions(sessions,showCwd);let msg=result2.method==="trash"?"Session moved to trash":"Session deleted";this.header.setStatusMessage({type:"info",message:msg},2e3),await this.refreshSessionsAfterMutation()}else{let errorMessage6=result2.error??"Unknown error";this.header.setStatusMessage({type:"error",message:`Failed to delete: ${errorMessage6}`},3e3)}this.requestRender()},this.loadScope("current")}cancelLoads(){this.currentLoad&&(this.currentLoad.abort(),this.currentLoad=null,this.currentSessions=null),this.allLoad&&(this.allLoad.abort(),this.allLoad=null,this.allSessions=null)}enterRenameMode(sessionPath,currentName){this.mode="rename",this.renameTargetPath=sessionPath,this.renameInput.setValue(currentName??""),this.renameInput.focused=!0;let panel=new Container;panel.addChild(new Text(theme.bold("Rename Session"),1,0)),panel.addChild(new Spacer(1)),panel.addChild(this.renameInput),panel.addChild(new Spacer(1)),panel.addChild(new Text(theme.fg("muted",`${keyText("tui.select.confirm")} to save \xB7 ${keyText("tui.select.cancel")} to cancel`),1,0)),this.buildBaseLayout(panel,{showHeader:!1}),this.requestRender()}exitRenameMode(){this.mode="list",this.renameTargetPath=null,this.buildBaseLayout(this.sessionList),this.requestRender()}async confirmRename(value2){let next=value2.trim();if(!next)return;let target=this.renameTargetPath;if(!target){this.exitRenameMode();return}let renameSession=this.renameSession;if(!renameSession){this.exitRenameMode();return}try{await renameSession(target,next),await this.refreshSessionsAfterMutation()}finally{this.exitRenameMode()}}async loadScope(scope){if(scope==="current"?this.currentLoad:this.allLoad)return;let showCwd=scope==="all",controller=new AbortController;scope==="current"?this.currentLoad=controller:this.allLoad=controller,this.header.setScope(scope),this.header.setLoading(!0),this.requestRender();let isActive=()=>(scope==="current"?this.currentLoad:this.allLoad)===controller,onProgress=(loaded,total,partialSessions)=>{if(isActive()){if(partialSessions){let sessions=[...partialSessions];scope==="current"?this.currentSessions=sessions:this.allSessions=sessions,scope===this.scope&&this.sessionList.setSessions(sessions,showCwd)}scope===this.scope&&(this.header.setProgress(loaded,total),this.requestRender())}};try{let sessions=await(scope==="current"?this.currentSessionsLoader(onProgress,controller.signal):this.allSessionsLoader(onProgress,controller.signal));if(!isActive()||(scope==="current"?(this.currentSessions=sessions,this.currentLoad=null):(this.allSessions=sessions,this.allLoad=null),scope!==this.scope))return;this.header.setLoading(!1),this.sessionList.setSessions(sessions,showCwd),this.requestRender()}catch(err2){if(!isActive()||(scope==="current"?(this.currentLoad=null,this.currentSessions=null):(this.allLoad=null,this.allSessions=null),scope!==this.scope))return;let message=err2 instanceof Error?err2.message:String(err2);this.header.setLoading(!1),this.header.setStatusMessage({type:"error",message:`Failed to load sessions: ${message}`},4e3),this.sessionList.setSessions([],showCwd),this.requestRender()}}toggleSortMode(){this.sortMode=this.sortMode==="threaded"?"recent":this.sortMode==="recent"?"relevance":"threaded",this.header.setSortMode(this.sortMode),this.sessionList.setSortMode(this.sortMode),this.requestRender()}toggleNameFilter(){this.nameFilter=this.nameFilter==="all"?"named":"all",this.header.setNameFilter(this.nameFilter),this.sessionList.setNameFilter(this.nameFilter),this.requestRender()}async refreshSessionsAfterMutation(){this.cancelLoads(),this.currentSessions=null,this.allSessions=null,await this.loadScope(this.scope)}toggleScope(){this.scope=this.scope==="current"?"all":"current";let sessions=this.scope==="current"?this.currentSessions:this.allSessions,loading=(this.scope==="current"?this.currentLoad:this.allLoad)!==null;this.header.setScope(this.scope),this.header.setLoading(loading),this.sessionList.setSessions(sessions??[],this.scope==="all"),this.requestRender(),sessions===null&&!loading&&this.loadScope(this.scope)}getSessionList(){return this.sessionList}};var DEFAULT_MAX_LINES=2e3,DEFAULT_MAX_BYTES2=51200;function splitLinesForCounting(content){if(content.length===0)return[];let lines=content.split(`
|
|
645
645
|
`);return content.endsWith(`
|
|
646
646
|
`)&&lines.pop(),lines}function formatSize(bytes){return bytes<1024?`${bytes}B`:bytes<1024*1024?`${(bytes/1024).toFixed(1)}KB`:`${(bytes/(1024*1024)).toFixed(1)}MB`}function truncateHead(content,options={}){let maxLines=options.maxLines??2e3,maxBytes=options.maxBytes??51200,totalBytes=Buffer.byteLength(content,"utf-8"),lines=splitLinesForCounting(content),totalLines=lines.length;if(totalLines<=maxLines&&totalBytes<=maxBytes)return{content,truncated:!1,truncatedBy:null,totalLines,totalBytes,outputLines:totalLines,outputBytes:totalBytes,lastLinePartial:!1,firstLineExceedsLimit:!1,maxLines,maxBytes};if(Buffer.byteLength(lines[0],"utf-8")>maxBytes)return{content:"",truncated:!0,truncatedBy:"bytes",totalLines,totalBytes,outputLines:0,outputBytes:0,lastLinePartial:!1,firstLineExceedsLimit:!0,maxLines,maxBytes};let outputLinesArr=[],outputBytesCount=0,truncatedBy="lines";for(let i=0;i<lines.length&&i<maxLines;i++){let line=lines[i],lineBytes=Buffer.byteLength(line,"utf-8")+(i>0?1:0);if(outputBytesCount+lineBytes>maxBytes){truncatedBy="bytes";break}outputLinesArr.push(line),outputBytesCount+=lineBytes}outputLinesArr.length>=maxLines&&outputBytesCount<=maxBytes&&(truncatedBy="lines");let outputContent=outputLinesArr.join(`
|
|
@@ -715,7 +715,7 @@ Command exited with code ${msg.exitCode}`),msg.truncated&&msg.fullOutputPath&&(t
|
|
|
715
715
|
`);else{let fd=openSync(this.sessionFile,"wx");try{for(let e of this.fileEntries)writeFileSync5(fd,`${JSON.stringify(e)}
|
|
716
716
|
`)}finally{closeSync(fd)}this.flushed=!0}}_appendEntry(entry){this.fileEntries.push(entry),this.byId.set(entry.id,entry),this.leafId=entry.id,this._persist(entry)}appendMessage(message){let entry={type:"message",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),message};return this._appendEntry(entry),entry.id}appendThinkingLevelChange(thinkingLevel){let entry={type:"thinking_level_change",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),thinkingLevel};return this._appendEntry(entry),entry.id}appendModelChange(provider,modelId2){let entry={type:"model_change",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),provider,modelId:modelId2};return this._appendEntry(entry),entry.id}appendUsage(kind,provider,model,usage,note){let entry={type:"usage",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),kind,provider,model,usage,...note?{note}:{}};return this._appendEntry(entry),entry}appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromHook,usage){let timestamp=new Date().toISOString(),systemMessage=getCurrentSystemMessage(this.buildSessionProjection().messages),id=generateId(this.byId),entry={type:"compaction",id,parentId:this.leafId,timestamp,summary,firstKeptEntryId:firstKeptEntryId??id,tokensBefore,details,usage,fromHook,...systemMessage?{systemMessage:{...systemMessage,timestamp:new Date(timestamp).getTime()}}:{}};return this._appendEntry(entry),entry.id}appendCustomEntry(customType,data){let entry={type:"custom",customType,data,id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendSessionInfo(name){let sanitizedName=name.replace(/[\r\n]+/g," ").trim(),entry={type:"session_info",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),name:sanitizedName};return this._appendEntry(entry),entry.id}getSessionName(){let entries=this.getEntries();for(let i=entries.length-1;i>=0;i--){let entry=entries[i];if(entry.type==="session_info")return entry.name?.trim()||void 0}}appendCustomMessageEntry(customType,content,display,details){let entry={type:"custom_message",customType,content,display,details,id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendContextEdit(targetId,replacement){if(replacement!==null&&(typeof replacement!="object"||!("content"in replacement)||typeof replacement.content!="string"&&!Array.isArray(replacement.content)))throw new Error("Context edit replacement must be null or contain string/array content");let target=this.byId.get(targetId);if(!target)throw new Error(`Entry ${targetId} not found`);if(!this.getBranch().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} is not on the active branch`);if(!(target.type==="custom_message"||target.type==="message"&&(target.message.role==="user"||target.message.role==="assistant"||target.message.role==="toolResult")))throw new Error(`Entry ${targetId} does not contribute editable model content`);let targetRole=target.type==="message"?target.message.role:"custom",normalizedReplacement=replacement!==null&&(targetRole==="assistant"||targetRole==="toolResult")&&typeof replacement.content=="string"?{content:[{type:"text",text:replacement.content}]}:replacement,entry={type:"context_edit",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,replacement:normalizedReplacement};return this._appendEntry(entry),entry.id}getLeafId(){return this.leafId}getLeafEntry(){return this.leafId?this.byId.get(this.leafId):void 0}getEntry(id){return this.byId.get(id)}getChildren(parentId){let children=[];for(let entry of this.byId.values())entry.parentId===parentId&&children.push(entry);return children}getLabel(id){return this.labelsById.get(id)}appendLabelChange(targetId,label){if(!this.byId.has(targetId))throw new Error(`Entry ${targetId} not found`);let entry={type:"label",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,label};return this._appendEntry(entry),label?(this.labelsById.set(targetId,label),this.labelTimestampsById.set(targetId,entry.timestamp)):(this.labelsById.delete(targetId),this.labelTimestampsById.delete(targetId)),entry.id}getBranch(fromId){let path14=[],startId=fromId??this.leafId,current=startId?this.byId.get(startId):void 0;for(;current;)path14.push(current),current=current.parentId?this.byId.get(current.parentId):void 0;return path14.reverse(),path14}buildContextEntries(){return buildContextEntries(this.getEntries(),this.leafId,this.byId)}buildSessionProjection(){return buildSessionProjection(this.getEntries(),this.leafId,this.byId)}buildSessionContext(){let{messages,thinkingLevel,model}=this.buildSessionProjection();return{messages,thinkingLevel,model}}getHeader(){let h=this.fileEntries.find(e=>e.type==="session");return h||null}getEntries(){return this.fileEntries.filter(e=>e.type!=="session")}getTree(){let entries=this.getEntries(),nodeMap=new Map,roots=[];for(let entry of entries){let label=this.labelsById.get(entry.id),labelTimestamp=this.labelTimestampsById.get(entry.id);nodeMap.set(entry.id,{entry,children:[],label,labelTimestamp})}for(let entry of entries){let node=nodeMap.get(entry.id);if(entry.parentId===null||entry.parentId===entry.id)roots.push(node);else{let parent=nodeMap.get(entry.parentId);parent?parent.children.push(node):roots.push(node)}}let stack=[...roots];for(;stack.length>0;){let node=stack.pop();node.children.sort((a,b2)=>new Date(a.entry.timestamp).getTime()-new Date(b2.entry.timestamp).getTime()),stack.push(...node.children)}return roots}branch(branchFromId){if(!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);this.leafId=branchFromId}resetLeaf(){this.leafId=null}branchWithSummary(branchFromId,summary,details,fromHook,usage){if(branchFromId!==null&&!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let fromId=this.leafId??"root";this.leafId=branchFromId;let entry={type:"branch_summary",id:generateId(this.byId),parentId:branchFromId,timestamp:new Date().toISOString(),fromId,summary,details,usage,fromHook};return this._appendEntry(entry),entry.id}createBranchedSession(leafId){let previousSessionFile=this.sessionFile,path14=this.getBranch(leafId);if(path14.length===0)throw new Error(`Entry ${leafId} not found`);let pathWithoutLabels=[],replacementByLabelId=new Map,pendingLabelIds=[],pathParentId=null;for(let entry of path14){if(entry.type==="label"){pendingLabelIds.push(entry.id);continue}for(let labelId of pendingLabelIds)replacementByLabelId.set(labelId,entry.id);pendingLabelIds.length=0,pathWithoutLabels.push(entry.type==="compaction"?{...entry,parentId:pathParentId,firstKeptEntryId:entry.firstKeptEntryId===entry.id?entry.id:replacementByLabelId.get(entry.firstKeptEntryId)??entry.firstKeptEntryId}:{...entry,parentId:pathParentId}),pathParentId=entry.id}let newSessionId=createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join18(this.getSessionDir(),`${fileTimestamp}_${newSessionId}.jsonl`),header={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:this.cwd,parentSession:this.persist?previousSessionFile:void 0},pathEntryIds=new Set(pathWithoutLabels.map(e=>e.id)),labelsToWrite=[];for(let[targetId,label]of this.labelsById)pathEntryIds.has(targetId)&&labelsToWrite.push({targetId,label,timestamp:this.labelTimestampsById.get(targetId)});if(this.persist){let parentId2=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null,labelEntries2=[];for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set(pathEntryIds)),parentId:parentId2,timestamp:labelTimestamp,targetId,label};pathEntryIds.add(labelEntry.id),labelEntries2.push(labelEntry),parentId2=labelEntry.id}return this.fileEntries=[header,...pathWithoutLabels,...labelEntries2],this.sessionId=newSessionId,this.sessionFile=newSessionFile,this._buildIndex(),this.fileEntries.some(e=>e.type==="message"&&e.message.role==="assistant")?(this._rewriteFile(),this.flushed=!0):this.flushed=!1,newSessionFile}let labelEntries=[],parentId=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null;for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set([...pathEntryIds,...labelEntries.map(e=>e.id)])),parentId,timestamp:labelTimestamp,targetId,label};labelEntries.push(labelEntry),parentId=labelEntry.id}this.fileEntries=[header,...pathWithoutLabels,...labelEntries],this.sessionId=newSessionId,this._buildIndex()}static create(cwd,sessionDir,options){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd);return new _SessionManager(cwd,dir,void 0,!0,options)}static open(path14,sessionDir,cwdOverride){let resolvedPath=resolvePath(path14),header=null,preloadedFileEntries;if(cwdOverride===void 0&&existsSync10(resolvedPath))try{header=readSessionHeader(resolvedPath)}catch(error){if(!(error instanceof SessionHeaderScanLimitError))throw error;preloadedFileEntries=loadEntriesFromFile(resolvedPath);let firstEntry=preloadedFileEntries[0];header=firstEntry?.type==="session"?firstEntry:null}let cwd=cwdOverride??(header?getSessionHeaderCwd(header):void 0)??process.cwd(),dir=sessionDir?normalizePath(sessionDir):resolve4(resolvedPath,"..");return new _SessionManager(cwd,dir,resolvedPath,!0,void 0,preloadedFileEntries)}static continueRecent(cwd,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),mostRecent=findMostRecentSession(dir,filterCwd?cwd:void 0);return mostRecent?new _SessionManager(cwd,dir,mostRecent,!0):new _SessionManager(cwd,dir,void 0,!0)}static inMemory(cwd=process.cwd(),options,entries){return new _SessionManager(cwd,"",void 0,!1,options,entries)}static forkFrom(sourcePath,targetCwd,sessionDir,options){let resolvedSourcePath=resolvePath(sourcePath),resolvedTargetCwd=resolvePath(targetCwd),sourceEntries=loadEntriesFromFile(resolvedSourcePath);if(sourceEntries.length===0)throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);if(!sourceEntries.find(e=>e.type==="session"))throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(resolvedTargetCwd);existsSync10(dir)||mkdirSync5(dir,{recursive:!0}),options?.id!==void 0&&assertValidSessionId(options.id);let newSessionId=options?.id??createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join18(dir,`${fileTimestamp}_${newSessionId}.jsonl`);writeFileSync5(newSessionFile,`${JSON.stringify({type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:resolvedTargetCwd,parentSession:resolvedSourcePath})}
|
|
717
717
|
`,{flag:"wx"});for(let entry of sourceEntries)entry.type!=="session"&&appendFileSync3(newSessionFile,`${JSON.stringify(entry)}
|
|
718
|
-
`);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd);try{for(let file of readdirSync5(dir)){if(!file.endsWith(".jsonl"))continue;let path14=join18(dir,file),header=readSessionHeaderForDiscovery(path14);if(header?.id===id&&!(filterCwd&&!sessionCwdMatches(getSessionHeaderCwd(header),resolvedCwd)))return path14}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd),includeSession=session=>!filterCwd||sessionCwdMatches(session.cwd,resolvedCwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync10(sessionsDir))return[];let dirs=(await readdir(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join18(sessionsDir,entry.name)),allFiles=(await mapWithConcurrency(dirs,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async dir=>{try{return(await readdir(dir)).filter(file=>file.endsWith(".jsonl")).map(file=>join18(dir,file))}catch{return[]}},abortSignal)).flat(),candidates=await mapWithConcurrency(allFiles,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async path14=>{try{return{path:path14,stats:await stat(path14)}}catch{return{path:path14}}},abortSignal);candidates.sort((a,b2)=>(b2.stats?.mtimeMs??Number.NEGATIVE_INFINITY)-(a.stats?.mtimeMs??Number.NEGATIVE_INFINITY)||basename5(b2.path).localeCompare(basename5(a.path)));let totalFiles=candidates.length,loaded=0,firstCandidateLoaded=!1,partialSessions=[],results=await buildSessionInfosWithConcurrency(candidates,(info,index3)=>{loaded++,index3===0&&(firstCandidateLoaded=!0),info&&partialSessions.push(info);let publishPartial=firstCandidateLoaded&&(index3===0||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles);progress?.(loaded,totalFiles,publishPartial?sortSessionInfos([...partialSessions]):void 0)},abortSignal);return sortSessionInfos(results.filter(info=>info!==null))}catch{return abortSignal?.throwIfAborted(),[]}}};import{EventEmitter as EventEmitter3}from"node:events";function createEventBus(){let emitter=new EventEmitter3;return{emit:(channel,data)=>{emitter.emit(channel,data)},on:(channel,handler)=>{let safeHandler=async data=>{try{await handler(data)}catch(err2){console.error(`Event handler error (${channel}):`,err2)}};return emitter.on(channel,safeHandler),()=>emitter.off(channel,safeHandler)},clear:()=>{emitter.removeAllListeners()}}}var STALE_EXTENSION_CONTEXT_MESSAGE="This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";function isStaleExtensionContextError(error){return error instanceof Error&&error.message===STALE_EXTENSION_CONTEXT_MESSAGE}function defineTool(tool){return tool}function isBashToolResult(e){return e.toolName==="bash"}function isPowerShellToolResult(e){return e.toolName==="powershell"}function isReadToolResult(e){return e.toolName==="read"}function isEditToolResult(e){return e.toolName==="edit"}function isWriteToolResult(e){return e.toolName==="write"}function isGrepToolResult(e){return e.toolName==="grep"}function isFindToolResult(e){return e.toolName==="find"}function isLsToolResult(e){return e.toolName==="ls"}function isToolCallEventType(toolName,event){return event.toolName===toolName}var dist_exports2={};__export(dist_exports2,{AGENT_TELEMETRY_SCHEMAS:()=>AGENT_TELEMETRY_SCHEMAS,AI_TELEMETRY_SCHEMA:()=>AI_TELEMETRY_SCHEMA,Agent:()=>Agent,AgentHarness:()=>AgentHarness,BACKGROUND_CONTEXT:()=>BACKGROUND_CONTEXT,BRANCH_SUMMARY_PREFIX:()=>BRANCH_SUMMARY_PREFIX2,BRANCH_SUMMARY_SUFFIX:()=>BRANCH_SUMMARY_SUFFIX2,BranchSummaryError:()=>BranchSummaryError,COMPACTION_SUMMARY_PREFIX:()=>COMPACTION_SUMMARY_PREFIX2,COMPACTION_SUMMARY_SUFFIX:()=>COMPACTION_SUMMARY_SUFFIX2,Closed:()=>Closed,CompactionError:()=>CompactionError,DEFAULT_COMPACTION_SETTINGS:()=>DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES:()=>DEFAULT_MAX_BYTES3,DEFAULT_MAX_LINES:()=>DEFAULT_MAX_LINES2,ExecutionError:()=>ExecutionError,FileError:()=>FileError,GREP_MAX_LINE_LENGTH:()=>GREP_MAX_LINE_LENGTH,HARNESS_TELEMETRY_SCHEMA:()=>HARNESS_TELEMETRY_SCHEMA,HarnessClosed:()=>HarnessClosed,HarnessFault:()=>HarnessFault,InMemoryTelemetryContext:()=>InMemoryTelemetryContext,InvalidLane:()=>InvalidLane,InvalidMessage:()=>InvalidMessage,InvalidNavigation:()=>InvalidNavigation,JSONL_STORAGE_VERSION:()=>JSONL_STORAGE_VERSION,JsonlSessionRepo:()=>JsonlSessionRepo,LaneBusy:()=>LaneBusy,MemorySessionRepo:()=>MemorySessionRepo,NOOP_TELEMETRY_CONTEXT:()=>NOOP_TELEMETRY_CONTEXT,NoActiveOperation:()=>NoActiveOperation,NoActiveRun:()=>NoActiveRun,NothingToCompact:()=>NothingToCompact,NothingToResume:()=>NothingToResume,OperationMismatch:()=>OperationMismatch,Result:()=>Result,SessionBranchExistsError:()=>SessionBranchExistsError,SessionInvalidBranchError:()=>SessionInvalidBranchError,SessionInvariantError:()=>SessionInvariantError,SessionPendingAssistantMessageError:()=>SessionPendingAssistantMessageError,SessionUnknownTargetError:()=>SessionUnknownTargetError,SliceNotImplemented:()=>SliceNotImplemented,StorageBackedSession:()=>StorageBackedSession,TODO_CONTEXT:()=>TODO_CONTEXT,TaggedError:()=>TaggedError,UnknownSkill:()=>UnknownSkill,UnknownTarget:()=>UnknownTarget,UnknownTemplate:()=>UnknownTemplate,agentLoop:()=>agentLoop,agentLoopContinue:()=>agentLoopContinue,appendList:()=>appendList,applyShellOutputUpdate:()=>applyShellOutputUpdate,awaitWithContext:()=>awaitWithContext,bashExecutionToText:()=>bashExecutionToText2,branchTip:()=>branchTip,branchTipInventoryPrefix:()=>branchTipInventoryPrefix,calculateContextTokens:()=>calculateContextTokens,collectEntriesForBranchSummary:()=>collectEntriesForBranchSummary,commitWrite:()=>commitWrite,compact:()=>compact,convertToLlm:()=>convertToLlm2,createBashTool:()=>createBashTool,createBranchSummaryMessage:()=>createBranchSummaryMessage2,createCompactionSummaryMessage:()=>createCompactionSummaryMessage2,createContextKey:()=>createContextKey,createCustomMessage:()=>createCustomMessage2,createEditTool:()=>createEditTool,createForkSnapshot:()=>createForkSnapshot,createReadTool:()=>createReadTool,createTypedSpanStarter:()=>createTypedSpanStarter,createWriteTool:()=>createWriteTool,defineTelemetrySchema:()=>defineTelemetrySchema,deleteList:()=>deleteList,deleteValue:()=>deleteValue,entryLabel:()=>entryLabel,err:()=>err,estimateContextTokens:()=>estimateContextTokens2,estimateTokens:()=>estimateTokens2,executeShellWithCapture:()=>executeShellWithCapture,findCutPoint:()=>findCutPoint,findTurnStartIndex:()=>findTurnStartIndex,formatPromptTemplateInvocation:()=>formatPromptTemplateInvocation,formatSize:()=>formatSize2,formatSkillInvocation:()=>formatSkillInvocation,formatSkillsForSystemPrompt:()=>formatSkillsForSystemPrompt,generateBranchSummary:()=>generateBranchSummary,generateSummary:()=>generateSummary,generateSummaryWithUsage:()=>generateSummaryWithUsage,getLastAssistantUsage:()=>getLastAssistantUsage,getOrThrow:()=>getOrThrow,getOrUndefined:()=>getOrUndefined,getTelemetryContext:()=>getTelemetryContext,insertEntry:()=>insertEntry,insertUsage:()=>insertUsage,laneConfig:()=>laneConfig,laneState:()=>laneState,list:()=>list,loadPromptTemplates:()=>loadPromptTemplates,loadSkills:()=>loadSkills2,loadSourcedPromptTemplates:()=>loadSourcedPromptTemplates,loadSourcedSkills:()=>loadSourcedSkills,matchError:()=>matchError,ok:()=>ok,operationMeta:()=>operationMeta,operationPreparation:()=>operationPreparation,operationPreparationPrefix:()=>operationPreparationPrefix,operationResult:()=>operationResult,operationScopeOf:()=>operationScopeOf,operationState:()=>operationState,operationToolArgs:()=>operationToolArgs,operationToolArgsPrefix:()=>operationToolArgsPrefix,operationToolMemo:()=>operationToolMemo,operationToolMemoPrefix:()=>operationToolMemoPrefix,parseCommandArgs:()=>parseCommandArgs,pendingAssistantFrames:()=>pendingAssistantFrames,pendingEntry:()=>pendingEntry,pendingToolOutput:()=>pendingToolOutput,pendingToolOutputPrefix:()=>pendingToolOutputPrefix,prepareBranchEntries:()=>prepareBranchEntries,prepareCompaction:()=>prepareCompaction,prepareStorageCommit:()=>prepareStorageCommit,projectForkCurrentStateWrite:()=>projectForkCurrentStateWrite,reduceLaneSnapshot:()=>reduceLaneSnapshot,resolveListReadOptions:()=>resolveListReadOptions,runAgentLoop:()=>runAgentLoop,runAgentLoopContinue:()=>runAgentLoopContinue,sanitizeBinaryOutput:()=>sanitizeShellOutput,serializeConversation:()=>serializeConversation,sessionName:()=>sessionName,setDefaultStreamFn:()=>setDefaultStreamFn,setValue:()=>setValue,shouldCompact:()=>shouldCompact,startAiSpan:()=>startAiSpan,startHarnessSpan:()=>startHarnessSpan,streamProxy:()=>streamProxy,substituteArgs:()=>substituteArgs,toError:()=>toError,truncateHead:()=>truncateHead2,truncateLine:()=>truncateLine2,truncateTail:()=>truncateTail2,utf8ByteLength:()=>utf8ByteLength,uuidv7:()=>uuidv7,validateCommittedWrites:()=>validateCommittedWrites,value:()=>value,withAbortSignal:()=>withAbortSignal,withCancel:()=>withCancel,withContextValue:()=>withContextValue,withTelemetryContext:()=>withTelemetryContext,withoutAbortSignal:()=>withoutAbortSignal});function startNoopSpan(_options,callback){try{return Promise.resolve(callback(noopTelemetrySpan))}catch(error){return Promise.reject(error)}}var noopTelemetrySpan={startSpan:startNoopSpan,addEvent:()=>{},setAttributes:()=>{},setStatus:()=>{}};Object.freeze(noopTelemetrySpan);var NOOP_TELEMETRY_CONTEXT=noopTelemetrySpan;function copyAttributeValue(value2){return Array.isArray(value2)?[...value2]:value2}function copyAttributes(attributes){let copy={};if(!attributes)return copy;for(let[name,value2]of Object.entries(attributes))value2!==void 0&&(copy[name]=copyAttributeValue(value2));return copy}function mergeAttributes(current,attributes){let merged=copyAttributes(current);for(let[name,value2]of Object.entries(attributes))value2!==void 0&&(merged[name]=copyAttributeValue(value2));return merged}function copyStatus(status){return status.status==="ok"?{status:"ok"}:status.error?{status:"error",error:{name:status.error.name,message:status.error.message}}:{status:"error"}}function automaticErrorStatus(error){try{if(error instanceof Error)return{status:"error",error:{name:error.name,message:error.message}}}catch{}return{status:"error"}}function settleSpan(state2,span,failed,error){span.settled||(failed&&!span.explicitStatus&&(span.status=automaticErrorStatus(error)),span.settled=!0,span.endSequence=state2.nextEndSequence++)}function createSpan(state2,parent,options){let name=options.name,attributes=copyAttributes(options.attributes);return{id:state2.nextSpanId++,parentId:parent?.id??null,name,attributes,events:[],status:{status:"ok"},explicitStatus:!1,settled:!1}}function startInMemorySpan(state2,parent,options,callback){if(parent?.settled)return NOOP_TELEMETRY_CONTEXT.startSpan(options,callback);let recordedSpan;try{recordedSpan=createSpan(state2,parent,options),state2.spans.push(recordedSpan)}catch{return NOOP_TELEMETRY_CONTEXT.startSpan(options,callback)}let span={startSpan:(childOptions,childCallback)=>startInMemorySpan(state2,recordedSpan,childOptions,childCallback),addEvent(name,attributes){if(!recordedSpan.settled)try{recordedSpan.events.push({name,attributes:copyAttributes(attributes)})}catch{}},setAttributes(attributes){if(!recordedSpan.settled)try{recordedSpan.attributes=mergeAttributes(recordedSpan.attributes,attributes)}catch{}},setStatus(status){if(!recordedSpan.settled)try{recordedSpan.status=copyStatus(status),recordedSpan.explicitStatus=!0}catch{}}},result2;try{result2=callback(span)}catch(error){return settleSpan(state2,recordedSpan,!0,error),Promise.reject(error)}return Promise.resolve(result2).then(value2=>(settleSpan(state2,recordedSpan,!1),value2),error=>{throw settleSpan(state2,recordedSpan,!0,error),error})}var InMemoryTelemetryContext=class{state={spans:[],nextSpanId:1,nextEndSequence:1};startSpan(options,callback){return startInMemorySpan(this.state,void 0,options,callback)}getSpans(){return this.state.spans.map(span=>({id:span.id,parentId:span.parentId,name:span.name,attributes:copyAttributes(span.attributes),events:span.events.map(event=>({name:event.name,attributes:copyAttributes(event.attributes)})),status:copyStatus(span.status),settled:span.settled,...span.endSequence===void 0?{}:{endSequence:span.endSequence}}))}};function defineTelemetrySchema(schema){return schema}function bindTypedSpanStarter(telemetryContext){return(name,attributes,callback)=>telemetryContext.startSpan({name,attributes},span=>callback(span,bindTypedSpanStarter(span)))}function createTypedSpanStarter(telemetryContext,_schemas){return bindTypedSpanStarter(telemetryContext)}var defaultStreamFn;function setDefaultStreamFn(streamFn){defaultStreamFn=streamFn}function getDefaultStreamFn(){if(!defaultStreamFn)throw new Error("No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().");return defaultStreamFn}function agentLoop(prompts,context,config,signal,streamFn){let stream2=createAgentStream();return runAgentLoop(prompts,context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}function agentLoopContinue(context,config,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let stream2=createAgentStream();return runAgentLoopContinue(context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}async function runAgentLoop(prompts,context,config,emit,signal,streamFn){let initialMessages=declareToolChanges(context,prompts),newMessages=[...initialMessages],currentContext={...context,messages:[...context.messages,...initialMessages]};await emit({type:"agent_start"}),await emit({type:"turn_start"});for(let message of initialMessages)await emit({type:"message_start",message}),await emit({type:"message_end",message});return await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}async function runAgentLoopContinue(context,config,emit,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let newMessages=[],currentContext={...context};return await emit({type:"agent_start"}),await emit({type:"turn_start"}),await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}function createAgentStream(){return new EventStream(event=>event.type==="agent_end",event=>event.type==="agent_end"?event.messages:[])}async function runLoop(initialContext,newMessages,initialConfig,signal,emit,streamFunction){let currentContext=initialContext,config=initialConfig,lastCompletedTurn,explicitContinuation=!1,pendingMessages=await config.getSteeringMessages?.()||[];for(;;){let hasMoreToolCalls=!0;for(;hasMoreToolCalls||pendingMessages.length>0;){let preparedMessages=[];if(lastCompletedTurn){let nextTurnSnapshot=await config.prepareNextTurn?.(lastCompletedTurn);nextTurnSnapshot&&(currentContext=nextTurnSnapshot.context??currentContext,preparedMessages=nextTurnSnapshot.messages??[],config={...config,model:nextTurnSnapshot.model??config.model,reasoning:nextTurnSnapshot.thinkingLevel===void 0?config.reasoning:nextTurnSnapshot.thinkingLevel==="off"?void 0:nextTurnSnapshot.thinkingLevel}),pendingMessages.length===0&&(pendingMessages=await config.getSteeringMessages?.()||[]),await emit({type:"turn_start"})}for(let message2 of declareToolChanges(currentContext,[...preparedMessages,...pendingMessages]))await emit({type:"message_start",message:message2}),await emit({type:"message_end",message:message2}),currentContext.messages.push(message2),newMessages.push(message2);pendingMessages=[];let requestUpdate=await config.prepareRequest?.({context:currentContext,model:config.model,thinkingLevel:config.reasoning??"off"},signal);requestUpdate&&(currentContext=requestUpdate.context??currentContext,config={...config,model:requestUpdate.model??config.model,reasoning:requestUpdate.thinkingLevel===void 0?config.reasoning:requestUpdate.thinkingLevel==="off"?void 0:requestUpdate.thinkingLevel});let message=await streamAssistantResponse(currentContext,config,signal,emit,streamFunction);if(newMessages.push(message),message.stopReason==="error"||message.stopReason==="aborted"){lastCompletedTurn={message,toolResults:[],context:currentContext,newMessages},await config.finishTurn?.(lastCompletedTurn,signal),await emit({type:"turn_end",message,toolResults:[]}),await emit({type:"agent_end",messages:newMessages});return}let toolCalls=message.content.filter(c=>c.type==="toolCall"),toolResults=[];if(hasMoreToolCalls=!1,toolCalls.length>0){let executedToolBatch=message.stopReason==="length"?await failToolCallsFromTruncatedMessage(toolCalls,emit):await executeToolCalls(currentContext,message,config,signal,emit);toolResults.push(...executedToolBatch.messages),hasMoreToolCalls=!executedToolBatch.terminate;for(let result2 of toolResults)currentContext.messages.push(result2),newMessages.push(result2)}lastCompletedTurn={message,toolResults,context:currentContext,newMessages};let decision=await config.finishTurn?.(lastCompletedTurn,signal);if(await emit({type:"turn_end",message,toolResults}),decision?.action==="end"){await emit({type:"agent_end",messages:newMessages});return}explicitContinuation=decision?.action==="continue",pendingMessages=await config.getSteeringMessages?.()||[],(hasMoreToolCalls||pendingMessages.length>0)&&(explicitContinuation=!1)}let followUpMessages=await config.getFollowUpMessages?.()||[];if(followUpMessages.length>0){explicitContinuation=!1,pendingMessages=followUpMessages;continue}if(explicitContinuation){explicitContinuation=!1;continue}break}await emit({type:"agent_end",messages:newMessages})}function declareToolChanges(context,pendingMessages){let systemIndex=-1;for(let i=pendingMessages.length-1;i>=0;i--)if(pendingMessages[i].role==="system"){systemIndex=i;break}let pending=pendingMessages[systemIndex],baseline=pending?pendingMessages.map((message,index4)=>index4===systemIndex?withToolChanges(pending,NO_CHANGES):message):pendingMessages,changes=getToolStateChanges(getCurrentTools([...context.messages,...baseline]),(context.tools??[]).map(toToolDeclaration)),unchanged=changes.toolsAdded.length===0&&changes.toolsRemoved.length===0;if(pending)return unchanged&&!pending.toolsAdded?.length&&!pending.toolsRemoved?.length?pendingMessages:baseline.map((message,index4)=>index4===systemIndex?withToolChanges(pending,changes):message);if(unchanged)return pendingMessages;let update=withToolChanges({role:"system",content:"",timestamp:Date.now()},changes),insertIndex=pendingMessages.findIndex(message=>message.role!=="system"),index3=insertIndex===-1?pendingMessages.length:insertIndex;return[...pendingMessages.slice(0,index3),update,...pendingMessages.slice(index3)]}var NO_CHANGES={toolsAdded:[],toolsRemoved:[]};function withToolChanges(message,{toolsAdded,toolsRemoved}){let{toolsAdded:_added,toolsRemoved:_removed,...rest}=message;return{...rest,...toolsAdded.length>0?{toolsAdded}:{},...toolsRemoved.length>0?{toolsRemoved}:{}}}async function streamAssistantResponse(context,config,signal,emit,streamFunction){let messages=context.messages;config.transformContext&&(messages=await config.transformContext(messages,signal));let llmMessages=await config.convertToLlm(messages),llmContext=normalizeContext({messages:llmMessages}),resolvedApiKey=(config.getApiKey?await config.getApiKey(config.model.provider):void 0)||config.apiKey,response=await streamFunction(config.model,llmContext,{...config,apiKey:resolvedApiKey,signal}),partialMessage=null,addedPartial=!1;for await(let event of response)switch(event.type){case"start":partialMessage=event.partial,context.messages.push(partialMessage),addedPartial=!0,await emit({type:"message_start",message:{...partialMessage}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":partialMessage&&(partialMessage=event.partial,context.messages[context.messages.length-1]=partialMessage,await emit({type:"message_update",assistantMessageEvent:event,message:{...partialMessage}}));break;case"done":case"error":{let finalMessage2=await response.result();return addedPartial?context.messages[context.messages.length-1]=finalMessage2:context.messages.push(finalMessage2),addedPartial||await emit({type:"message_start",message:{...finalMessage2}}),await emit({type:"message_end",message:finalMessage2}),finalMessage2}}let finalMessage=await response.result();return addedPartial?context.messages[context.messages.length-1]=finalMessage:(context.messages.push(finalMessage),await emit({type:"message_start",message:{...finalMessage}})),await emit({type:"message_end",message:finalMessage}),finalMessage}async function failToolCallsFromTruncatedMessage(toolCalls,emit){let messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let finalized={toolCall,result:createErrorToolResult(`Tool call "${toolCall.name}" was not executed: the response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`),isError:!0};await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:!1}}async function executeToolCalls(currentContext,assistantMessage,config,signal,emit){let toolCalls=assistantMessage.content.filter(c=>c.type==="toolCall"),hasSequentialToolCall=toolCalls.some(tc=>currentContext.tools?.find(t=>t.name===tc.name)?.executionMode==="sequential");return config.toolExecution==="sequential"||hasSequentialToolCall?executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit):executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit)}async function executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[],messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal),finalized;if(preparation.kind==="immediate")finalized={toolCall,result:preparation.result,isError:preparation.isError};else{let executed=await executePreparedToolCall(preparation,signal,emit);finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal)}await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);if(await emitToolResultMessage(toolResultMessage,emit),finalizedCalls.push(finalized),messages.push(toolResultMessage),signal?.aborted)break}return{messages,terminate:shouldTerminateToolBatch(finalizedCalls)}}async function executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal);if(preparation.kind==="immediate"){let finalized={toolCall,result:preparation.result,isError:preparation.isError};if(await emitToolExecutionEnd(finalized,emit),finalizedCalls.push(finalized),signal?.aborted)break;continue}if(finalizedCalls.push(async()=>{if(signal?.aborted){let finalized2={toolCall,result:createErrorToolResult("Operation aborted"),isError:!0};return await emitToolExecutionEnd(finalized2,emit),finalized2}let executed=await executePreparedToolCall(preparation,signal,emit),finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal);return await emitToolExecutionEnd(finalized,emit),finalized}),signal?.aborted)break}let orderedFinalizedCalls=await Promise.all(finalizedCalls.map(entry=>typeof entry=="function"?entry():Promise.resolve(entry))),messages=[];for(let finalized of orderedFinalizedCalls){let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:shouldTerminateToolBatch(orderedFinalizedCalls)}}function shouldTerminateToolBatch(finalizedCalls){return finalizedCalls.length>0&&finalizedCalls.every(finalized=>finalized.result.terminate===!0)}function prepareToolCallArguments(tool,toolCall){if(!tool.prepareArguments)return toolCall;let preparedArguments=tool.prepareArguments(toolCall.arguments);return preparedArguments===toolCall.arguments?toolCall:{...toolCall,arguments:preparedArguments}}async function prepareToolCall(currentContext,assistantMessage,toolCall,config,signal){let tool=currentContext.tools?.find(t=>t.name===toolCall.name);if(!tool)return{kind:"immediate",result:createErrorToolResult(`Tool ${toolCall.name} not found`),isError:!0};try{let preparedToolCall=prepareToolCallArguments(tool,toolCall),validatedArgs=validateToolArguments(tool,preparedToolCall);if(config.beforeToolCall){let beforeResult=await config.beforeToolCall({assistantMessage,toolCall,args:validatedArgs,context:currentContext},signal);if(signal?.aborted)return{kind:"immediate",result:createErrorToolResult("Operation aborted"),isError:!0};if(beforeResult?.block){let result2=createErrorToolResult(beforeResult.reason||"Tool execution was blocked");return beforeResult.terminate===!0&&(result2.terminate=!0),{kind:"immediate",result:result2,isError:!0}}}return signal?.aborted?{kind:"immediate",result:createErrorToolResult("Operation aborted"),isError:!0}:{kind:"prepared",toolCall,tool,args:validatedArgs}}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}}async function executePreparedToolCall(prepared,signal,emit){let updateEvents=[],acceptingUpdates=!0;try{let result2=await prepared.tool.execute(prepared.toolCall.id,prepared.args,signal,partialResult=>{acceptingUpdates&&updateEvents.push(Promise.resolve(emit({type:"tool_execution_update",toolCallId:prepared.toolCall.id,toolName:prepared.toolCall.name,args:prepared.toolCall.arguments,partialResult})))});return acceptingUpdates=!1,await Promise.all(updateEvents),{result:result2,isError:!1}}catch(error){return acceptingUpdates=!1,await Promise.all(updateEvents),{result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}finally{acceptingUpdates=!1}}async function finalizeExecutedToolCall(currentContext,assistantMessage,prepared,executed,config,signal){let result2=executed.result,isError=executed.isError;if(config.afterToolCall)try{let afterResult=await config.afterToolCall({assistantMessage,toolCall:prepared.toolCall,args:prepared.args,result:result2,isError,context:currentContext},signal);afterResult&&(result2={...result2,content:afterResult.content??result2.content,details:afterResult.details??result2.details,usage:afterResult.usage??result2.usage,terminate:afterResult.terminate??result2.terminate},isError=afterResult.isError??isError)}catch(error){result2=createErrorToolResult(error instanceof Error?error.message:String(error)),isError=!0}return{toolCall:prepared.toolCall,result:result2,isError}}function createErrorToolResult(message){return{content:[{type:"text",text:message}],details:{}}}async function emitToolExecutionEnd(finalized,emit){await emit({type:"tool_execution_end",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,result:finalized.result,isError:finalized.isError})}function createToolResultMessage(finalized){return{role:"toolResult",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,content:finalized.result.content??[],details:finalized.result.details,usage:finalized.result.usage,isError:finalized.isError,timestamp:Date.now()}}async function emitToolResultMessage(toolResultMessage,emit){await emit({type:"message_start",message:toolResultMessage}),await emit({type:"message_end",message:toolResultMessage})}function defaultConvertToLlm(messages){return messages.filter(message=>message.role==="system"||message.role==="user"||message.role==="assistant"||message.role==="toolResult")}var EMPTY_USAGE={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},DEFAULT_MODEL={id:"unknown",name:"unknown",api:"unknown",provider:"unknown",baseUrl:"",reasoning:!1,input:[],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:0,maxTokens:0};function createMutableAgentState(initialState){let tools=initialState?.tools?.slice()??[],messages=initialState?.messages?.slice()??[],initialMessage=createInitialSystemMessage(initialState?.systemPrompt,tools.map(toToolDeclaration));return messages[0]?.role!=="system"&&initialMessage&&messages.unshift(initialMessage),{get systemPrompt(){return getCurrentSystemPrompt(messages)},model:initialState?.model??DEFAULT_MODEL,thinkingLevel:initialState?.thinkingLevel??"off",get tools(){return tools},set tools(nextTools){tools=nextTools.slice()},get messages(){return messages},set messages(nextMessages){messages=nextMessages.slice()},isStreaming:!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:void 0}}var PendingMessageQueue=class{messages=[];mode;constructor(mode){this.mode=mode}enqueue(message){this.messages.push(message)}hasItems(){return this.messages.length>0}peek(){if(this.mode==="all")return this.messages.slice();let first=this.messages[0];return first?[first]:[]}drain(){let drained=this.peek();return this.messages=this.messages.slice(drained.length),drained}clear(){this.messages=[]}},Agent=class{_state;listeners=new Set;steeringQueue;followUpQueue;convertToLlm;transformContext;streamFunction;getApiKey;onPayload;onResponse;beforeToolCall;afterToolCall;finishTurn;prepareRequest;prepareNextTurn;prepareNextTurnWithContext;activeRun;sessionId;thinkingBudgets;transport;maxRetryDelayMs;toolExecution;constructor(options){let runtimeOptions=options??{};this._state=createMutableAgentState(runtimeOptions.initialState),this.convertToLlm=runtimeOptions.convertToLlm??defaultConvertToLlm,this.transformContext=runtimeOptions.transformContext,this.streamFunction=runtimeOptions.streamFn??getDefaultStreamFn(),this.getApiKey=runtimeOptions.getApiKey,this.onPayload=runtimeOptions.onPayload,this.onResponse=runtimeOptions.onResponse,this.beforeToolCall=runtimeOptions.beforeToolCall,this.afterToolCall=runtimeOptions.afterToolCall,this.finishTurn=runtimeOptions.finishTurn,this.prepareRequest=runtimeOptions.prepareRequest,this.prepareNextTurn=runtimeOptions.prepareNextTurn,this.prepareNextTurnWithContext=runtimeOptions.prepareNextTurnWithContext,this.steeringQueue=new PendingMessageQueue(runtimeOptions.steeringMode??"one-at-a-time"),this.followUpQueue=new PendingMessageQueue(runtimeOptions.followUpMode??"one-at-a-time"),this.sessionId=runtimeOptions.sessionId,this.thinkingBudgets=runtimeOptions.thinkingBudgets,this.transport=runtimeOptions.transport??"auto",this.maxRetryDelayMs=runtimeOptions.maxRetryDelayMs,this.toolExecution=runtimeOptions.toolExecution??"parallel"}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}get state(){return this._state}set steeringMode(mode){this.steeringQueue.mode=mode}get steeringMode(){return this.steeringQueue.mode}set followUpMode(mode){this.followUpQueue.mode=mode}get followUpMode(){return this.followUpQueue.mode}steer(message){this.steeringQueue.enqueue(message)}followUp(message){this.followUpQueue.enqueue(message)}clearSteeringQueue(){this.steeringQueue.clear()}clearFollowUpQueue(){this.followUpQueue.clear()}clearAllQueues(){this.clearSteeringQueue(),this.clearFollowUpQueue()}hasQueuedMessages(){return this.steeringQueue.hasItems()||this.followUpQueue.hasItems()}peekQueuedMessages(){let steering=this.steeringQueue.peek();return steering.length>0?steering:this.followUpQueue.peek()}get signal(){return this.activeRun?.abortController.signal}abort(){this.activeRun?.abortController.abort()}waitForIdle(){return this.activeRun?.promise??Promise.resolve()}reset(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before resetting.");let baseline=getCurrentSystemMessage(this._state.messages);this._state.messages=baseline?[baseline]:[],this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this._state.errorMessage=void 0,this.clearFollowUpQueue(),this.clearSteeringQueue()}async prompt(input2,images){if(this.activeRun)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");let messages=this.normalizePromptInput(input2,images);await this.runPromptMessages(messages)}async continue(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before continuing.");let lastMessage=this._state.messages[this._state.messages.length-1];if(!lastMessage||this._state.messages.every(message=>message.role==="system"))throw new Error("No messages to continue from");if(lastMessage.role==="assistant"){let queuedSteering=this.steeringQueue.drain();if(queuedSteering.length>0){await this.runPromptMessages(queuedSteering,{skipInitialSteeringPoll:!0});return}let queuedFollowUps=this.followUpQueue.drain();if(queuedFollowUps.length>0){await this.runPromptMessages(queuedFollowUps);return}throw new Error("Cannot continue from message role: assistant")}await this.runContinuation()}normalizePromptInput(input2,images){if(Array.isArray(input2))return input2;if(typeof input2!="string")return[input2];let content=[{type:"text",text:input2}];return images&&images.length>0&&content.push(...images),[{role:"user",content,timestamp:Date.now()}]}async runPromptMessages(messages,options={}){await this.runWithLifecycle(async signal=>{await runAgentLoop(messages,this.createContextSnapshot(),this.createLoopConfig(options),event=>this.processEvents(event),signal,this.streamFunction)})}async runContinuation(){await this.runWithLifecycle(async signal=>{await runAgentLoopContinue(this.createContextSnapshot(),this.createLoopConfig(),event=>this.processEvents(event),signal,this.streamFunction)})}createContextSnapshot(){return{messages:this._state.messages.slice(),tools:this._state.tools.slice()}}createLoopConfig(options={}){let skipInitialSteeringPoll=options.skipInitialSteeringPoll===!0;return{model:this._state.model,reasoning:this._state.thinkingLevel==="off"?void 0:this._state.thinkingLevel,sessionId:this.sessionId,onPayload:this.onPayload,onResponse:this.onResponse,transport:this.transport,thinkingBudgets:this.thinkingBudgets,maxRetryDelayMs:this.maxRetryDelayMs,toolExecution:this.toolExecution,beforeToolCall:this.beforeToolCall,afterToolCall:this.afterToolCall,finishTurn:this.finishTurn,prepareRequest:this.prepareRequest,prepareNextTurn:this.prepareNextTurnWithContext||this.prepareNextTurn?async context=>this.prepareNextTurnWithContext?await this.prepareNextTurnWithContext(context,this.signal):await this.prepareNextTurn?.(this.signal):void 0,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>skipInitialSteeringPoll?(skipInitialSteeringPoll=!1,[]):this.steeringQueue.drain(),getFollowUpMessages:async()=>this.followUpQueue.drain()}}async runWithLifecycle(executor){if(this.activeRun)throw new Error("Agent is already processing.");let abortController=new AbortController,resolvePromise=()=>{},promise=new Promise(resolve17=>{resolvePromise=resolve17});this.activeRun={promise,resolve:resolvePromise,abortController},this._state.isStreaming=!0,this._state.streamingMessage=void 0,this._state.errorMessage=void 0;try{await executor(abortController.signal)}catch(error){await this.handleRunFailure(error,abortController.signal.aborted)}finally{this.finishRun()}}async handleRunFailure(error,aborted){let failureMessage={role:"assistant",content:[{type:"text",text:""}],api:this._state.model.api,provider:this._state.model.provider,model:this._state.model.id,usage:EMPTY_USAGE,stopReason:aborted?"aborted":"error",errorMessage:error instanceof Error?error.message:String(error),timestamp:Date.now()};await this.processEvents({type:"message_start",message:failureMessage}),await this.processEvents({type:"message_end",message:failureMessage}),await this.processEvents({type:"turn_end",message:failureMessage,toolResults:[]}),await this.processEvents({type:"agent_end",messages:[failureMessage]})}finishRun(){this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this.activeRun?.resolve(),this.activeRun=void 0}async processEvents(event){switch(event.type){case"message_start":this._state.streamingMessage=event.message;break;case"message_update":this._state.streamingMessage=event.message;break;case"message_end":this._state.streamingMessage=void 0,this._state.messages.push(event.message);break;case"tool_execution_start":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.add(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"tool_execution_end":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.delete(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"turn_end":event.message.role==="assistant"&&event.message.errorMessage&&(this._state.errorMessage=event.message.errorMessage);break;case"agent_end":this._state.streamingMessage=void 0;break}let signal=this.activeRun?.abortController.signal;if(!signal)throw new Error("Agent listener invoked outside active run");for(let listener of this.listeners)await listener(event,signal)}};var Result={ok(value2){return{ok:!0,value:value2}},err(error){return{ok:!1,error}},isOk(result2){return result2.ok},isErr(result2){return!result2.ok}};function TaggedError(tag){class TaggedErrorClass extends Error{_tag=tag;constructor(props){super(props.message),this.name=tag,Object.assign(this,props)}toJSON(){let payload={};for(let key of Object.keys(this))key!=="_tag"&&(payload[key]=this[key]);return{_tag:tag,message:this.message,...payload}}static is(value2){return value2 instanceof TaggedErrorClass}}return TaggedErrorClass}var LaneBusy=class extends TaggedError("LaneBusy"){},OperationMismatch=class extends TaggedError("OperationMismatch"){},NoActiveRun=class extends TaggedError("NoActiveRun"){},NoActiveOperation=class extends TaggedError("NoActiveOperation"){},NothingToResume=class extends TaggedError("NothingToResume"){},NothingToCompact=class extends TaggedError("NothingToCompact"){},InvalidMessage=class extends TaggedError("InvalidMessage"){},InvalidNavigation=class extends TaggedError("InvalidNavigation"){},UnknownSkill=class extends TaggedError("UnknownSkill"){},UnknownTemplate=class extends TaggedError("UnknownTemplate"){},UnknownTarget=class extends TaggedError("UnknownTarget"){},InvalidLane=class extends TaggedError("InvalidLane"){},Closed=class extends TaggedError("Closed"){},HarnessFault=class extends Error{cause;constructor(message,cause){super(message),this.name="HarnessFault",this.cause=cause}},HarnessClosed=class extends Error{constructor(){super("AgentHarness was closed while the operation was active"),this.name="HarnessClosed"}};function matchError(error,matchers){let matcher=matchers[error._tag];return matcher(error)}import{awaitWithContext,BACKGROUND_CONTEXT,createContextKey,TODO_CONTEXT,withAbortSignal,withCancel,withContextValue,withoutAbortSignal}from"@earendil-works/chord/context";var TELEMETRY_CONTEXT_KEY=createContextKey("pi.telemetryContext");function getTelemetryContext(context){return context.value(TELEMETRY_CONTEXT_KEY)??NOOP_TELEMETRY_CONTEXT}function withTelemetryContext(telemetryContext,context){return withContextValue(TELEMETRY_CONTEXT_KEY,telemetryContext,context)}var AbortRequested=class extends Error{cancellation;constructor(cancellation){super("Abort requested"),this.name="AbortRequested",this.cancellation=cancellation}};function createGate(){let state2={status:"open"},controller=new AbortController,check=()=>{if(state2.status==="aborting")throw new AbortRequested(state2.cancellation);if(state2.status==="closed")throw state2.error};return{gate:{admit(invoke){return check(),invoke()},signal:controller.signal},control:{beginAbort(cancellation){state2.status==="open"&&(state2={status:"aborting",cancellation})},signalAbort(){state2.status!=="aborting"||controller.signal.aborted||controller.abort(new AbortRequested(state2.cancellation))},close(error){state2.status!=="closed"&&(state2={status:"closed",error},controller.signal.aborted||controller.abort(error))}}}}var SliceNotImplemented=class extends Error{constructor(operation){super(`${operation} is not implemented until its later AgentHarness slice`),this.name="SliceNotImplemented"}},Drive=class{operationId;completion;gate;context;waitForRetry;closeSignal;deferredPermits;control;closeController;resolveCompletion;rejectCompletion;constructor(options,context){this.operationId=options.operationId,this.context=withoutAbortSignal(context),this.waitForRetry=options.waitForRetry??!1,this.deferredPermits=options.pollDeferred===!0?1:0;let resolveCompletion,rejectCompletion;this.completion=new Promise((resolve17,reject)=>{resolveCompletion=resolve17,rejectCompletion=reject}),this.resolveCompletion=resolveCompletion,this.rejectCompletion=rejectCompletion,this.completion.catch(()=>{});let{gate,control}=createGate();this.gate=gate,this.control=control,this.closeController=new AbortController,this.closeSignal=this.closeController.signal}settle(outcome){this.resolveCompletion(outcome)}fail(error){this.rejectCompletion(error)}beginAbort(cancellation){this.control.beginAbort(cancellation)}signalAbort(){this.control.signalAbort()}closeGate(error){this.control.close(error),this.closeSignal.aborted||this.closeController.abort(error),this.rejectCompletion(error)}};var COMPACTION_SUMMARY_PREFIX2=`The conversation history before this point was compacted into the following summary:
|
|
718
|
+
`);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd);try{for(let file of readdirSync5(dir)){if(!file.endsWith(".jsonl"))continue;let path14=join18(dir,file),header=readSessionHeaderForDiscovery(path14);if(header?.id===id&&!(filterCwd&&!sessionCwdMatches(getSessionHeaderCwd(header),resolvedCwd)))return path14}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd),includeSession=session=>!filterCwd||sessionCwdMatches(session.cwd,resolvedCwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync10(sessionsDir))return[];let dirs=(await readdir(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join18(sessionsDir,entry.name)),allFiles=(await mapWithConcurrency(dirs,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async dir=>{try{return(await readdir(dir)).filter(file=>file.endsWith(".jsonl")).map(file=>join18(dir,file))}catch{return[]}},abortSignal)).flat(),candidates=await mapWithConcurrency(allFiles,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async path14=>{try{return{path:path14,stats:await stat(path14)}}catch{return{path:path14}}},abortSignal);candidates.sort((a,b2)=>(b2.stats?.mtimeMs??Number.NEGATIVE_INFINITY)-(a.stats?.mtimeMs??Number.NEGATIVE_INFINITY)||basename5(b2.path).localeCompare(basename5(a.path)));let totalFiles=candidates.length,loaded=0,firstCandidateLoaded=!1,partialSessions=[],results=await buildSessionInfosWithConcurrency(candidates,(info,index3)=>{loaded++,index3===0&&(firstCandidateLoaded=!0),info&&partialSessions.push(info);let publishPartial=firstCandidateLoaded&&(index3===0||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles);progress?.(loaded,totalFiles,publishPartial?sortSessionInfos([...partialSessions]):void 0)},abortSignal);return sortSessionInfos(results.filter(info=>info!==null))}catch{return abortSignal?.throwIfAborted(),[]}}};import{EventEmitter as EventEmitter3}from"node:events";function createEventBus(){let emitter=new EventEmitter3;return{emit:(channel,data)=>{emitter.emit(channel,data)},on:(channel,handler)=>{let safeHandler=async data=>{try{await handler(data)}catch(err2){console.error(`Event handler error (${channel}):`,err2)}};return emitter.on(channel,safeHandler),()=>emitter.off(channel,safeHandler)},clear:()=>{emitter.removeAllListeners()}}}var dist_exports2={};__export(dist_exports2,{AGENT_TELEMETRY_SCHEMAS:()=>AGENT_TELEMETRY_SCHEMAS,AI_TELEMETRY_SCHEMA:()=>AI_TELEMETRY_SCHEMA,Agent:()=>Agent,AgentHarness:()=>AgentHarness,BACKGROUND_CONTEXT:()=>BACKGROUND_CONTEXT,BRANCH_SUMMARY_PREFIX:()=>BRANCH_SUMMARY_PREFIX2,BRANCH_SUMMARY_SUFFIX:()=>BRANCH_SUMMARY_SUFFIX2,BranchSummaryError:()=>BranchSummaryError,COMPACTION_SUMMARY_PREFIX:()=>COMPACTION_SUMMARY_PREFIX2,COMPACTION_SUMMARY_SUFFIX:()=>COMPACTION_SUMMARY_SUFFIX2,Closed:()=>Closed,CompactionError:()=>CompactionError,DEFAULT_COMPACTION_SETTINGS:()=>DEFAULT_COMPACTION_SETTINGS,DEFAULT_MAX_BYTES:()=>DEFAULT_MAX_BYTES3,DEFAULT_MAX_LINES:()=>DEFAULT_MAX_LINES2,ExecutionError:()=>ExecutionError,FileError:()=>FileError,GREP_MAX_LINE_LENGTH:()=>GREP_MAX_LINE_LENGTH,HARNESS_TELEMETRY_SCHEMA:()=>HARNESS_TELEMETRY_SCHEMA,HarnessClosed:()=>HarnessClosed,HarnessFault:()=>HarnessFault,InMemoryTelemetryContext:()=>InMemoryTelemetryContext,InvalidLane:()=>InvalidLane,InvalidMessage:()=>InvalidMessage,InvalidNavigation:()=>InvalidNavigation,JSONL_STORAGE_VERSION:()=>JSONL_STORAGE_VERSION,JsonlSessionRepo:()=>JsonlSessionRepo,LaneBusy:()=>LaneBusy,MemorySessionRepo:()=>MemorySessionRepo,NOOP_TELEMETRY_CONTEXT:()=>NOOP_TELEMETRY_CONTEXT,NoActiveOperation:()=>NoActiveOperation,NoActiveRun:()=>NoActiveRun,NothingToCompact:()=>NothingToCompact,NothingToResume:()=>NothingToResume,OperationMismatch:()=>OperationMismatch,Result:()=>Result,SessionBranchExistsError:()=>SessionBranchExistsError,SessionInvalidBranchError:()=>SessionInvalidBranchError,SessionInvariantError:()=>SessionInvariantError,SessionPendingAssistantMessageError:()=>SessionPendingAssistantMessageError,SessionUnknownTargetError:()=>SessionUnknownTargetError,SliceNotImplemented:()=>SliceNotImplemented,StorageBackedSession:()=>StorageBackedSession,TODO_CONTEXT:()=>TODO_CONTEXT,TaggedError:()=>TaggedError,UnknownSkill:()=>UnknownSkill,UnknownTarget:()=>UnknownTarget,UnknownTemplate:()=>UnknownTemplate,agentLoop:()=>agentLoop,agentLoopContinue:()=>agentLoopContinue,appendList:()=>appendList,applyShellOutputUpdate:()=>applyShellOutputUpdate,awaitWithContext:()=>awaitWithContext,bashExecutionToText:()=>bashExecutionToText2,branchTip:()=>branchTip,branchTipInventoryPrefix:()=>branchTipInventoryPrefix,calculateContextTokens:()=>calculateContextTokens,collectEntriesForBranchSummary:()=>collectEntriesForBranchSummary,commitWrite:()=>commitWrite,compact:()=>compact,convertToLlm:()=>convertToLlm2,createBashTool:()=>createBashTool,createBranchSummaryMessage:()=>createBranchSummaryMessage2,createCompactionSummaryMessage:()=>createCompactionSummaryMessage2,createContextKey:()=>createContextKey,createCustomMessage:()=>createCustomMessage2,createEditTool:()=>createEditTool,createForkSnapshot:()=>createForkSnapshot,createReadTool:()=>createReadTool,createTypedSpanStarter:()=>createTypedSpanStarter,createWriteTool:()=>createWriteTool,defineTelemetrySchema:()=>defineTelemetrySchema,deleteList:()=>deleteList,deleteValue:()=>deleteValue,entryLabel:()=>entryLabel,err:()=>err,estimateContextTokens:()=>estimateContextTokens2,estimateTokens:()=>estimateTokens2,executeShellWithCapture:()=>executeShellWithCapture,findCutPoint:()=>findCutPoint,findTurnStartIndex:()=>findTurnStartIndex,formatPromptTemplateInvocation:()=>formatPromptTemplateInvocation,formatSize:()=>formatSize2,formatSkillInvocation:()=>formatSkillInvocation,formatSkillsForSystemPrompt:()=>formatSkillsForSystemPrompt,generateBranchSummary:()=>generateBranchSummary,generateSummary:()=>generateSummary,generateSummaryWithUsage:()=>generateSummaryWithUsage,getLastAssistantUsage:()=>getLastAssistantUsage,getOrThrow:()=>getOrThrow,getOrUndefined:()=>getOrUndefined,getTelemetryContext:()=>getTelemetryContext,insertEntry:()=>insertEntry,insertUsage:()=>insertUsage,laneConfig:()=>laneConfig,laneState:()=>laneState,list:()=>list,loadPromptTemplates:()=>loadPromptTemplates,loadSkills:()=>loadSkills2,loadSourcedPromptTemplates:()=>loadSourcedPromptTemplates,loadSourcedSkills:()=>loadSourcedSkills,matchError:()=>matchError,ok:()=>ok,operationMeta:()=>operationMeta,operationPreparation:()=>operationPreparation,operationPreparationPrefix:()=>operationPreparationPrefix,operationResult:()=>operationResult,operationScopeOf:()=>operationScopeOf,operationState:()=>operationState,operationToolArgs:()=>operationToolArgs,operationToolArgsPrefix:()=>operationToolArgsPrefix,operationToolMemo:()=>operationToolMemo,operationToolMemoPrefix:()=>operationToolMemoPrefix,parseCommandArgs:()=>parseCommandArgs,pendingAssistantFrames:()=>pendingAssistantFrames,pendingEntry:()=>pendingEntry,pendingToolOutput:()=>pendingToolOutput,pendingToolOutputPrefix:()=>pendingToolOutputPrefix,prepareBranchEntries:()=>prepareBranchEntries,prepareCompaction:()=>prepareCompaction,prepareStorageCommit:()=>prepareStorageCommit,projectForkCurrentStateWrite:()=>projectForkCurrentStateWrite,reduceLaneSnapshot:()=>reduceLaneSnapshot,resolveListReadOptions:()=>resolveListReadOptions,runAgentLoop:()=>runAgentLoop,runAgentLoopContinue:()=>runAgentLoopContinue,sanitizeBinaryOutput:()=>sanitizeShellOutput,serializeConversation:()=>serializeConversation,sessionName:()=>sessionName,setDefaultStreamFn:()=>setDefaultStreamFn,setValue:()=>setValue,shouldCompact:()=>shouldCompact,startAiSpan:()=>startAiSpan,startHarnessSpan:()=>startHarnessSpan,streamProxy:()=>streamProxy,substituteArgs:()=>substituteArgs,toError:()=>toError,truncateHead:()=>truncateHead2,truncateLine:()=>truncateLine2,truncateTail:()=>truncateTail2,utf8ByteLength:()=>utf8ByteLength,uuidv7:()=>uuidv7,validateCommittedWrites:()=>validateCommittedWrites,value:()=>value,withAbortSignal:()=>withAbortSignal,withCancel:()=>withCancel,withContextValue:()=>withContextValue,withTelemetryContext:()=>withTelemetryContext,withoutAbortSignal:()=>withoutAbortSignal});function startNoopSpan(_options,callback){try{return Promise.resolve(callback(noopTelemetrySpan))}catch(error){return Promise.reject(error)}}var noopTelemetrySpan={startSpan:startNoopSpan,addEvent:()=>{},setAttributes:()=>{},setStatus:()=>{}};Object.freeze(noopTelemetrySpan);var NOOP_TELEMETRY_CONTEXT=noopTelemetrySpan;function copyAttributeValue(value2){return Array.isArray(value2)?[...value2]:value2}function copyAttributes(attributes){let copy={};if(!attributes)return copy;for(let[name,value2]of Object.entries(attributes))value2!==void 0&&(copy[name]=copyAttributeValue(value2));return copy}function mergeAttributes(current,attributes){let merged=copyAttributes(current);for(let[name,value2]of Object.entries(attributes))value2!==void 0&&(merged[name]=copyAttributeValue(value2));return merged}function copyStatus(status){return status.status==="ok"?{status:"ok"}:status.error?{status:"error",error:{name:status.error.name,message:status.error.message}}:{status:"error"}}function automaticErrorStatus(error){try{if(error instanceof Error)return{status:"error",error:{name:error.name,message:error.message}}}catch{}return{status:"error"}}function settleSpan(state2,span,failed,error){span.settled||(failed&&!span.explicitStatus&&(span.status=automaticErrorStatus(error)),span.settled=!0,span.endSequence=state2.nextEndSequence++)}function createSpan(state2,parent,options){let name=options.name,attributes=copyAttributes(options.attributes);return{id:state2.nextSpanId++,parentId:parent?.id??null,name,attributes,events:[],status:{status:"ok"},explicitStatus:!1,settled:!1}}function startInMemorySpan(state2,parent,options,callback){if(parent?.settled)return NOOP_TELEMETRY_CONTEXT.startSpan(options,callback);let recordedSpan;try{recordedSpan=createSpan(state2,parent,options),state2.spans.push(recordedSpan)}catch{return NOOP_TELEMETRY_CONTEXT.startSpan(options,callback)}let span={startSpan:(childOptions,childCallback)=>startInMemorySpan(state2,recordedSpan,childOptions,childCallback),addEvent(name,attributes){if(!recordedSpan.settled)try{recordedSpan.events.push({name,attributes:copyAttributes(attributes)})}catch{}},setAttributes(attributes){if(!recordedSpan.settled)try{recordedSpan.attributes=mergeAttributes(recordedSpan.attributes,attributes)}catch{}},setStatus(status){if(!recordedSpan.settled)try{recordedSpan.status=copyStatus(status),recordedSpan.explicitStatus=!0}catch{}}},result2;try{result2=callback(span)}catch(error){return settleSpan(state2,recordedSpan,!0,error),Promise.reject(error)}return Promise.resolve(result2).then(value2=>(settleSpan(state2,recordedSpan,!1),value2),error=>{throw settleSpan(state2,recordedSpan,!0,error),error})}var InMemoryTelemetryContext=class{state={spans:[],nextSpanId:1,nextEndSequence:1};startSpan(options,callback){return startInMemorySpan(this.state,void 0,options,callback)}getSpans(){return this.state.spans.map(span=>({id:span.id,parentId:span.parentId,name:span.name,attributes:copyAttributes(span.attributes),events:span.events.map(event=>({name:event.name,attributes:copyAttributes(event.attributes)})),status:copyStatus(span.status),settled:span.settled,...span.endSequence===void 0?{}:{endSequence:span.endSequence}}))}};function defineTelemetrySchema(schema){return schema}function bindTypedSpanStarter(telemetryContext){return(name,attributes,callback)=>telemetryContext.startSpan({name,attributes},span=>callback(span,bindTypedSpanStarter(span)))}function createTypedSpanStarter(telemetryContext,_schemas){return bindTypedSpanStarter(telemetryContext)}var defaultStreamFn;function setDefaultStreamFn(streamFn){defaultStreamFn=streamFn}function getDefaultStreamFn(){if(!defaultStreamFn)throw new Error("No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().");return defaultStreamFn}function agentLoop(prompts,context,config,signal,streamFn){let stream2=createAgentStream();return runAgentLoop(prompts,context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}function agentLoopContinue(context,config,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let stream2=createAgentStream();return runAgentLoopContinue(context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}async function runAgentLoop(prompts,context,config,emit,signal,streamFn){let initialMessages=declareToolChanges(context,prompts),newMessages=[...initialMessages],currentContext={...context,messages:[...context.messages,...initialMessages]};await emit({type:"agent_start"}),await emit({type:"turn_start"});for(let message of initialMessages)await emit({type:"message_start",message}),await emit({type:"message_end",message});return await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}async function runAgentLoopContinue(context,config,emit,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let newMessages=[],currentContext={...context};return await emit({type:"agent_start"}),await emit({type:"turn_start"}),await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}function createAgentStream(){return new EventStream(event=>event.type==="agent_end",event=>event.type==="agent_end"?event.messages:[])}async function runLoop(initialContext,newMessages,initialConfig,signal,emit,streamFunction){let currentContext=initialContext,config=initialConfig,lastCompletedTurn,explicitContinuation=!1,pendingMessages=await config.getSteeringMessages?.()||[];for(;;){let hasMoreToolCalls=!0;for(;hasMoreToolCalls||pendingMessages.length>0;){let preparedMessages=[];if(lastCompletedTurn){let nextTurnSnapshot=await config.prepareNextTurn?.(lastCompletedTurn);nextTurnSnapshot&&(currentContext=nextTurnSnapshot.context??currentContext,preparedMessages=nextTurnSnapshot.messages??[],config={...config,model:nextTurnSnapshot.model??config.model,reasoning:nextTurnSnapshot.thinkingLevel===void 0?config.reasoning:nextTurnSnapshot.thinkingLevel==="off"?void 0:nextTurnSnapshot.thinkingLevel}),pendingMessages.length===0&&(pendingMessages=await config.getSteeringMessages?.()||[]),await emit({type:"turn_start"})}for(let message2 of declareToolChanges(currentContext,[...preparedMessages,...pendingMessages]))await emit({type:"message_start",message:message2}),await emit({type:"message_end",message:message2}),currentContext.messages.push(message2),newMessages.push(message2);pendingMessages=[];let requestUpdate=await config.prepareRequest?.({context:currentContext,model:config.model,thinkingLevel:config.reasoning??"off"},signal);requestUpdate&&(currentContext=requestUpdate.context??currentContext,config={...config,model:requestUpdate.model??config.model,reasoning:requestUpdate.thinkingLevel===void 0?config.reasoning:requestUpdate.thinkingLevel==="off"?void 0:requestUpdate.thinkingLevel});let message=await streamAssistantResponse(currentContext,config,signal,emit,streamFunction);if(newMessages.push(message),message.stopReason==="error"||message.stopReason==="aborted"){lastCompletedTurn={message,toolResults:[],context:currentContext,newMessages},await config.finishTurn?.(lastCompletedTurn,signal),await emit({type:"turn_end",message,toolResults:[]}),await emit({type:"agent_end",messages:newMessages});return}let toolCalls=message.content.filter(c=>c.type==="toolCall"),toolResults=[];if(hasMoreToolCalls=!1,toolCalls.length>0){let executedToolBatch=message.stopReason==="length"?await failToolCallsFromTruncatedMessage(toolCalls,emit):await executeToolCalls(currentContext,message,config,signal,emit);toolResults.push(...executedToolBatch.messages),hasMoreToolCalls=!executedToolBatch.terminate;for(let result2 of toolResults)currentContext.messages.push(result2),newMessages.push(result2)}lastCompletedTurn={message,toolResults,context:currentContext,newMessages};let decision=await config.finishTurn?.(lastCompletedTurn,signal);if(await emit({type:"turn_end",message,toolResults}),decision?.action==="end"){await emit({type:"agent_end",messages:newMessages});return}explicitContinuation=decision?.action==="continue",pendingMessages=await config.getSteeringMessages?.()||[],(hasMoreToolCalls||pendingMessages.length>0)&&(explicitContinuation=!1)}let followUpMessages=await config.getFollowUpMessages?.()||[];if(followUpMessages.length>0){explicitContinuation=!1,pendingMessages=followUpMessages;continue}if(explicitContinuation){explicitContinuation=!1;continue}break}await emit({type:"agent_end",messages:newMessages})}function declareToolChanges(context,pendingMessages){let systemIndex=-1;for(let i=pendingMessages.length-1;i>=0;i--)if(pendingMessages[i].role==="system"){systemIndex=i;break}let pending=pendingMessages[systemIndex],baseline=pending?pendingMessages.map((message,index4)=>index4===systemIndex?withToolChanges(pending,NO_CHANGES):message):pendingMessages,changes=getToolStateChanges(getCurrentTools([...context.messages,...baseline]),(context.tools??[]).map(toToolDeclaration)),unchanged=changes.toolsAdded.length===0&&changes.toolsRemoved.length===0;if(pending)return unchanged&&!pending.toolsAdded?.length&&!pending.toolsRemoved?.length?pendingMessages:baseline.map((message,index4)=>index4===systemIndex?withToolChanges(pending,changes):message);if(unchanged)return pendingMessages;let update=withToolChanges({role:"system",content:"",timestamp:Date.now()},changes),insertIndex=pendingMessages.findIndex(message=>message.role!=="system"),index3=insertIndex===-1?pendingMessages.length:insertIndex;return[...pendingMessages.slice(0,index3),update,...pendingMessages.slice(index3)]}var NO_CHANGES={toolsAdded:[],toolsRemoved:[]};function withToolChanges(message,{toolsAdded,toolsRemoved}){let{toolsAdded:_added,toolsRemoved:_removed,...rest}=message;return{...rest,...toolsAdded.length>0?{toolsAdded}:{},...toolsRemoved.length>0?{toolsRemoved}:{}}}async function streamAssistantResponse(context,config,signal,emit,streamFunction){let messages=context.messages;config.transformContext&&(messages=await config.transformContext(messages,signal));let llmMessages=await config.convertToLlm(messages),llmContext=normalizeContext({messages:llmMessages}),resolvedApiKey=(config.getApiKey?await config.getApiKey(config.model.provider):void 0)||config.apiKey,response=await streamFunction(config.model,llmContext,{...config,apiKey:resolvedApiKey,signal}),partialMessage=null,addedPartial=!1;for await(let event of response)switch(event.type){case"start":partialMessage=event.partial,context.messages.push(partialMessage),addedPartial=!0,await emit({type:"message_start",message:{...partialMessage}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":partialMessage&&(partialMessage=event.partial,context.messages[context.messages.length-1]=partialMessage,await emit({type:"message_update",assistantMessageEvent:event,message:{...partialMessage}}));break;case"done":case"error":{let finalMessage2=await response.result();return addedPartial?context.messages[context.messages.length-1]=finalMessage2:context.messages.push(finalMessage2),addedPartial||await emit({type:"message_start",message:{...finalMessage2}}),await emit({type:"message_end",message:finalMessage2}),finalMessage2}}let finalMessage=await response.result();return addedPartial?context.messages[context.messages.length-1]=finalMessage:(context.messages.push(finalMessage),await emit({type:"message_start",message:{...finalMessage}})),await emit({type:"message_end",message:finalMessage}),finalMessage}async function failToolCallsFromTruncatedMessage(toolCalls,emit){let messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let finalized={toolCall,result:createErrorToolResult(`Tool call "${toolCall.name}" was not executed: the response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`),isError:!0};await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:!1}}async function executeToolCalls(currentContext,assistantMessage,config,signal,emit){let toolCalls=assistantMessage.content.filter(c=>c.type==="toolCall"),hasSequentialToolCall=toolCalls.some(tc=>currentContext.tools?.find(t=>t.name===tc.name)?.executionMode==="sequential");return config.toolExecution==="sequential"||hasSequentialToolCall?executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit):executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit)}async function executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[],messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal),finalized;if(preparation.kind==="immediate")finalized={toolCall,result:preparation.result,isError:preparation.isError};else{let executed=await executePreparedToolCall(preparation,signal,emit);finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal)}await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);if(await emitToolResultMessage(toolResultMessage,emit),finalizedCalls.push(finalized),messages.push(toolResultMessage),signal?.aborted)break}return{messages,terminate:shouldTerminateToolBatch(finalizedCalls)}}async function executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal);if(preparation.kind==="immediate"){let finalized={toolCall,result:preparation.result,isError:preparation.isError};if(await emitToolExecutionEnd(finalized,emit),finalizedCalls.push(finalized),signal?.aborted)break;continue}if(finalizedCalls.push(async()=>{if(signal?.aborted){let finalized2={toolCall,result:createErrorToolResult("Operation aborted"),isError:!0};return await emitToolExecutionEnd(finalized2,emit),finalized2}let executed=await executePreparedToolCall(preparation,signal,emit),finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal);return await emitToolExecutionEnd(finalized,emit),finalized}),signal?.aborted)break}let orderedFinalizedCalls=await Promise.all(finalizedCalls.map(entry=>typeof entry=="function"?entry():Promise.resolve(entry))),messages=[];for(let finalized of orderedFinalizedCalls){let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:shouldTerminateToolBatch(orderedFinalizedCalls)}}function shouldTerminateToolBatch(finalizedCalls){return finalizedCalls.length>0&&finalizedCalls.every(finalized=>finalized.result.terminate===!0)}function prepareToolCallArguments(tool,toolCall){if(!tool.prepareArguments)return toolCall;let preparedArguments=tool.prepareArguments(toolCall.arguments);return preparedArguments===toolCall.arguments?toolCall:{...toolCall,arguments:preparedArguments}}async function prepareToolCall(currentContext,assistantMessage,toolCall,config,signal){let tool=currentContext.tools?.find(t=>t.name===toolCall.name);if(!tool)return{kind:"immediate",result:createErrorToolResult(`Tool ${toolCall.name} not found`),isError:!0};try{let preparedToolCall=prepareToolCallArguments(tool,toolCall),validatedArgs=validateToolArguments(tool,preparedToolCall);if(config.beforeToolCall){let beforeResult=await config.beforeToolCall({assistantMessage,toolCall,args:validatedArgs,context:currentContext},signal);if(signal?.aborted)return{kind:"immediate",result:createErrorToolResult("Operation aborted"),isError:!0};if(beforeResult?.block){let result2=createErrorToolResult(beforeResult.reason||"Tool execution was blocked");return beforeResult.terminate===!0&&(result2.terminate=!0),{kind:"immediate",result:result2,isError:!0}}}return signal?.aborted?{kind:"immediate",result:createErrorToolResult("Operation aborted"),isError:!0}:{kind:"prepared",toolCall,tool,args:validatedArgs}}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}}async function executePreparedToolCall(prepared,signal,emit){let updateEvents=[],acceptingUpdates=!0;try{let result2=await prepared.tool.execute(prepared.toolCall.id,prepared.args,signal,partialResult=>{acceptingUpdates&&updateEvents.push(Promise.resolve(emit({type:"tool_execution_update",toolCallId:prepared.toolCall.id,toolName:prepared.toolCall.name,args:prepared.toolCall.arguments,partialResult})))});return acceptingUpdates=!1,await Promise.all(updateEvents),{result:result2,isError:!1}}catch(error){return acceptingUpdates=!1,await Promise.all(updateEvents),{result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}finally{acceptingUpdates=!1}}async function finalizeExecutedToolCall(currentContext,assistantMessage,prepared,executed,config,signal){let result2=executed.result,isError=executed.isError;if(config.afterToolCall)try{let afterResult=await config.afterToolCall({assistantMessage,toolCall:prepared.toolCall,args:prepared.args,result:result2,isError,context:currentContext},signal);afterResult&&(result2={...result2,content:afterResult.content??result2.content,details:afterResult.details??result2.details,usage:afterResult.usage??result2.usage,terminate:afterResult.terminate??result2.terminate},isError=afterResult.isError??isError)}catch(error){result2=createErrorToolResult(error instanceof Error?error.message:String(error)),isError=!0}return{toolCall:prepared.toolCall,result:result2,isError}}function createErrorToolResult(message){return{content:[{type:"text",text:message}],details:{}}}async function emitToolExecutionEnd(finalized,emit){await emit({type:"tool_execution_end",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,result:finalized.result,isError:finalized.isError})}function createToolResultMessage(finalized){return{role:"toolResult",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,content:finalized.result.content??[],details:finalized.result.details,usage:finalized.result.usage,isError:finalized.isError,timestamp:Date.now()}}async function emitToolResultMessage(toolResultMessage,emit){await emit({type:"message_start",message:toolResultMessage}),await emit({type:"message_end",message:toolResultMessage})}function defaultConvertToLlm(messages){return messages.filter(message=>message.role==="system"||message.role==="user"||message.role==="assistant"||message.role==="toolResult")}var EMPTY_USAGE={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},DEFAULT_MODEL={id:"unknown",name:"unknown",api:"unknown",provider:"unknown",baseUrl:"",reasoning:!1,input:[],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:0,maxTokens:0};function createMutableAgentState(initialState){let tools=initialState?.tools?.slice()??[],messages=initialState?.messages?.slice()??[],initialMessage=createInitialSystemMessage(initialState?.systemPrompt,tools.map(toToolDeclaration));return messages[0]?.role!=="system"&&initialMessage&&messages.unshift(initialMessage),{get systemPrompt(){return getCurrentSystemPrompt(messages)},model:initialState?.model??DEFAULT_MODEL,thinkingLevel:initialState?.thinkingLevel??"off",get tools(){return tools},set tools(nextTools){tools=nextTools.slice()},get messages(){return messages},set messages(nextMessages){messages=nextMessages.slice()},isStreaming:!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:void 0}}var PendingMessageQueue=class{messages=[];mode;constructor(mode){this.mode=mode}enqueue(message){this.messages.push(message)}hasItems(){return this.messages.length>0}peek(){if(this.mode==="all")return this.messages.slice();let first=this.messages[0];return first?[first]:[]}drain(){let drained=this.peek();return this.messages=this.messages.slice(drained.length),drained}clear(){this.messages=[]}},Agent=class{_state;listeners=new Set;steeringQueue;followUpQueue;convertToLlm;transformContext;streamFunction;getApiKey;onPayload;onResponse;beforeToolCall;afterToolCall;finishTurn;prepareRequest;prepareNextTurn;prepareNextTurnWithContext;activeRun;sessionId;thinkingBudgets;transport;maxRetryDelayMs;toolExecution;constructor(options){let runtimeOptions=options??{};this._state=createMutableAgentState(runtimeOptions.initialState),this.convertToLlm=runtimeOptions.convertToLlm??defaultConvertToLlm,this.transformContext=runtimeOptions.transformContext,this.streamFunction=runtimeOptions.streamFn??getDefaultStreamFn(),this.getApiKey=runtimeOptions.getApiKey,this.onPayload=runtimeOptions.onPayload,this.onResponse=runtimeOptions.onResponse,this.beforeToolCall=runtimeOptions.beforeToolCall,this.afterToolCall=runtimeOptions.afterToolCall,this.finishTurn=runtimeOptions.finishTurn,this.prepareRequest=runtimeOptions.prepareRequest,this.prepareNextTurn=runtimeOptions.prepareNextTurn,this.prepareNextTurnWithContext=runtimeOptions.prepareNextTurnWithContext,this.steeringQueue=new PendingMessageQueue(runtimeOptions.steeringMode??"one-at-a-time"),this.followUpQueue=new PendingMessageQueue(runtimeOptions.followUpMode??"one-at-a-time"),this.sessionId=runtimeOptions.sessionId,this.thinkingBudgets=runtimeOptions.thinkingBudgets,this.transport=runtimeOptions.transport??"auto",this.maxRetryDelayMs=runtimeOptions.maxRetryDelayMs,this.toolExecution=runtimeOptions.toolExecution??"parallel"}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}get state(){return this._state}set steeringMode(mode){this.steeringQueue.mode=mode}get steeringMode(){return this.steeringQueue.mode}set followUpMode(mode){this.followUpQueue.mode=mode}get followUpMode(){return this.followUpQueue.mode}steer(message){this.steeringQueue.enqueue(message)}followUp(message){this.followUpQueue.enqueue(message)}clearSteeringQueue(){this.steeringQueue.clear()}clearFollowUpQueue(){this.followUpQueue.clear()}clearAllQueues(){this.clearSteeringQueue(),this.clearFollowUpQueue()}hasQueuedMessages(){return this.steeringQueue.hasItems()||this.followUpQueue.hasItems()}peekQueuedMessages(){let steering=this.steeringQueue.peek();return steering.length>0?steering:this.followUpQueue.peek()}get signal(){return this.activeRun?.abortController.signal}abort(){this.activeRun?.abortController.abort()}waitForIdle(){return this.activeRun?.promise??Promise.resolve()}reset(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before resetting.");let baseline=getCurrentSystemMessage(this._state.messages);this._state.messages=baseline?[baseline]:[],this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this._state.errorMessage=void 0,this.clearFollowUpQueue(),this.clearSteeringQueue()}async prompt(input2,images){if(this.activeRun)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");let messages=this.normalizePromptInput(input2,images);await this.runPromptMessages(messages)}async continue(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before continuing.");let lastMessage=this._state.messages[this._state.messages.length-1];if(!lastMessage||this._state.messages.every(message=>message.role==="system"))throw new Error("No messages to continue from");if(lastMessage.role==="assistant"){let queuedSteering=this.steeringQueue.drain();if(queuedSteering.length>0){await this.runPromptMessages(queuedSteering,{skipInitialSteeringPoll:!0});return}let queuedFollowUps=this.followUpQueue.drain();if(queuedFollowUps.length>0){await this.runPromptMessages(queuedFollowUps);return}throw new Error("Cannot continue from message role: assistant")}await this.runContinuation()}normalizePromptInput(input2,images){if(Array.isArray(input2))return input2;if(typeof input2!="string")return[input2];let content=[{type:"text",text:input2}];return images&&images.length>0&&content.push(...images),[{role:"user",content,timestamp:Date.now()}]}async runPromptMessages(messages,options={}){await this.runWithLifecycle(async signal=>{await runAgentLoop(messages,this.createContextSnapshot(),this.createLoopConfig(options),event=>this.processEvents(event),signal,this.streamFunction)})}async runContinuation(){await this.runWithLifecycle(async signal=>{await runAgentLoopContinue(this.createContextSnapshot(),this.createLoopConfig(),event=>this.processEvents(event),signal,this.streamFunction)})}createContextSnapshot(){return{messages:this._state.messages.slice(),tools:this._state.tools.slice()}}createLoopConfig(options={}){let skipInitialSteeringPoll=options.skipInitialSteeringPoll===!0;return{model:this._state.model,reasoning:this._state.thinkingLevel==="off"?void 0:this._state.thinkingLevel,sessionId:this.sessionId,onPayload:this.onPayload,onResponse:this.onResponse,transport:this.transport,thinkingBudgets:this.thinkingBudgets,maxRetryDelayMs:this.maxRetryDelayMs,toolExecution:this.toolExecution,beforeToolCall:this.beforeToolCall,afterToolCall:this.afterToolCall,finishTurn:this.finishTurn,prepareRequest:this.prepareRequest,prepareNextTurn:this.prepareNextTurnWithContext||this.prepareNextTurn?async context=>this.prepareNextTurnWithContext?await this.prepareNextTurnWithContext(context,this.signal):await this.prepareNextTurn?.(this.signal):void 0,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>skipInitialSteeringPoll?(skipInitialSteeringPoll=!1,[]):this.steeringQueue.drain(),getFollowUpMessages:async()=>this.followUpQueue.drain()}}async runWithLifecycle(executor){if(this.activeRun)throw new Error("Agent is already processing.");let abortController=new AbortController,resolvePromise=()=>{},promise=new Promise(resolve17=>{resolvePromise=resolve17});this.activeRun={promise,resolve:resolvePromise,abortController},this._state.isStreaming=!0,this._state.streamingMessage=void 0,this._state.errorMessage=void 0;try{await executor(abortController.signal)}catch(error){await this.handleRunFailure(error,abortController.signal.aborted)}finally{this.finishRun()}}async handleRunFailure(error,aborted){let failureMessage={role:"assistant",content:[{type:"text",text:""}],api:this._state.model.api,provider:this._state.model.provider,model:this._state.model.id,usage:EMPTY_USAGE,stopReason:aborted?"aborted":"error",errorMessage:error instanceof Error?error.message:String(error),timestamp:Date.now()};await this.processEvents({type:"message_start",message:failureMessage}),await this.processEvents({type:"message_end",message:failureMessage}),await this.processEvents({type:"turn_end",message:failureMessage,toolResults:[]}),await this.processEvents({type:"agent_end",messages:[failureMessage]})}finishRun(){this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this.activeRun?.resolve(),this.activeRun=void 0}async processEvents(event){switch(event.type){case"message_start":this._state.streamingMessage=event.message;break;case"message_update":this._state.streamingMessage=event.message;break;case"message_end":this._state.streamingMessage=void 0,this._state.messages.push(event.message);break;case"tool_execution_start":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.add(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"tool_execution_end":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.delete(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"turn_end":event.message.role==="assistant"&&event.message.errorMessage&&(this._state.errorMessage=event.message.errorMessage);break;case"agent_end":this._state.streamingMessage=void 0;break}let signal=this.activeRun?.abortController.signal;if(!signal)throw new Error("Agent listener invoked outside active run");for(let listener of this.listeners)await listener(event,signal)}};var Result={ok(value2){return{ok:!0,value:value2}},err(error){return{ok:!1,error}},isOk(result2){return result2.ok},isErr(result2){return!result2.ok}};function TaggedError(tag){class TaggedErrorClass extends Error{_tag=tag;constructor(props){super(props.message),this.name=tag,Object.assign(this,props)}toJSON(){let payload={};for(let key of Object.keys(this))key!=="_tag"&&(payload[key]=this[key]);return{_tag:tag,message:this.message,...payload}}static is(value2){return value2 instanceof TaggedErrorClass}}return TaggedErrorClass}var LaneBusy=class extends TaggedError("LaneBusy"){},OperationMismatch=class extends TaggedError("OperationMismatch"){},NoActiveRun=class extends TaggedError("NoActiveRun"){},NoActiveOperation=class extends TaggedError("NoActiveOperation"){},NothingToResume=class extends TaggedError("NothingToResume"){},NothingToCompact=class extends TaggedError("NothingToCompact"){},InvalidMessage=class extends TaggedError("InvalidMessage"){},InvalidNavigation=class extends TaggedError("InvalidNavigation"){},UnknownSkill=class extends TaggedError("UnknownSkill"){},UnknownTemplate=class extends TaggedError("UnknownTemplate"){},UnknownTarget=class extends TaggedError("UnknownTarget"){},InvalidLane=class extends TaggedError("InvalidLane"){},Closed=class extends TaggedError("Closed"){},HarnessFault=class extends Error{cause;constructor(message,cause){super(message),this.name="HarnessFault",this.cause=cause}},HarnessClosed=class extends Error{constructor(){super("AgentHarness was closed while the operation was active"),this.name="HarnessClosed"}};function matchError(error,matchers){let matcher=matchers[error._tag];return matcher(error)}import{awaitWithContext,BACKGROUND_CONTEXT,createContextKey,TODO_CONTEXT,withAbortSignal,withCancel,withContextValue,withoutAbortSignal}from"@earendil-works/chord/context";var TELEMETRY_CONTEXT_KEY=createContextKey("pi.telemetryContext");function getTelemetryContext(context){return context.value(TELEMETRY_CONTEXT_KEY)??NOOP_TELEMETRY_CONTEXT}function withTelemetryContext(telemetryContext,context){return withContextValue(TELEMETRY_CONTEXT_KEY,telemetryContext,context)}var AbortRequested=class extends Error{cancellation;constructor(cancellation){super("Abort requested"),this.name="AbortRequested",this.cancellation=cancellation}};function createGate(){let state2={status:"open"},controller=new AbortController,check=()=>{if(state2.status==="aborting")throw new AbortRequested(state2.cancellation);if(state2.status==="closed")throw state2.error};return{gate:{admit(invoke){return check(),invoke()},signal:controller.signal},control:{beginAbort(cancellation){state2.status==="open"&&(state2={status:"aborting",cancellation})},signalAbort(){state2.status!=="aborting"||controller.signal.aborted||controller.abort(new AbortRequested(state2.cancellation))},close(error){state2.status!=="closed"&&(state2={status:"closed",error},controller.signal.aborted||controller.abort(error))}}}}var SliceNotImplemented=class extends Error{constructor(operation){super(`${operation} is not implemented until its later AgentHarness slice`),this.name="SliceNotImplemented"}},Drive=class{operationId;completion;gate;context;waitForRetry;closeSignal;deferredPermits;control;closeController;resolveCompletion;rejectCompletion;constructor(options,context){this.operationId=options.operationId,this.context=withoutAbortSignal(context),this.waitForRetry=options.waitForRetry??!1,this.deferredPermits=options.pollDeferred===!0?1:0;let resolveCompletion,rejectCompletion;this.completion=new Promise((resolve17,reject)=>{resolveCompletion=resolve17,rejectCompletion=reject}),this.resolveCompletion=resolveCompletion,this.rejectCompletion=rejectCompletion,this.completion.catch(()=>{});let{gate,control}=createGate();this.gate=gate,this.control=control,this.closeController=new AbortController,this.closeSignal=this.closeController.signal}settle(outcome){this.resolveCompletion(outcome)}fail(error){this.rejectCompletion(error)}beginAbort(cancellation){this.control.beginAbort(cancellation)}signalAbort(){this.control.signalAbort()}closeGate(error){this.control.close(error),this.closeSignal.aborted||this.closeController.abort(error),this.rejectCompletion(error)}};var COMPACTION_SUMMARY_PREFIX2=`The conversation history before this point was compacted into the following summary:
|
|
719
719
|
|
|
720
720
|
<summary>
|
|
721
721
|
`,COMPACTION_SUMMARY_SUFFIX2=`
|
|
@@ -1118,7 +1118,7 @@ Additional focus: ${customInstructions}`:instructions=BRANCH_SUMMARY_PROMPT2;let
|
|
|
1118
1118
|
${conversationText}
|
|
1119
1119
|
</conversation>
|
|
1120
1120
|
|
|
1121
|
-
${instructions}`}],timestamp:Date.now()}],maxTokens=Math.min(4096,model.maxTokens>0?model.maxTokens:Number.POSITIVE_INFINITY),context=normalizeContext({systemPrompt:SUMMARIZATION_SYSTEM_PROMPT2,messages:summarizationMessages}),response=await completeSummarization(model,context,{apiKey,headers,env:env2,signal,maxTokens},streamFn,retry,callbacks);if(response.stopReason==="aborted")return{aborted:!0};let failure=getSummarizationFailure(response,"Branch summarization");if(failure)return{error:failure};if(response.content.some(block=>block.type==="toolCall"))return{error:"Branch summarization attempted to call a tool"};let summary=contentText(response.content);summary=BRANCH_SUMMARY_PREAMBLE2+summary;let{readFiles,modifiedFiles}=computeFileLists2(fileOps);return summary+=formatFileOperations2(readFiles,modifiedFiles),{summary:summary||"No summary generated",usage:response.usage,readFiles,modifiedFiles}}var RECEIVED_ARGUMENTS_MARKER=`
|
|
1121
|
+
${instructions}`}],timestamp:Date.now()}],maxTokens=Math.min(4096,model.maxTokens>0?model.maxTokens:Number.POSITIVE_INFINITY),context=normalizeContext({systemPrompt:SUMMARIZATION_SYSTEM_PROMPT2,messages:summarizationMessages}),response=await completeSummarization(model,context,{apiKey,headers,env:env2,signal,maxTokens},streamFn,retry,callbacks);if(response.stopReason==="aborted")return{aborted:!0};let failure=getSummarizationFailure(response,"Branch summarization");if(failure)return{error:failure};if(response.content.some(block=>block.type==="toolCall"))return{error:"Branch summarization attempted to call a tool"};let summary=contentText(response.content);summary=BRANCH_SUMMARY_PREAMBLE2+summary;let{readFiles,modifiedFiles}=computeFileLists2(fileOps);return summary+=formatFileOperations2(readFiles,modifiedFiles),{summary:summary||"No summary generated",usage:response.usage,readFiles,modifiedFiles}}var STALE_EXTENSION_CONTEXT_PREFIX="This extension ctx is stale";function isStaleExtensionContextError(error){return error instanceof Error&&error.message.startsWith(STALE_EXTENSION_CONTEXT_PREFIX)}function defineTool(tool){return tool}function isBashToolResult(e){return e.toolName==="bash"}function isPowerShellToolResult(e){return e.toolName==="powershell"}function isReadToolResult(e){return e.toolName==="read"}function isEditToolResult(e){return e.toolName==="edit"}function isWriteToolResult(e){return e.toolName==="write"}function isGrepToolResult(e){return e.toolName==="grep"}function isFindToolResult(e){return e.toolName==="find"}function isLsToolResult(e){return e.toolName==="ls"}function isToolCallEventType(toolName,event){return event.toolName===toolName}var RECEIVED_ARGUMENTS_MARKER=`
|
|
1122
1122
|
|
|
1123
1123
|
Received arguments:
|
|
1124
1124
|
`,HINT_MARKER=`
|
|
@@ -1127,19 +1127,20 @@ Hint: `,RECEIVED_ARGUMENTS_MAX_BYTES=2*1024,RECEIVED_ARGUMENTS_MAX_LINES=40,FIEL
|
|
|
1127
1127
|
|
|
1128
1128
|
Hint: ${hints.join(`
|
|
1129
1129
|
Hint: `)}`:head;if(markerIndex!==-1){let bounded=truncateHead(received,{maxBytes:RECEIVED_ARGUMENTS_MAX_BYTES,maxLines:RECEIVED_ARGUMENTS_MAX_LINES});enriched+=`${RECEIVED_ARGUMENTS_MARKER}${bounded.content}`,bounded.truncated&&(enriched+=`
|
|
1130
|
-
\u2026 (arguments truncated)`)}return new Error(enriched)}function wrapPrepareArguments(definition){let tool={name:definition.name,description:definition.description,parameters:definition.parameters};return raw=>{let args=definition.prepareArguments?definition.prepareArguments(raw):raw;try{validateToolArguments(tool,{type:"toolCall",id:"",name:definition.name,arguments:args})}catch(error){throw enrichValidationError(error,definition.parameters,args)}return args}}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,constrainedSampling:definition.constrainedSampling,
|
|
1130
|
+
\u2026 (arguments truncated)`)}return new Error(enriched)}function wrapPrepareArguments(definition){let tool={name:definition.name,description:definition.description,parameters:definition.parameters};return raw=>{let args=definition.prepareArguments?definition.prepareArguments(raw):raw;try{validateToolArguments(tool,{type:"toolCall",id:"",name:definition.name,arguments:args})}catch(error){throw enrichValidationError(error,definition.parameters,args)}return args}}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,constrainedSampling:definition.constrainedSampling,prepareArguments:wrapPrepareArguments(definition),executionMode:definition.executionMode,execute:(toolCallId,params,signal,onUpdate,ctx)=>definition.execute(toolCallId,params,signal,onUpdate,ctx??ctxFactory?.())}}function createToolDefinitionFromAgentTool(tool){return{name:tool.name,label:tool.label,description:tool.description,parameters:tool.parameters,constrainedSampling:tool.constrainedSampling,prepareArguments:tool.prepareArguments,executionMode:tool.executionMode,execute:async(toolCallId,params,signal,onUpdate)=>tool.execute(toolCallId,params,signal,onUpdate)}}function wrapRegisteredTool(registeredTool,runner){return wrapToolDefinition(registeredTool.definition,()=>runner.createContext())}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import*as fs5 from"node:fs";import{createRequire as createRequire4}from"node:module";import*as path7 from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import{spawn as spawn3}from"node:child_process";async function execCommand(command,args,cwd,options){return new Promise(resolve17=>{let proc=spawn3(command,args,{cwd,shell:!1,stdio:["ignore","pipe","pipe"]}),stdout="",stderr="",killed=!1,timeoutId,killProcess=()=>{killed||(killed=!0,proc.kill("SIGTERM"),setTimeout(()=>{proc.killed||proc.kill("SIGKILL")},5e3))};options?.signal&&(options.signal.aborted?killProcess():options.signal.addEventListener("abort",killProcess,{once:!0})),options?.timeout&&options.timeout>0&&(timeoutId=setTimeout(()=>{killProcess()},options.timeout)),proc.stdout?.on("data",data=>{stdout+=data.toString()}),proc.stderr?.on("data",data=>{stderr+=data.toString()}),waitForChildProcess(proc).then(code=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve17({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve17({stdout,stderr,code:1,killed})})})}var ENABLED=process.env.PI_TIMING==="1",timingNamespaces=new Map;function resetTimings(namespace="main"){ENABLED&&timingNamespaces.set(namespace,{timings:[],lastTime:Date.now()})}function time(label,namespace="main"){if(!ENABLED)return;let now=Date.now();timingNamespaces.has(namespace)||resetTimings(namespace);let timingNamespace=timingNamespaces.get(namespace);timingNamespace.timings.push({label,ms:now-timingNamespace.lastTime}),timingNamespace.lastTime=now}function printTimingGroup(title,timings){let printableTimings=timings.filter(timing=>timing.ms>=0);if(printableTimings.length!==0){console.error(`
|
|
1131
1131
|
--- ${title} ---`);for(let t of printableTimings)console.error(` ${t.label}: ${t.ms}ms`);console.error(` TOTAL: ${printableTimings.reduce((a,b2)=>a+b2.ms,0)}ms`),console.error(`${"-".repeat(title.length+8)}
|
|
1132
|
-
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire4(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-W3OGMIX7.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],assertActive:()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??STALE_EXTENSION_CONTEXT_MESSAGE;for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){assertActive(),extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value2]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value2);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=extensionPath.startsWith("<")&&extensionPath.endsWith(">")?extensionPath.slice(1,-1).split(":")[0]||"temporary":"local",baseDir=extensionPath.startsWith("<")?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err2){return{extension:null,error:`Failed to load extension: ${err2 instanceof Error?err2.message:String(err2)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId2){return this.runtime.getModel(provider,modelId2)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}import{constants as constants2}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn4}from"child_process";import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";function ansiRegex({onlyFirst=!1}={}){let pattern="(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";return new RegExp(pattern,onlyFirst?void 0:"g")}var regex=ansiRegex();function stripAnsi(value2){if(typeof value2!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value2}\``);return!value2.includes("\x1B")&&!value2.includes("\x9B")?value2:value2.replace(regex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value2){return typeof value2=="string"?value2:value2==null?"":null}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
|
|
1132
|
+
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire4(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-KUEIEAZN.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],assertActive:()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){assertActive(),extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value2]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value2);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=extensionPath.startsWith("<")&&extensionPath.endsWith(">")?extensionPath.slice(1,-1).split(":")[0]||"temporary":"local",baseDir=extensionPath.startsWith("<")?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err2){return{extension:null,error:`Failed to load extension: ${err2 instanceof Error?err2.message:String(err2)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId2){return this.runtime.getModel(provider,modelId2)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}import{constants as constants2}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn4}from"child_process";import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";function ansiRegex({onlyFirst=!1}={}){let pattern="(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";return new RegExp(pattern,onlyFirst?void 0:"g")}var regex=ansiRegex();function stripAnsi(value2){if(typeof value2!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value2}\``);return!value2.includes("\x1B")&&!value2.includes("\x9B")?value2:value2.replace(regex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value2){return typeof value2=="string"?value2:value2==null?"":null}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
|
|
1133
1133
|
`),caps=getCapabilities();if(imageBlocks.length>0&&(!caps.images||!showImages)){let imageIndicators=imageBlocks.map(img=>{let mimeType=img.mimeType??"image/unknown",dims=img.data&&img.mimeType?getImageDimensions(img.data,img.mimeType)??void 0:void 0;return imageFallback(mimeType,dims)}).join(`
|
|
1134
1134
|
`);output=output?`${output}
|
|
1135
|
-
${imageIndicators}`:imageIndicators}return output}function invalidArgText(theme2){return theme2.fg("error","[invalid arg]")}function renderToolPath(rawPath,theme2,cwd,options){if(rawPath===null)return invalidArgText(theme2);let value2=rawPath||options?.emptyFallback;return value2?linkPath(theme2.fg("accent",shortenPath2(value2)),value2,cwd):theme2.fg("toolOutput","...")}
|
|
1136
|
-
`)}function formatFullShellCall(command,timeout,config){let commandDisplay=command===null?invalidArgText(theme):command?styleShellCommand(command,config):theme.fg("toolOutput","...");return formatShellPrompt(config.prompt)+commandDisplay+formatShellTimeout(timeout)}function fitCollapsedShellCall(body,timeout,width,suffix,config){let prompt=formatShellPrompt(config.prompt),timeoutSuffix2=formatShellTimeout(timeout),bodyWidth=Math.max(0,width-visibleWidth(prompt)-visibleWidth(suffix)-visibleWidth(timeoutSuffix2)),fittedBody=truncateToWidth(body,bodyWidth,"");return truncateToWidth(prompt+fittedBody+suffix+timeoutSuffix2,width,"\u2026")}function formatTruncatedShellCall(command,timeout,width,config){if(command===null)return truncateToWidth(formatFullShellCall(command,timeout,config),width,"\u2026");if(!command)return formatFullShellCall(command,timeout,config);let physicalLines=command.split(/\r?\n/).filter(line=>line.trim()),firstNonEmptyLine=physicalLines[0]?.trim()??command.trim(),hiddenLines=Math.max(0,physicalLines.length-1),suffix=hiddenLines>0?theme.fg("muted",` (+${hiddenLines} line${hiddenLines===1?"":"s"})`):theme.fg("muted"," \u2026");return fitCollapsedShellCall(styleShellCommand(firstNonEmptyLine,config),timeout,width,suffix,config)}function rebuildBashResultRenderComponent(component,result2,options,showImages){let state2=component.state;component.clear();let background=result2.details?.background,output=background?.kind==="background"?`Moved to background \xB7 ${background.taskId}`:getTextOutput(result2,showImages).trim(),truncation=result2.details?.truncation,fullOutputPath=result2.details?.fullOutputPath;if(!options.isPartial&&truncation?.truncated&&fullOutputPath&&output.endsWith("]")){let footerStart=output.lastIndexOf(`
|
|
1135
|
+
${imageIndicators}`:imageIndicators}return output}function invalidArgText(theme2){return theme2.fg("error","[invalid arg]")}function renderToolPath(rawPath,theme2,cwd,options){if(rawPath===null)return invalidArgText(theme2);let value2=rawPath||options?.emptyFallback;return value2?linkPath(theme2.fg("accent",shortenPath2(value2)),value2,cwd):theme2.fg("toolOutput","...")}var BASH_PREVIEW_LINES=5,BASH_UPDATE_THROTTLE_MS=100,BashCallRenderComponent=class{constructor(config){this.command="",this.expanded=!1,this.config=config}update(args,expanded){let command=str(args?.command),timeout=args?.timeout;this.command===command&&this.timeout===timeout&&this.expanded===expanded||(this.command=command,this.timeout=timeout,this.expanded=expanded,this.invalidate())}render(width){return(this.cachedLines===void 0||this.cachedWidth!==width)&&(this.cachedLines=this.renderLines(Math.max(1,width)),this.cachedWidth=width),this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}renderLines(width){let fullCall=formatFullShellCall(this.command,this.timeout,this.config),fullLines=new Text(fullCall,0,0).render(width);return this.expanded||fullLines.length<=1?fullLines:[formatTruncatedShellCall(this.command,this.timeout,width,this.config)]}},BashResultRenderComponent=class extends Container{constructor(){super(...arguments),this.state={cachedWidth:void 0,cachedLines:void 0,cachedSkipped:void 0}}},shellTiming=Symbol("shellTiming");function getShellTiming(context){if(!context.executionStarted)return;let state2=context.state;if(state2[shellTiming])return state2[shellTiming];let timing={startedAt:Date.now(),disposed:!1};state2[shellTiming]=timing;let previousDispose=state2.dispose;return state2.dispose=()=>{try{previousDispose?.call(state2)}finally{clearInterval(timing.interval),timing.interval=void 0,timing.disposed=!0}},timing}function formatDuration(ms){let seconds=ms/1e3;if(seconds<60)return`${seconds.toFixed(1)}s`;let totalSeconds=Math.floor(seconds),minutes=Math.floor(totalSeconds/60),remainder=totalSeconds%60;return minutes<60?`${minutes}m ${remainder}s`:`${Math.floor(minutes/60)}h ${minutes%60}m ${remainder}s`}function formatShellPrompt(prompt){return theme.fg("toolTitle",theme.bold(`${prompt} `))}function formatShellTimeout(timeout){return timeout?theme.fg("muted",` (timeout ${timeout}s)`):""}function styleShellCommand(command,config){let language=config.name==="powershell"?"powershell":"bash";return highlightCode(command,language).join(`
|
|
1136
|
+
`)}function formatFullShellCall(command,timeout,config){let commandDisplay=command===null?invalidArgText(theme):command?styleShellCommand(command,config):theme.fg("toolOutput","...");return formatShellPrompt(config.prompt)+commandDisplay+formatShellTimeout(timeout)}function fitCollapsedShellCall(body,timeout,width,suffix,config){let prompt=formatShellPrompt(config.prompt),timeoutSuffix2=formatShellTimeout(timeout),bodyWidth=Math.max(0,width-visibleWidth(prompt)-visibleWidth(suffix)-visibleWidth(timeoutSuffix2)),fittedBody=truncateToWidth(body,bodyWidth,"");return truncateToWidth(prompt+fittedBody+suffix+timeoutSuffix2,width,"\u2026")}function formatTruncatedShellCall(command,timeout,width,config){if(command===null)return truncateToWidth(formatFullShellCall(command,timeout,config),width,"\u2026");if(!command)return formatFullShellCall(command,timeout,config);let physicalLines=command.split(/\r?\n/).filter(line=>line.trim()),firstNonEmptyLine=physicalLines[0]?.trim()??command.trim(),hiddenLines=Math.max(0,physicalLines.length-1),suffix=hiddenLines>0?theme.fg("muted",` (+${hiddenLines} line${hiddenLines===1?"":"s"})`):theme.fg("muted"," \u2026");return fitCollapsedShellCall(styleShellCommand(firstNonEmptyLine,config),timeout,width,suffix,config)}function rebuildBashResultRenderComponent(component,result2,options,showImages,startedAt,endedAt){let state2=component.state;component.clear();let background=result2.details?.background,output=background?.kind==="background"?`Moved to background \xB7 ${background.taskId}`:getTextOutput(result2,showImages).trim(),truncation=result2.details?.truncation,fullOutputPath=result2.details?.fullOutputPath;if(!options.isPartial&&truncation?.truncated&&fullOutputPath&&output.endsWith("]")){let footerStart=output.lastIndexOf(`
|
|
1137
1137
|
|
|
1138
1138
|
[`);footerStart!==-1&&output.slice(footerStart).includes(fullOutputPath)&&(output=output.slice(0,footerStart).trimEnd())}if(output){let styledOutput=output.split(`
|
|
1139
1139
|
`).map(line=>theme.fg("toolOutput",line)).join(`
|
|
1140
1140
|
`);options.expanded?component.addChild(new Text(`
|
|
1141
|
-
${styledOutput}`,0,0)):component.addChild({render:width=>{if(state2.cachedLines===void 0||state2.cachedWidth!==width){let preview=truncateToVisualLines(styledOutput,BASH_PREVIEW_LINES,width);state2.cachedLines=preview.visualLines,state2.cachedSkipped=preview.skippedCount,state2.cachedWidth=width}if(state2.cachedSkipped&&state2.cachedSkipped>0){let hint2=
|
|
1142
|
-
${theme.fg("warning",`[${warnings.join(". ")}]`)}`,0,0))}
|
|
1141
|
+
${styledOutput}`,0,0)):component.addChild({render:width=>{if(state2.cachedLines===void 0||state2.cachedWidth!==width){let preview=truncateToVisualLines(styledOutput,BASH_PREVIEW_LINES,width);state2.cachedLines=preview.visualLines,state2.cachedSkipped=preview.skippedCount,state2.cachedWidth=width}if(state2.cachedSkipped&&state2.cachedSkipped>0){let hint2=theme.fg("muted",`... (${state2.cachedSkipped} earlier lines,`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return["",truncateToWidth(hint2,width,"..."),...state2.cachedLines??[]]}return["",...state2.cachedLines??[]]},invalidate:()=>{state2.cachedWidth=void 0,state2.cachedLines=void 0,state2.cachedSkipped=void 0}})}if(truncation?.truncated||fullOutputPath){let warnings=[];fullOutputPath&&warnings.push(`Full output: ${fullOutputPath}`),truncation?.truncated&&(truncation.truncatedBy==="lines"?warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`):warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes??51200)} limit)`)),component.addChild(new Text(`
|
|
1142
|
+
${theme.fg("warning",`[${warnings.join(". ")}]`)}`,0,0))}if(startedAt!==void 0){let label=options.isPartial?"Elapsed":"Took",endTime=endedAt??Date.now();component.addChild(new Text(`
|
|
1143
|
+
${theme.fg("muted",`${label} ${formatDuration(endTime-startedAt)}`)}`,0,0))}}function createShellRenderers(config){return{renderCall(args,_theme,context){getShellTiming(context);let component=context.lastComponent??new BashCallRenderComponent(config);return component.update(args,context.expanded),component},renderResult(result2,options,_theme,context){let timing=getShellTiming(context);timing&&(!options.isPartial||context.isError?(timing.endedAt??=Date.now(),clearInterval(timing.interval),timing.interval=void 0):!timing.disposed&&timing.interval===void 0&&(timing.interval=setInterval(()=>context.invalidate(),1e3),timing.interval.unref?.()));let component=context.lastComponent??new BashResultRenderComponent;return rebuildBashResultRenderComponent(component,result2,options,context.showImages,timing?.startedAt,timing?.endedAt),component.invalidate(),component}}}import{unlink as unlink2}from"node:fs/promises";import{randomBytes}from"node:crypto";import{closeSync as closeSync2,createWriteStream,openSync as openSync2,writeSync}from"node:fs";import{tmpdir as tmpdir2}from"node:os";import{join as join20}from"node:path";function defaultTempFilePath(prefix){let id=randomBytes(8).toString("hex");return join20(tmpdir2(),`${prefix}-${id}.log`)}function byteLength(text2){return Buffer.byteLength(text2,"utf-8")}var OutputAccumulator=class{constructor(options={}){if(this.decoder=new TextDecoder,this.rawChunks=[],this.tailText="",this.tailBytes=0,this.tailStartsAtLineBoundary=!0,this.totalRawBytes=0,this.totalDecodedBytes=0,this.completedLines=0,this.totalLines=0,this.currentLineBytes=0,this.hasOpenLine=!1,this.finished=!1,this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"pi-output",options.persistFromStart){let path14=defaultTempFilePath(this.tempFilePrefix);this.tempFileFd=openSync2(path14,"wx",384),this.tempFilePath=path14}}append(data){if(this.finished)throw new Error("Cannot append to a finished output accumulator");if(this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),this.tempFileFd!==void 0){let offset=0;for(;offset<data.length;){let written=writeSync(this.tempFileFd,data,offset,data.length-offset);if(written===0)throw new Error("Output file write made no progress");offset+=written}}else this.tempFileStream||this.shouldUseTempFile()?(this.ensureTempFile(),this.tempFileStream?.write(data)):data.length>0&&this.rawChunks.push(data)}finish(){this.finished||(this.finished=!0,this.appendDecodedText(this.decoder.decode()),this.shouldUseTempFile()&&this.ensureTempFile())}snapshot(options={}){let maxBytes=Math.min(this.maxBytes,options.maxBytes??this.maxBytes),tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}getTotalBytes(){return this.totalRawBytes}async closeTempFile(){if(this.tempFileFd!==void 0){let fd=this.tempFileFd;this.tempFileFd=void 0,closeSync2(fd)}if(!this.tempFileStream)return;let stream2=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve17,reject)=>{let onError=error=>{stream2.off("finish",onFinish),reject(error)},onFinish=()=>{stream2.off("error",onError),resolve17()};stream2.once("error",onError),stream2.once("finish",onFinish),stream2.end()})}getLastLineBytes(){return this.currentLineBytes}appendDecodedText(text2){if(text2.length===0)return;let bytes=byteLength(text2);this.totalDecodedBytes+=bytes,this.tailText+=text2,this.tailBytes+=bytes,this.tailBytes>this.maxRollingBytes*2&&this.trimTail();let newlines=0,lastNewline=-1;for(let i=text2.indexOf(`
|
|
1143
1144
|
`);i!==-1;i=text2.indexOf(`
|
|
1144
1145
|
`,i+1))newlines++,lastNewline=i;if(newlines===0)this.currentLineBytes+=bytes,this.hasOpenLine=!0;else{this.completedLines+=newlines;let tail=text2.slice(lastNewline+1);this.currentLineBytes=byteLength(tail),this.hasOpenLine=tail.length>0}this.totalLines=this.completedLines+(this.hasOpenLine?1:0)}trimTail(){let buffer=Buffer.from(this.tailText,"utf-8");if(buffer.length<=this.maxRollingBytes){this.tailBytes=buffer.length;return}let start=buffer.length-this.maxRollingBytes;for(;start<buffer.length&&(buffer[start]&192)===128;)start++;this.tailStartsAtLineBoundary=start===0?this.tailStartsAtLineBoundary:buffer[start-1]===10,this.tailText=buffer.subarray(start).toString("utf-8"),this.tailBytes=byteLength(this.tailText)}getSnapshotText(){if(this.tailStartsAtLineBoundary)return this.tailText;let firstNewline=this.tailText.indexOf(`
|
|
1145
1146
|
`);return firstNewline===-1?this.tailText:this.tailText.slice(firstNewline+1)}shouldUseTempFile(){return this.totalRawBytes>this.maxBytes||this.totalDecodedBytes>this.maxBytes||this.totalLines>this.maxLines}ensureTempFile(){if(!this.tempFilePath){this.tempFilePath=defaultTempFilePath(this.tempFilePrefix),this.tempFileStream=createWriteStream(this.tempFilePath);for(let chunk of this.rawChunks)this.tempFileStream.write(chunk);this.rawChunks=[]}}};var CMD_NUL_REDIRECT_REGEX=/(\d?&?>+\s*)[Nn][Uu][Ll](?=\s|$|[|&;)\n])/g;function rewriteCmdNulRedirects(command){return command.replace(CMD_NUL_REDIRECT_REGEX,"$1/dev/null")}var MAX_BACKGROUND_OUTPUT_BYTES=20*1024*1024;function shellFailure(error){return error instanceof Error&&error.message==="aborted"?{status:"cancelled",error:"Command aborted"}:error instanceof Error&&error.message.startsWith("timeout:")?{status:"timeout",error:`Command timed out after ${error.message.split(":")[1]} seconds`}:{status:"failed",error:boundText(error instanceof Error?error.message:String(error),4096)}}function formatOutput(output,snapshot,managed,emptyText){let truncation=snapshot.truncation,text2=snapshot.content||emptyText,details=managed?{fullOutputPath:snapshot.fullOutputPath}:void 0;if(truncation.truncated){details={truncation,fullOutputPath:snapshot.fullOutputPath};let startLine=truncation.totalLines-truncation.outputLines+1,endLine=truncation.totalLines;if(truncation.lastLinePartial){let lastLineSize=formatSize(output.getLastLineBytes());text2+=`
|
|
@@ -1173,29 +1174,28 @@ Full output: ${outcome.task.outputPath}`:""}`}],details:{background:{kind:"backg
|
|
|
1173
1174
|
`);if(raw[raw.length-1]===""&&raw.pop(),part.added||part.removed){firstChangedLine===void 0&&(firstChangedLine=newLineNum);for(let line of raw)if(part.added){let lineNum=String(newLineNum).padStart(lineNumWidth," ");output.push(`+${lineNum} ${line}`),newLineNum++}else{let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(`-${lineNum} ${line}`),oldLineNum++}lastWasChange=!0}else{let nextPartIsChange=i<parts.length-1&&(parts[i+1].added||parts[i+1].removed),hasLeadingChange=lastWasChange,hasTrailingChange=nextPartIsChange;if(hasLeadingChange&&hasTrailingChange)if(raw.length<=contextLines*2)for(let line of raw){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}else{let leadingLines=raw.slice(0,contextLines),trailingLines=raw.slice(raw.length-contextLines),skippedLines=raw.length-leadingLines.length-trailingLines.length;for(let line of leadingLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines;for(let line of trailingLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}}else if(hasLeadingChange){let shownLines=raw.slice(0,contextLines),skippedLines=raw.length-shownLines.length;for(let line of shownLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}skippedLines>0&&(output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines)}else if(hasTrailingChange){let skippedLines=Math.max(0,raw.length-contextLines);skippedLines>0&&(output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines);for(let line of raw.slice(skippedLines)){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}}else oldLineNum+=raw.length,newLineNum+=raw.length;lastWasChange=!1}}return{diff:output.join(`
|
|
1174
1175
|
`),firstChangedLine}}async function computeEditsDiff(path14,edits,cwd){let absolutePath=resolveToCwd(path14,cwd);try{try{await access2(absolutePath,constants4.R_OK)}catch(error){let errorMessage6=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);return{error:`Could not edit file: ${path14}. ${errorMessage6}.`}}let rawContent=await readFile2(absolutePath,"utf-8"),{text:content}=splitBom(rawContent),normalizedContent=normalizeToLF2(content),{baseContent,newContent}=applyEditsToNormalizedContent2(normalizedContent,edits,path14);return generateDiffString2(baseContent,newContent)}catch(err2){return{error:err2 instanceof Error?err2.message:String(err2)}}}import{realpath}from"node:fs/promises";import{resolve as resolve6}from"node:path";var fileMutationQueues=new Map,registrationQueue=Promise.resolve();function isMissingPathError(error){return typeof error=="object"&&error!==null&&"code"in error&&(error.code==="ENOENT"||error.code==="ENOTDIR")}async function getMutationQueueKey2(filePath){let resolvedPath=resolve6(filePath);try{return await realpath(resolvedPath)}catch(error){if(isMissingPathError(error))return resolvedPath;throw error}}async function withFileMutationQueue2(filePath,fn){let registration=registrationQueue.then(async()=>{let key2=await getMutationQueueKey2(filePath),currentQueue2=fileMutationQueues.get(key2)??Promise.resolve(),releaseNext2,nextQueue=new Promise(resolveQueue=>{releaseNext2=resolveQueue}),chainedQueue2=currentQueue2.then(()=>nextQueue);return fileMutationQueues.set(key2,chainedQueue2),{key:key2,currentQueue:currentQueue2,chainedQueue:chainedQueue2,releaseNext:releaseNext2}});registrationQueue=registration.then(()=>{},()=>{});let{key,currentQueue,chainedQueue,releaseNext}=await registration;await currentQueue;try{return await fn()}finally{releaseNext(),fileMutationQueues.get(key)===chainedQueue&&fileMutationQueues.delete(key)}}function parseDiffLine(line){let match2=line.match(/^([+-\s])(\s*\d*)\s(.*)$/);return match2?{prefix:match2[1],lineNum:match2[2],content:match2[3]}:null}function replaceTabs2(text2){return text2.replace(/\t/g," ")}function renderIntraLineDiff(oldContent,newContent){let wordDiff2=diffWords(oldContent,newContent),removedLine="",addedLine="",isFirstRemoved=!0,isFirstAdded=!0;for(let part of wordDiff2)if(part.removed){let value2=part.value;if(isFirstRemoved){let leadingWs2=value2.match(/^(\s*)/)?.[1]||"";value2=value2.slice(leadingWs2.length),removedLine+=leadingWs2,isFirstRemoved=!1}value2&&(removedLine+=theme.inverse(value2))}else if(part.added){let value2=part.value;if(isFirstAdded){let leadingWs2=value2.match(/^(\s*)/)?.[1]||"";value2=value2.slice(leadingWs2.length),addedLine+=leadingWs2,isFirstAdded=!1}value2&&(addedLine+=theme.inverse(value2))}else removedLine+=part.value,addedLine+=part.value;return{removedLine,addedLine}}function renderDiff(diffText,_options={}){let lines=diffText.split(`
|
|
1175
1176
|
`),result2=[],i=0;for(;i<lines.length;){let line=lines[i],parsed=parseDiffLine(line);if(!parsed){result2.push(theme.fg("toolDiffContext",line)),i++;continue}if(parsed.prefix==="-"){let removedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="-")break;removedLines.push({lineNum:p.lineNum,content:p.content}),i++}let addedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="+")break;addedLines.push({lineNum:p.lineNum,content:p.content}),i++}if(removedLines.length===1&&addedLines.length===1){let removed=removedLines[0],added=addedLines[0],{removedLine,addedLine}=renderIntraLineDiff(replaceTabs2(removed.content),replaceTabs2(added.content));result2.push(theme.fg("toolDiffRemoved",`-${removed.lineNum} ${removedLine}`)),result2.push(theme.fg("toolDiffAdded",`+${added.lineNum} ${addedLine}`))}else{for(let removed of removedLines)result2.push(theme.fg("toolDiffRemoved",`-${removed.lineNum} ${replaceTabs2(removed.content)}`));for(let added of addedLines)result2.push(theme.fg("toolDiffAdded",`+${added.lineNum} ${replaceTabs2(added.content)}`))}}else parsed.prefix==="+"?(result2.push(theme.fg("toolDiffAdded",`+${parsed.lineNum} ${replaceTabs2(parsed.content)}`)),i++):(result2.push(theme.fg("toolDiffContext",` ${parsed.lineNum} ${replaceTabs2(parsed.content)}`)),i++)}return result2.join(`
|
|
1176
|
-
`)}import{constants as constants5}from"fs";import{access as fsAccess2,readFile as fsReadFile,writeFile as fsWriteFile}from"fs/promises";var EditCallRenderComponent=class extends Container{constructor(){super(...arguments),this.previewPending=!1}};function getEditCallRenderComponent(state2,lastComponent){if(lastComponent instanceof EditCallRenderComponent)return state2.callComponent=lastComponent,lastComponent;if(state2.callComponent)return state2.callComponent;let component=new EditCallRenderComponent;return state2.callComponent=component,component}function getRenderablePreviewInput(args){if(!args)return null;let path14=typeof args.path=="string"?args.path:typeof args.file_path=="string"?args.file_path:null;return path14?Array.isArray(args.edits)&&args.edits.length>0&&args.edits.every(edit=>typeof edit?.oldText=="string"&&typeof edit?.newText=="string")?{path:path14,edits:args.edits}:typeof args.oldText=="string"&&typeof args.newText=="string"?{path:path14,edits:[{oldText:args.oldText,newText:args.newText}]}:null:null}function formatEditCall(args,theme2,cwd){let pathDisplay=renderToolPath(str(args?.file_path??args?.path),theme2,cwd);return`${theme2.fg("toolTitle",theme2.bold("edit"))} ${pathDisplay}`}var EDIT_COLLAPSED_DIFF_LINES=10;function
|
|
1177
|
-
`))line.startsWith("+")?added++:line.startsWith("-")&&removed++;return{added,removed}}function formatDiffStat(diff,theme2){let{added,removed}=diffStat(diff);return` ${theme2.fg("toolDiffAdded",`+${added}`)} ${theme2.fg("toolDiffRemoved",`-${removed}`)}`}function boundDiffBody(renderedDiff,expanded,theme2){if(expanded)return renderedDiff;let lines=renderedDiff.split(`
|
|
1177
|
+
`)}import{constants as constants5}from"fs";import{access as fsAccess2,readFile as fsReadFile,writeFile as fsWriteFile}from"fs/promises";var EditCallRenderComponent=class extends Container{constructor(){super(...arguments),this.previewPending=!1}};function getEditCallRenderComponent(state2,lastComponent){if(lastComponent instanceof EditCallRenderComponent)return state2.callComponent=lastComponent,lastComponent;if(state2.callComponent)return state2.callComponent;let component=new EditCallRenderComponent;return state2.callComponent=component,component}function getRenderablePreviewInput(args){if(!args)return null;let path14=typeof args.path=="string"?args.path:typeof args.file_path=="string"?args.file_path:null;return path14?Array.isArray(args.edits)&&args.edits.length>0&&args.edits.every(edit=>typeof edit?.oldText=="string"&&typeof edit?.newText=="string")?{path:path14,edits:args.edits}:typeof args.oldText=="string"&&typeof args.newText=="string"?{path:path14,edits:[{oldText:args.oldText,newText:args.newText}]}:null:null}function formatEditCall(args,theme2,cwd){let pathDisplay=renderToolPath(str(args?.file_path??args?.path),theme2,cwd);return`${theme2.fg("toolTitle",theme2.bold("edit"))} ${pathDisplay}`}var EDIT_COLLAPSED_DIFF_LINES=10;function boundDiffBody(renderedDiff,expanded,theme2){if(expanded)return renderedDiff;let lines=renderedDiff.split(`
|
|
1178
1178
|
`);if(lines.length<=EDIT_COLLAPSED_DIFF_LINES)return renderedDiff;let shown=lines.slice(0,EDIT_COLLAPSED_DIFF_LINES),remaining=lines.length-shown.length;return`${shown.join(`
|
|
1179
|
-
`)}
|
|
1180
|
-
${
|
|
1181
|
-
`);return!errorText2||errorText2===previewError?void 0:theme2.fg("error",errorText2)}let resultDiff=result2.details?.diff;if(resultDiff&&resultDiff!==previewDiff)return boundDiffBody(renderDiff(resultDiff,{filePath:rawPath??void 0}),expanded,theme2)}function buildEditCallComponent(component,args,theme2,cwd,expanded){component.clear();let preview=component.preview,previewDiff=preview&&!("error"in preview)?preview.diff:void 0,headline=formatEditCall(args,theme2,cwd);if(previewDiff!==void 0&&(headline+=formatDiffStat(previewDiff,theme2)),component.addChild(new Text(headline,0,0)),!preview)return component;let body="error"in preview?theme2.fg("error",preview.error):boundDiffBody(renderDiff(preview.diff),expanded,theme2);return component.addChild(new Spacer(1)),component.addChild(new Text(body,0,0)),component}function setEditPreview(component,preview,argsKey){let current=component.preview,changed=current===void 0||("error"in current&&"error"in preview?current.error!==preview.error:"error"in current!="error"in preview)||!("error"in current)&&!("error"in preview)&&(current.diff!==preview.diff||current.firstChangedLine!==preview.firstChangedLine);return component.preview=preview,component.previewArgsKey=argsKey,component.previewPending=!1,changed}var editRenderers={renderCall(args,theme2,context){let component=getEditCallRenderComponent(context.state,context.lastComponent),previewInput=getRenderablePreviewInput(args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0;if(component.previewArgsKey!==argsKey&&(component.preview=void 0,component.previewArgsKey=argsKey,component.previewPending=!1),context.argsComplete&&previewInput&&!component.preview&&!component.previewPending){component.previewPending=!0;let requestKey=argsKey;computeEditsDiff(previewInput.path,previewInput.edits,context.cwd).then(preview=>{component.previewArgsKey===requestKey&&(setEditPreview(component,preview,requestKey),context.invalidate())})}return buildEditCallComponent(component,args,theme2,context.cwd,context.expanded)},renderResult(result2,options,theme2,context){let callComponent=context.state.callComponent,previewInput=getRenderablePreviewInput(context.args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0,typedResult=result2,resultDiff=context.isError?void 0:typedResult.details?.diff,changed=!1;callComponent&&(typeof resultDiff=="string"&&(changed=setEditPreview(callComponent,{diff:resultDiff,firstChangedLine:typedResult.details?.firstChangedLine},argsKey)||changed),changed&&buildEditCallComponent(callComponent,context.args,theme2,context.cwd,context.expanded));let output=formatEditResult(context.args,callComponent?.preview,typedResult,theme2,context.isError,options.expanded),component=context.lastComponent??new Container;return component.clear(),output&&(component.addChild(new Spacer(1)),component.addChild(new Text(output,1,0))),component}};var replaceEditSchema2=typebox_exports.Object({oldText:typebox_exports.String({description:"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call."}),newText:typebox_exports.String({description:"Replacement text for this targeted edit."})},{}),editSchema2=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to edit (relative or absolute)"}),edits:typebox_exports.Array(replaceEditSchema2,{description:"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead."})},{}),editToolSystemPromptContribution={snippet:"Make precise file edits with exact text replacement, including multiple disjoint edits in one call",guidelines:["Use edit for precise changes (edits[].oldText must match exactly)","When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls","Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.","Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions."]};function isSingleEditInput2(value2){if(!value2||typeof value2!="object"||Array.isArray(value2))return!1;let edit=value2;return typeof edit.oldText=="string"&&typeof edit.newText=="string"}var defaultEditOperations={readFile:path14=>fsReadFile(path14),writeFile:(path14,content)=>fsWriteFile(path14,content,"utf-8"),access:path14=>fsAccess2(path14,constants5.R_OK|constants5.W_OK)};function prepareEditArguments2(input2){if(!input2||typeof input2!="object")return input2;let args=input2;if(typeof args.edits=="string")try{let parsed=JSON.parse(args.edits);Array.isArray(parsed)?args.edits=parsed:isSingleEditInput2(parsed)&&(args.edits=[parsed])}catch{}else isSingleEditInput2(args.edits)&&(args.edits=[args.edits]);let legacy=args;if(typeof legacy.oldText!="string"||typeof legacy.newText!="string")return args;let edits=Array.isArray(legacy.edits)?[...legacy.edits]:[];edits.push({oldText:legacy.oldText,newText:legacy.newText});let{oldText:_oldText,newText:_newText,...rest}=legacy;return{...rest,edits}}function validateEditInput2(input2){if(!Array.isArray(input2.edits)||input2.edits.length===0)throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");return{path:input2.path,edits:input2.edits}}function createEditToolDefinition(cwd,options){let ops=options?.operations??defaultEditOperations;return{name:"edit",label:"edit",description:"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.",promptSnippet:editToolSystemPromptContribution.snippet,promptGuidelines:[...editToolSystemPromptContribution.guidelines],parameters:editSchema2,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:prepareEditArguments2,async execute(_toolCallId,input2,signal,_onUpdate,ctx){let{path:path14,edits}=validateEditInput2(input2),absolutePath=resolveToCwd(path14,ctx?.cwd||cwd);return withFileMutationQueue2(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};throwIfAborted();try{await ops.access(absolutePath)}catch(error){throwIfAborted();let errorMessage6=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);throw new Error(`Could not edit file: ${path14}. ${errorMessage6}.`)}throwIfAborted();let rawContent=(await ops.readFile(absolutePath)).toString("utf-8");throwIfAborted();let{bom,text:content}=splitBom(rawContent),originalEnding=detectLineEnding2(content),normalizedContent=normalizeToLF2(content),{baseContent,newContent}=applyEditsToNormalizedContent2(normalizedContent,edits,path14);throwIfAborted();let finalContent=bom+restoreLineEndings2(newContent,originalEnding);await ops.writeFile(absolutePath,finalContent),throwIfAborted();let diffResult=generateDiffString2(baseContent,newContent),patch=generateUnifiedPatch2(path14,baseContent,newContent);return{content:[{type:"text",text:`Successfully replaced ${edits.length} block(s) in ${path14}.`}],details:{diff:diffResult.diff,patch,firstChangedLine:diffResult.firstChangedLine}}})},...editRenderers}}function createEditTool2(cwd,options){return wrapToolDefinition(createEditToolDefinition(cwd,options))}import{createInterface as createInterface2}from"node:readline";import{spawn as spawn5}from"child_process";import path8 from"path";import{spawnSync as spawnSync4}from"child_process";import{chmodSync as chmodSync2,createWriteStream as createWriteStream2,existsSync as existsSync12,mkdirSync as mkdirSync6,readdirSync as readdirSync7,renameSync,rmSync as rmSync2}from"fs";import{arch,platform}from"os";import{join as join21}from"path";import{Readable}from"stream";import{pipeline}from"stream/promises";var TOOLS_DIR=getBinDir(),NETWORK_TIMEOUT_MS2=1e4,DOWNLOAD_TIMEOUT_MS=12e4;function isOfflineModeEnabled2(){let value2=process.env.PI_OFFLINE;return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}var TOOLS={fd:{name:"fd",repo:"sharkdp/fd",binaryName:"fd",systemBinaryNames:["fd","fdfind"],tagPrefix:"v",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null},rg:{name:"ripgrep",repo:"BurntSushi/ripgrep",binaryName:"rg",tagPrefix:"",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null}};function commandExists(cmd){try{let result2=spawnSync4(cmd,["--version"],{stdio:"pipe"});return result2.error===void 0||result2.error===null}catch{return!1}}function getToolPath(tool){let config=TOOLS[tool];if(!config)return null;let localPath=join21(TOOLS_DIR,config.binaryName+(platform()==="win32"?".exe":""));if(existsSync12(localPath))return localPath;let systemBinaryNames=config.systemBinaryNames??[config.binaryName];for(let systemBinaryName of systemBinaryNames)if(commandExists(systemBinaryName))return systemBinaryName;return null}async function getLatestVersion(repo){let response=await fetchWithRetry(`https://github.com/${repo}/releases/latest`,{headers:{"User-Agent":`${APP_NAME}-coding-agent`},redirect:"manual"},{timeoutMs:NETWORK_TIMEOUT_MS2});try{await response.body?.cancel()}catch{}let location=response.status>=300&&response.status<400?response.headers.get("location"):null;if(!location)throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);let tag=new URL(location,"https://github.com").pathname.split("/").pop();if(!tag||!location.includes("/releases/tag/"))throw new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);return decodeURIComponent(tag).replace(/^v/,"")}async function downloadFile(url,dest){let response=await fetchWithRetry(url,void 0,{timeoutMs:DOWNLOAD_TIMEOUT_MS});if(!response.ok)throw new Error(`Download failed with HTTP ${response.status}: ${url}`);if(!response.body)throw new Error("No response body");let fileStream=createWriteStream2(dest);await pipeline(Readable.fromWeb(response.body),fileStream)}function findBinaryRecursively(rootDir,binaryFileName){let stack=[rootDir];for(;stack.length>0;){let currentDir=stack.pop();if(!currentDir)continue;let entries=readdirSync7(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join21(currentDir,entry.name);if(entry.isFile()&&entry.name===binaryFileName)return fullPath;entry.isDirectory()&&stack.push(fullPath)}}return null}function formatSpawnFailure(result2){if(result2.error?.message)return result2.error.message;let stderr=result2.stderr?.toString().trim();if(stderr)return stderr;let stdout=result2.stdout?.toString().trim();return stdout||`exit status ${result2.status??"unknown"}`}function runExtractionCommand(command,args){let result2=spawnSync4(command,args,{stdio:"pipe"});return!result2.error&&result2.status===0?null:`${command}: ${formatSpawnFailure(result2)}`}function extractTarGzArchive(archivePath,extractDir,assetName){let failure=runExtractionCommand("tar",["xzf",archivePath,"-C",extractDir]);if(failure)throw new Error(`Failed to extract ${assetName}: ${failure}`)}function getWindowsTarCommand(){let systemRoot=process.env.SystemRoot??process.env.WINDIR;if(systemRoot){let systemTar=join21(systemRoot,"System32","tar.exe");if(existsSync12(systemTar))return systemTar}return"tar.exe"}function extractZipArchive(archivePath,extractDir,assetName){let failures=[];if(platform()==="win32"){let tarFailure=runExtractionCommand(getWindowsTarCommand(),["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure);let powershellFailure=runExtractionCommand("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }",archivePath,extractDir]);if(!powershellFailure)return;failures.push(powershellFailure)}else{let unzipFailure=runExtractionCommand("unzip",["-q",archivePath,"-d",extractDir]);if(!unzipFailure)return;failures.push(unzipFailure);let tarFailure=runExtractionCommand("tar",["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure)}throw new Error(`Failed to extract ${assetName}: ${failures.join("; ")}`)}async function downloadTool(tool){let config=TOOLS[tool];if(!config)throw new Error(`Unknown tool: ${tool}`);let plat=platform(),architecture=arch(),version2=tool==="fd"&&plat==="darwin"&&architecture==="x64"?"10.3.0":await getLatestVersion(config.repo),assetName=config.getAssetName(version2,plat,architecture);if(!assetName)throw new Error(`Unsupported platform: ${plat}/${architecture}`);mkdirSync6(TOOLS_DIR,{recursive:!0});let downloadUrl=`https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version2}/${assetName}`,archivePath=join21(TOOLS_DIR,assetName),binaryExt=plat==="win32"?".exe":"",binaryPath=join21(TOOLS_DIR,config.binaryName+binaryExt);await downloadFile(downloadUrl,archivePath);let extractDir=join21(TOOLS_DIR,`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2,10)}`);mkdirSync6(extractDir,{recursive:!0});try{if(assetName.endsWith(".tar.gz"))extractTarGzArchive(archivePath,extractDir,assetName);else if(assetName.endsWith(".zip"))extractZipArchive(archivePath,extractDir,assetName);else throw new Error(`Unsupported archive format: ${assetName}`);let binaryFileName=config.binaryName+binaryExt,extractedDir=join21(extractDir,assetName.replace(/\.(tar\.gz|zip)$/,"")),extractedBinary=[join21(extractedDir,binaryFileName),join21(extractDir,binaryFileName)].find(candidate=>existsSync12(candidate));if(extractedBinary||(extractedBinary=findBinaryRecursively(extractDir,binaryFileName)??void 0),extractedBinary)renameSync(extractedBinary,binaryPath);else throw new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);plat!=="win32"&&chmodSync2(binaryPath,493)}finally{rmSync2(archivePath,{force:!0}),rmSync2(extractDir,{recursive:!0,force:!0})}return binaryPath}var TERMUX_PACKAGES={fd:"fd",rg:"ripgrep"};async function ensureTool(tool,onStatus){let existingPath=getToolPath(tool);if(existingPath)return existingPath;let config=TOOLS[tool];if(config){if(isOfflineModeEnabled2()){onStatus?.({type:"warning",message:`${config.name} not found. Offline mode enabled, skipping download.`});return}if(platform()==="android"){let pkgName=TERMUX_PACKAGES[tool]??tool;onStatus?.({type:"warning",message:`${config.name} not found. Install with: pkg install ${pkgName}`});return}onStatus?.({type:"info",message:`${config.name} not found. Downloading...`});try{let path14=await downloadTool(tool);return onStatus?.({type:"info",message:`${config.name} installed to ${path14}`}),path14}catch(e){let messages=[];for(let current=e,depth=0;current instanceof Error&&depth<5;current=current.cause,depth++)messages.includes(current.message)||messages.push(current.message);onStatus?.({type:"warning",message:`Failed to download ${config.name}: ${messages.length>0?messages.join(": "):String(e)}`});return}}}function formatFindCall(args,theme2,cwd){let pattern=str(args?.pattern),rawPath=str(args?.path),limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("find"))+" "+(pattern===null?invalidArg:theme2.fg("accent",pattern||""))+theme2.fg("toolOutput"," in ")+renderToolPath(rawPath,theme2,cwd,{emptyFallback:"."});return limit!==void 0&&(text2+=theme2.fg("toolOutput",` (limit ${limit})`)),text2}function formatFindResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
1179
|
+
`)}${theme2.fg("muted",`
|
|
1180
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}function formatEditResult(args,preview,result2,theme2,isError,expanded){let rawPath=str(args?.file_path??args?.path),previewDiff=preview&&!("error"in preview)?preview.diff:void 0,previewError=preview&&"error"in preview?preview.error:void 0;if(isError){let errorText2=result2.content.filter(c=>c.type==="text").map(c=>c.text||"").join(`
|
|
1181
|
+
`);return!errorText2||errorText2===previewError?void 0:theme2.fg("error",errorText2)}let resultDiff=result2.details?.diff;if(resultDiff&&resultDiff!==previewDiff)return boundDiffBody(renderDiff(resultDiff,{filePath:rawPath??void 0}),expanded,theme2)}function buildEditCallComponent(component,args,theme2,cwd,expanded){component.clear(),component.addChild(new Text(formatEditCall(args,theme2,cwd),0,0));let preview=component.preview;if(!preview)return component;let body="error"in preview?theme2.fg("error",preview.error):boundDiffBody(renderDiff(preview.diff),expanded,theme2);return component.addChild(new Spacer(1)),component.addChild(new Text(body,0,0)),component}function setEditPreview(component,preview,argsKey){let current=component.preview,changed=current===void 0||("error"in current&&"error"in preview?current.error!==preview.error:"error"in current!="error"in preview)||!("error"in current)&&!("error"in preview)&&(current.diff!==preview.diff||current.firstChangedLine!==preview.firstChangedLine);return component.preview=preview,component.previewArgsKey=argsKey,component.previewPending=!1,changed}var editRenderers={renderCall(args,theme2,context){let component=getEditCallRenderComponent(context.state,context.lastComponent),previewInput=getRenderablePreviewInput(args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0;if(component.previewArgsKey!==argsKey&&(component.preview=void 0,component.previewArgsKey=argsKey,component.previewPending=!1),context.argsComplete&&previewInput&&!component.preview&&!component.previewPending){component.previewPending=!0;let requestKey=argsKey;computeEditsDiff(previewInput.path,previewInput.edits,context.cwd).then(preview=>{component.previewArgsKey===requestKey&&(setEditPreview(component,preview,requestKey),context.invalidate())})}return buildEditCallComponent(component,args,theme2,context.cwd,context.expanded)},renderResult(result2,options,theme2,context){let callComponent=context.state.callComponent,previewInput=getRenderablePreviewInput(context.args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0,typedResult=result2,resultDiff=context.isError?void 0:typedResult.details?.diff,changed=!1;callComponent&&(typeof resultDiff=="string"&&(changed=setEditPreview(callComponent,{diff:resultDiff,firstChangedLine:typedResult.details?.firstChangedLine},argsKey)||changed),changed&&buildEditCallComponent(callComponent,context.args,theme2,context.cwd,context.expanded));let output=formatEditResult(context.args,callComponent?.preview,typedResult,theme2,context.isError,options.expanded),component=context.lastComponent??new Container;return component.clear(),output&&(component.addChild(new Spacer(1)),component.addChild(new Text(output,1,0))),component}};var replaceEditSchema2=typebox_exports.Object({oldText:typebox_exports.String({description:"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call."}),newText:typebox_exports.String({description:"Replacement text for this targeted edit."})},{}),editSchema2=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to edit (relative or absolute)"}),edits:typebox_exports.Array(replaceEditSchema2,{description:"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead."})},{}),editToolSystemPromptContribution={snippet:"Make precise file edits with exact text replacement, including multiple disjoint edits in one call",guidelines:["Use edit for precise changes (edits[].oldText must match exactly)","When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls","Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.","Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions."]};function isSingleEditInput2(value2){if(!value2||typeof value2!="object"||Array.isArray(value2))return!1;let edit=value2;return typeof edit.oldText=="string"&&typeof edit.newText=="string"}var defaultEditOperations={readFile:path14=>fsReadFile(path14),writeFile:(path14,content)=>fsWriteFile(path14,content,"utf-8"),access:path14=>fsAccess2(path14,constants5.R_OK|constants5.W_OK)};function prepareEditArguments2(input2){if(!input2||typeof input2!="object")return input2;let args=input2;if(typeof args.edits=="string")try{let parsed=JSON.parse(args.edits);Array.isArray(parsed)?args.edits=parsed:isSingleEditInput2(parsed)&&(args.edits=[parsed])}catch{}else isSingleEditInput2(args.edits)&&(args.edits=[args.edits]);let legacy=args;if(typeof legacy.oldText!="string"||typeof legacy.newText!="string")return args;let edits=Array.isArray(legacy.edits)?[...legacy.edits]:[];edits.push({oldText:legacy.oldText,newText:legacy.newText});let{oldText:_oldText,newText:_newText,...rest}=legacy;return{...rest,edits}}function validateEditInput2(input2){if(!Array.isArray(input2.edits)||input2.edits.length===0)throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");return{path:input2.path,edits:input2.edits}}function createEditToolDefinition(cwd,options){let ops=options?.operations??defaultEditOperations;return{name:"edit",label:"edit",description:"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.",promptSnippet:editToolSystemPromptContribution.snippet,promptGuidelines:[...editToolSystemPromptContribution.guidelines],parameters:editSchema2,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:prepareEditArguments2,async execute(_toolCallId,input2,signal,_onUpdate,ctx){let{path:path14,edits}=validateEditInput2(input2),absolutePath=resolveToCwd(path14,ctx?.cwd||cwd);return withFileMutationQueue2(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};throwIfAborted();try{await ops.access(absolutePath)}catch(error){throwIfAborted();let errorMessage6=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);throw new Error(`Could not edit file: ${path14}. ${errorMessage6}.`)}throwIfAborted();let rawContent=(await ops.readFile(absolutePath)).toString("utf-8");throwIfAborted();let{bom,text:content}=splitBom(rawContent),originalEnding=detectLineEnding2(content),normalizedContent=normalizeToLF2(content),{baseContent,newContent}=applyEditsToNormalizedContent2(normalizedContent,edits,path14);throwIfAborted();let finalContent=bom+restoreLineEndings2(newContent,originalEnding);await ops.writeFile(absolutePath,finalContent),throwIfAborted();let diffResult=generateDiffString2(baseContent,newContent),patch=generateUnifiedPatch2(path14,baseContent,newContent);return{content:[{type:"text",text:`Successfully replaced ${edits.length} block(s) in ${path14}.`}],details:{diff:diffResult.diff,patch,firstChangedLine:diffResult.firstChangedLine}}})},...editRenderers}}function createEditTool2(cwd,options){return wrapToolDefinition(createEditToolDefinition(cwd,options))}import{createInterface as createInterface2}from"node:readline";import{spawn as spawn5}from"child_process";import path8 from"path";import{spawnSync as spawnSync4}from"child_process";import{chmodSync as chmodSync2,createWriteStream as createWriteStream2,existsSync as existsSync12,mkdirSync as mkdirSync6,readdirSync as readdirSync7,renameSync,rmSync as rmSync2}from"fs";import{arch,platform}from"os";import{join as join21}from"path";import{Readable}from"stream";import{pipeline}from"stream/promises";var TOOLS_DIR=getBinDir(),NETWORK_TIMEOUT_MS2=1e4,DOWNLOAD_TIMEOUT_MS=12e4;function isOfflineModeEnabled2(){let value2=process.env.PI_OFFLINE;return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}var TOOLS={fd:{name:"fd",repo:"sharkdp/fd",binaryName:"fd",systemBinaryNames:["fd","fdfind"],tagPrefix:"v",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null},rg:{name:"ripgrep",repo:"BurntSushi/ripgrep",binaryName:"rg",tagPrefix:"",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null}};function commandExists(cmd){try{let result2=spawnSync4(cmd,["--version"],{stdio:"pipe"});return result2.error===void 0||result2.error===null}catch{return!1}}function getToolPath(tool){let config=TOOLS[tool];if(!config)return null;let localPath=join21(TOOLS_DIR,config.binaryName+(platform()==="win32"?".exe":""));if(existsSync12(localPath))return localPath;let systemBinaryNames=config.systemBinaryNames??[config.binaryName];for(let systemBinaryName of systemBinaryNames)if(commandExists(systemBinaryName))return systemBinaryName;return null}async function getLatestVersion(repo){let response=await fetchWithRetry(`https://github.com/${repo}/releases/latest`,{headers:{"User-Agent":`${APP_NAME}-coding-agent`},redirect:"manual"},{timeoutMs:NETWORK_TIMEOUT_MS2});try{await response.body?.cancel()}catch{}let location=response.status>=300&&response.status<400?response.headers.get("location"):null;if(!location)throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);let tag=new URL(location,"https://github.com").pathname.split("/").pop();if(!tag||!location.includes("/releases/tag/"))throw new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);return decodeURIComponent(tag).replace(/^v/,"")}async function downloadFile(url,dest){let response=await fetchWithRetry(url,void 0,{timeoutMs:DOWNLOAD_TIMEOUT_MS});if(!response.ok)throw new Error(`Download failed with HTTP ${response.status}: ${url}`);if(!response.body)throw new Error("No response body");let fileStream=createWriteStream2(dest);await pipeline(Readable.fromWeb(response.body),fileStream)}function findBinaryRecursively(rootDir,binaryFileName){let stack=[rootDir];for(;stack.length>0;){let currentDir=stack.pop();if(!currentDir)continue;let entries=readdirSync7(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join21(currentDir,entry.name);if(entry.isFile()&&entry.name===binaryFileName)return fullPath;entry.isDirectory()&&stack.push(fullPath)}}return null}function formatSpawnFailure(result2){if(result2.error?.message)return result2.error.message;let stderr=result2.stderr?.toString().trim();if(stderr)return stderr;let stdout=result2.stdout?.toString().trim();return stdout||`exit status ${result2.status??"unknown"}`}function runExtractionCommand(command,args){let result2=spawnSync4(command,args,{stdio:"pipe"});return!result2.error&&result2.status===0?null:`${command}: ${formatSpawnFailure(result2)}`}function extractTarGzArchive(archivePath,extractDir,assetName){let failure=runExtractionCommand("tar",["xzf",archivePath,"-C",extractDir]);if(failure)throw new Error(`Failed to extract ${assetName}: ${failure}`)}function getWindowsTarCommand(){let systemRoot=process.env.SystemRoot??process.env.WINDIR;if(systemRoot){let systemTar=join21(systemRoot,"System32","tar.exe");if(existsSync12(systemTar))return systemTar}return"tar.exe"}function extractZipArchive(archivePath,extractDir,assetName){let failures=[];if(platform()==="win32"){let tarFailure=runExtractionCommand(getWindowsTarCommand(),["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure);let powershellFailure=runExtractionCommand("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }",archivePath,extractDir]);if(!powershellFailure)return;failures.push(powershellFailure)}else{let unzipFailure=runExtractionCommand("unzip",["-q",archivePath,"-d",extractDir]);if(!unzipFailure)return;failures.push(unzipFailure);let tarFailure=runExtractionCommand("tar",["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure)}throw new Error(`Failed to extract ${assetName}: ${failures.join("; ")}`)}async function downloadTool(tool){let config=TOOLS[tool];if(!config)throw new Error(`Unknown tool: ${tool}`);let plat=platform(),architecture=arch(),version2=tool==="fd"&&plat==="darwin"&&architecture==="x64"?"10.3.0":await getLatestVersion(config.repo),assetName=config.getAssetName(version2,plat,architecture);if(!assetName)throw new Error(`Unsupported platform: ${plat}/${architecture}`);mkdirSync6(TOOLS_DIR,{recursive:!0});let downloadUrl=`https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version2}/${assetName}`,archivePath=join21(TOOLS_DIR,assetName),binaryExt=plat==="win32"?".exe":"",binaryPath=join21(TOOLS_DIR,config.binaryName+binaryExt);await downloadFile(downloadUrl,archivePath);let extractDir=join21(TOOLS_DIR,`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2,10)}`);mkdirSync6(extractDir,{recursive:!0});try{if(assetName.endsWith(".tar.gz"))extractTarGzArchive(archivePath,extractDir,assetName);else if(assetName.endsWith(".zip"))extractZipArchive(archivePath,extractDir,assetName);else throw new Error(`Unsupported archive format: ${assetName}`);let binaryFileName=config.binaryName+binaryExt,extractedDir=join21(extractDir,assetName.replace(/\.(tar\.gz|zip)$/,"")),extractedBinary=[join21(extractedDir,binaryFileName),join21(extractDir,binaryFileName)].find(candidate=>existsSync12(candidate));if(extractedBinary||(extractedBinary=findBinaryRecursively(extractDir,binaryFileName)??void 0),extractedBinary)renameSync(extractedBinary,binaryPath);else throw new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);plat!=="win32"&&chmodSync2(binaryPath,493)}finally{rmSync2(archivePath,{force:!0}),rmSync2(extractDir,{recursive:!0,force:!0})}return binaryPath}var TERMUX_PACKAGES={fd:"fd",rg:"ripgrep"};async function ensureTool(tool,onStatus){let existingPath=getToolPath(tool);if(existingPath)return existingPath;let config=TOOLS[tool];if(config){if(isOfflineModeEnabled2()){onStatus?.({type:"warning",message:`${config.name} not found. Offline mode enabled, skipping download.`});return}if(platform()==="android"){let pkgName=TERMUX_PACKAGES[tool]??tool;onStatus?.({type:"warning",message:`${config.name} not found. Install with: pkg install ${pkgName}`});return}onStatus?.({type:"info",message:`${config.name} not found. Downloading...`});try{let path14=await downloadTool(tool);return onStatus?.({type:"info",message:`${config.name} installed to ${path14}`}),path14}catch(e){let messages=[];for(let current=e,depth=0;current instanceof Error&&depth<5;current=current.cause,depth++)messages.includes(current.message)||messages.push(current.message);onStatus?.({type:"warning",message:`Failed to download ${config.name}: ${messages.length>0?messages.join(": "):String(e)}`});return}}}function formatFindCall(args,theme2){let pattern=str(args?.pattern),rawPath=str(args?.path),path14=rawPath!==null?shortenPath2(rawPath||"."):null,limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("find"))+" "+(pattern===null?invalidArg:theme2.fg("accent",pattern||""))+theme2.fg("toolOutput",` in ${path14===null?invalidArg:path14}`);return limit!==void 0&&(text2+=theme2.fg("toolOutput",` (limit ${limit})`)),text2}function formatFindResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
1182
1182
|
`),maxLines=options.expanded?lines.length:20,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
1183
1183
|
${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
1184
|
-
`)}`,remaining>0&&(text2
|
|
1185
|
-
${
|
|
1186
|
-
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var findRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatFindCall(args,theme2
|
|
1184
|
+
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1185
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`)}let resultLimit=result2.details?.resultLimitReached,truncation=result2.details?.truncation;if(resultLimit||truncation?.truncated){let warnings=[];resultLimit&&warnings.push(`${resultLimit} results limit`),truncation?.truncated&&warnings.push(`${formatSize(truncation.maxBytes??51200)} limit`),text2+=`
|
|
1186
|
+
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var findRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatFindCall(args,theme2)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatFindResult(result2,options,theme2,context.showImages)),text2}};function toPosixPath3(value2,pathModule=path8){return value2.split(pathModule.sep).join("/")}function relativizeFindResultPath(resultPath,searchPath,pathModule=path8){let hadTrailingSeparator=resultPath.endsWith(pathModule.sep)||pathModule.sep==="\\"&&resultPath.endsWith("/"),posixPath=(pathModule.isAbsolute(resultPath)?pathModule.relative(searchPath,resultPath):resultPath).split(pathModule.sep).join("/");return hadTrailingSeparator&&!posixPath.endsWith("/")?`${posixPath}/`:posixPath}function matchesFindResultPath(resultPath,searchPath,pattern,pathModule=path8){let normalizedResult=resultPath.replace(/\r$/,"").trim();if(!normalizedResult)return!1;let candidate=pathModule.isAbsolute(pattern)?toPosixPath3(normalizedResult,pathModule):toPosixPath3(pathModule.relative(searchPath,normalizedResult),pathModule),candidateWithDirectoryMarker=(normalizedResult.endsWith("/")||normalizedResult.endsWith("\\"))&&!candidate.endsWith("/")?`${candidate}/`:candidate;return minimatch(candidateWithDirectoryMarker,toPosixPath3(pattern,pathModule),{dot:!0,nocase:!/[A-Z]/u.test(pattern)})}var findSchema=typebox_exports.Object({pattern:typebox_exports.String({description:"Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'"}),path:typebox_exports.Optional(typebox_exports.String({description:"Directory to search in (default: current directory)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of results (default: 1000)"}))}),findToolSystemPromptContribution={snippet:"Find files by glob pattern (respects .gitignore)",guidelines:[]},DEFAULT_LIMIT=1e3,defaultFindOperations={exists:pathExists,glob:()=>[]};function createFindToolDefinition(cwd,options){let customOps=options?.operations;return{name:"find",label:"find",description:`Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${51200/1024}KB (whichever is hit first).`,promptSnippet:findToolSystemPromptContribution.snippet,parameters:findSchema,async execute(_toolCallId,{pattern,path:searchDir,limit},signal,_onUpdate,ctx){return new Promise((resolve17,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let settled=!1,stopChild,settle=fn=>{settled||(settled=!0,signal?.removeEventListener("abort",onAbort),stopChild=void 0,fn())},onAbort=()=>{stopChild?.(),settle(()=>reject(new Error("Operation aborted")))};signal?.addEventListener("abort",onAbort,{once:!0}),(async()=>{try{let searchPath=resolveToCwd(searchDir||".",ctx?.cwd||cwd),effectiveLimit=limit??DEFAULT_LIMIT,ops=customOps??defaultFindOperations;if(customOps?.glob){if(!await ops.exists(searchPath)){settle(()=>reject(new Error(`Path not found: ${searchPath}`)));return}if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let results=await ops.glob(pattern,searchPath,{ignore:["**/node_modules/**","**/.git/**"],limit:effectiveLimit});if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}if(results.length===0){settle(()=>resolve17({content:[{type:"text",text:"No files found matching pattern"}],details:void 0}));return}let relativized=results.map(p=>relativizeFindResultPath(p,searchPath)),resultLimitReached=relativized.length>=effectiveLimit,rawOutput=relativized.join(`
|
|
1187
1187
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),resultOutput=truncation.content,details={},notices=[];resultLimitReached&&(notices.push(`${effectiveLimit} results limit reached`),details.resultLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(resultOutput+=`
|
|
1188
1188
|
|
|
1189
1189
|
[${notices.join(". ")}]`),settle(()=>resolve17({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}));return}let fdPath=await ensureTool("fd");if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}if(!fdPath){settle(()=>reject(new Error("fd is not available and could not be downloaded")));return}let args=["--glob","--color=never","--hidden"],needsWindowsPathFilter=process.platform==="win32"&&pattern.includes("/"),insideGitRepo=!1;for(let current=searchPath;;){if(await pathExists(path8.join(current,".git"))){insideGitRepo=!0;break}let parent=path8.dirname(current);if(parent===current)break;current=parent}insideGitRepo||args.push("--no-require-git"),needsWindowsPathFilter||args.push("--max-results",String(effectiveLimit));let effectivePattern=pattern;pattern.includes("/")&&(needsWindowsPathFilter?effectivePattern="**":(args.push("--full-path"),!pattern.startsWith("/")&&!pattern.startsWith("**/")&&pattern!=="**"&&(effectivePattern=`**/${pattern}`)),process.platform==="win32"&&(effectivePattern=effectivePattern.replaceAll("/",String.raw`[/\\]`))),args.push("--",effectivePattern,searchPath);let child=spawn5(fdPath,args,{stdio:["ignore","pipe","pipe"]}),rl=createInterface2({input:child.stdout}),stderr="",lines=[];stopChild=()=>{child.killed||child.kill()};let cleanup=()=>{rl.close()};child.stderr?.on("data",chunk=>{stderr+=chunk.toString()}),rl.on("line",line=>{needsWindowsPathFilter&&(lines.length>=effectiveLimit||!matchesFindResultPath(line,searchPath,pattern))||(lines.push(line),needsWindowsPathFilter&&lines.length>=effectiveLimit&&stopChild?.())}),child.on("error",error=>{cleanup(),settle(()=>reject(new Error(`Failed to run fd: ${error.message}`)))}),child.on("close",code=>{if(cleanup(),signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let output=lines.join(`
|
|
1190
1190
|
`);if(code!==0){let errorMsg=stderr.trim()||`fd exited with code ${code}`;if(!output){settle(()=>reject(new Error(errorMsg)));return}}if(!output){settle(()=>resolve17({content:[{type:"text",text:"No files found matching pattern"}],details:void 0}));return}let relativized=[];for(let rawLine of lines){let line=rawLine.replace(/\r$/,"").trim();line&&relativized.push(relativizeFindResultPath(line,searchPath))}let resultLimitReached=relativized.length>=effectiveLimit,rawOutput=relativized.join(`
|
|
1191
1191
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),resultOutput=truncation.content,details={},notices=[];resultLimitReached&&(notices.push(`${effectiveLimit} results limit reached. Use limit=${effectiveLimit*2} for more, or refine pattern`),details.resultLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(resultOutput+=`
|
|
1192
1192
|
|
|
1193
|
-
[${notices.join(". ")}]`),settle(()=>resolve17({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}))})}catch(e){if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let error=e instanceof Error?e:new Error(String(e));settle(()=>reject(error))}})()})},...findRenderers}}function createFindTool(cwd,options){return wrapToolDefinition(createFindToolDefinition(cwd,options))}import{readFile as fsReadFile2,stat as fsStat}from"node:fs/promises";import{createInterface as createInterface3}from"node:readline";import{spawn as spawn6}from"child_process";import path9 from"path";function formatGrepCall(args,theme2
|
|
1193
|
+
[${notices.join(". ")}]`),settle(()=>resolve17({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}))})}catch(e){if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let error=e instanceof Error?e:new Error(String(e));settle(()=>reject(error))}})()})},...findRenderers}}function createFindTool(cwd,options){return wrapToolDefinition(createFindToolDefinition(cwd,options))}import{readFile as fsReadFile2,stat as fsStat}from"node:fs/promises";import{createInterface as createInterface3}from"node:readline";import{spawn as spawn6}from"child_process";import path9 from"path";function formatGrepCall(args,theme2){let pattern=str(args?.pattern),rawPath=str(args?.path),path14=rawPath!==null?shortenPath2(rawPath||"."):null,glob=str(args?.glob),limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("grep"))+" "+(pattern===null?invalidArg:theme2.fg("accent",`/${pattern||""}/`))+theme2.fg("toolOutput",` in ${path14===null?invalidArg:path14}`);glob&&(text2+=theme2.fg("toolOutput",` (${glob})`));let flags=[];return args?.ignoreCase===!0&&flags.push("-i"),args?.literal===!0&&flags.push("-F"),typeof args?.context=="number"&&flags.push(`-C ${args.context}`),flags.length>0&&(text2+=theme2.fg("toolOutput",` (${flags.join(" ")})`)),limit!==void 0&&(text2+=theme2.fg("toolOutput",` limit ${limit}`)),text2}function formatGrepResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
1194
1194
|
`),maxLines=options.expanded?lines.length:15,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
1195
1195
|
${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
1196
|
-
`)}`,remaining>0&&(text2
|
|
1197
|
-
${
|
|
1198
|
-
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var grepRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatGrepCall(args,theme2
|
|
1196
|
+
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1197
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`)}let matchLimit=result2.details?.matchLimitReached,truncation=result2.details?.truncation,linesTruncated=result2.details?.linesTruncated;if(matchLimit||truncation?.truncated||linesTruncated){let warnings=[];matchLimit&&warnings.push(`${matchLimit} matches limit`),truncation?.truncated&&warnings.push(`${formatSize(truncation.maxBytes??51200)} limit`),linesTruncated&&warnings.push("some lines truncated"),text2+=`
|
|
1198
|
+
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var grepRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatGrepCall(args,theme2)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatGrepResult(result2,options,theme2,context.showImages)),text2}};var grepSchema=typebox_exports.Object({pattern:typebox_exports.String({description:"Search pattern (regex or literal string)"}),path:typebox_exports.Optional(typebox_exports.String({description:"Directory or file to search (default: current directory)"})),glob:typebox_exports.Optional(typebox_exports.String({description:"Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'"})),ignoreCase:typebox_exports.Optional(typebox_exports.Boolean({description:"Case-insensitive search (default: false)"})),literal:typebox_exports.Optional(typebox_exports.Boolean({description:"Treat pattern as literal string instead of regex (default: false)"})),context:typebox_exports.Optional(typebox_exports.Number({description:"Number of lines to show before and after each match (default: 0)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of matches to return (default: 100)"}))}),grepToolSystemPromptContribution={snippet:"Search file contents for patterns (respects .gitignore)",guidelines:[]},DEFAULT_LIMIT2=100,defaultGrepOperations={isDirectory:async p=>(await fsStat(p)).isDirectory(),readFile:p=>fsReadFile2(p,"utf-8")};function createGrepToolDefinition(cwd,options){let customOps=options?.operations;return{name:"grep",label:"grep",description:`Search file contents for a pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT2} matches or ${51200/1024}KB (whichever is hit first). Long lines are truncated to ${500} chars.`,promptSnippet:grepToolSystemPromptContribution.snippet,parameters:grepSchema,async execute(_toolCallId,{pattern,path:searchDir,glob,ignoreCase,literal,context,limit},signal,_onUpdate,ctx){return new Promise((resolve17,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let settled=!1,settle=fn=>{settled||(settled=!0,fn())};(async()=>{try{let rgPath=await ensureTool("rg");if(!rgPath){settle(()=>reject(new Error("ripgrep (rg) is not available and could not be downloaded")));return}let searchPath=resolveToCwd(searchDir||".",ctx?.cwd||cwd),ops=customOps??defaultGrepOperations,isDirectory;try{isDirectory=await ops.isDirectory(searchPath)}catch{settle(()=>reject(new Error(`Path not found: ${searchPath}`)));return}let contextValue=context&&context>0?context:0,effectiveLimit=Math.max(1,limit??DEFAULT_LIMIT2),formatPath=filePath=>{if(isDirectory){let relative12=path9.relative(searchPath,filePath);if(relative12&&!relative12.startsWith(".."))return relative12.replace(/\\/g,"/")}return path9.basename(filePath)},fileCache=new Map,getFileLines=async filePath=>{let lines=fileCache.get(filePath);if(!lines){try{lines=(await ops.readFile(filePath)).replace(/\r\n/g,`
|
|
1199
1199
|
`).replace(/\r/g,`
|
|
1200
1200
|
`).split(`
|
|
1201
1201
|
`)}catch{lines=[]}fileCache.set(filePath,lines)}return lines},args=["--json","--line-number","--color=never","--hidden"];ignoreCase&&args.push("--ignore-case"),literal&&args.push("--fixed-strings"),glob&&args.push("--glob",glob),args.push("--",pattern,searchPath);let child=spawn6(rgPath,args,{stdio:["ignore","pipe","pipe"]}),rl=createInterface3({input:child.stdout}),stderr="",matchCount=0,matchLimitReached=!1,linesTruncated=!1,aborted=!1,killedDueToLimit=!1,outputLines=[],cleanup=()=>{rl.close(),signal?.removeEventListener("abort",onAbort)},stopChild=(dueToLimit=!1)=>{child.killed||(killedDueToLimit=dueToLimit,child.kill())},onAbort=()=>{aborted=!0,stopChild()};signal?.addEventListener("abort",onAbort,{once:!0}),child.stderr?.on("data",chunk=>{stderr+=chunk.toString()});let formatBlock=async(filePath,lineNumber)=>{let relativePath=formatPath(filePath),lines=await getFileLines(filePath);if(!lines.length)return[`${relativePath}:${lineNumber}: (unable to read file)`];let block=[],start=contextValue>0?Math.max(1,lineNumber-contextValue):lineNumber,end=contextValue>0?Math.min(lines.length,lineNumber+contextValue):lineNumber;for(let current=start;current<=end;current++){let sanitized=(lines[current-1]??"").replace(/\r/g,""),isMatchLine=current===lineNumber,{text:truncatedText,wasTruncated}=truncateLine(sanitized);wasTruncated&&(linesTruncated=!0),isMatchLine?block.push(`${relativePath}:${current}: ${truncatedText}`):block.push(`${relativePath}-${current}- ${truncatedText}`)}return block},matches=[];rl.on("line",line=>{if(!line.trim()||matchCount>=effectiveLimit)return;let event;try{event=JSON.parse(line)}catch{return}if(event.type==="match"){matchCount++;let filePath=event.data?.path?.text,lineNumber=event.data?.line_number,lineText=event.data?.lines?.text;filePath&&typeof lineNumber=="number"&&matches.push({filePath,lineNumber,lineText}),matchCount>=effectiveLimit&&(matchLimitReached=!0,stopChild(!0))}}),child.on("error",error=>{cleanup(),settle(()=>reject(new Error(`Failed to run ripgrep: ${error.message}`)))}),child.on("close",async code=>{if(cleanup(),aborted){settle(()=>reject(new Error("Operation aborted")));return}if(!killedDueToLimit&&code!==0&&code!==1){let errorMsg=stderr.trim()||`ripgrep exited with code ${code}`;settle(()=>reject(new Error(errorMsg)));return}if(matchCount===0){settle(()=>resolve17({content:[{type:"text",text:"No matches found"}],details:void 0}));return}for(let match2 of matches)if(contextValue===0&&match2.lineText!==void 0){let relativePath=formatPath(match2.filePath),sanitized=match2.lineText.replace(/\r\n/g,`
|
|
@@ -1205,20 +1205,20 @@ ${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var
|
|
|
1205
1205
|
[${notices.join(". ")}]`),settle(()=>resolve17({content:[{type:"text",text:output}],details:Object.keys(details).length>0?details:void 0}))})}catch(err2){settle(()=>reject(err2))}})()})},...grepRenderers}}function createGrepTool(cwd,options){return wrapToolDefinition(createGrepToolDefinition(cwd,options))}import{readdir as fsReaddir,stat as fsStat2}from"node:fs/promises";import nodePath from"path";function formatLsCall(args,theme2,cwd){let limit=args?.limit,pathDisplay=renderToolPath(str(args?.path),theme2,cwd,{emptyFallback:"."}),text2=`${theme2.fg("toolTitle",theme2.bold("ls"))} ${pathDisplay}`;return limit!==void 0&&(text2+=theme2.fg("toolOutput",` (limit ${limit})`)),text2}function formatLsResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
1206
1206
|
`),maxLines=options.expanded?lines.length:20,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
1207
1207
|
${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
1208
|
-
`)}`,remaining>0&&(text2
|
|
1209
|
-
${
|
|
1210
|
-
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var lsRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsCall(args,theme2,context.cwd)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsResult(result2,options,theme2,context.showImages)),text2}};var lsSchema=typebox_exports.Object({path:typebox_exports.Optional(typebox_exports.String({description:"Directory to list (default: current directory)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of entries to return (default: 500)"}))}),lsToolSystemPromptContribution={snippet:"List directory contents",guidelines:[]},DEFAULT_LIMIT3=500,defaultLsOperations={exists:pathExists,stat:fsStat2,readdir:fsReaddir};function createLsToolDefinition(cwd,options){let ops=options?.operations??defaultLsOperations;return{name:"ls",label:"ls",description:`List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT3} entries or ${51200/1024}KB (whichever is hit first).`,promptSnippet:lsToolSystemPromptContribution.snippet,parameters:lsSchema,
|
|
1208
|
+
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1209
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`)}let entryLimit=result2.details?.entryLimitReached,truncation=result2.details?.truncation;if(entryLimit||truncation?.truncated){let warnings=[];entryLimit&&warnings.push(`${entryLimit} entries limit`),truncation?.truncated&&warnings.push(`${formatSize(truncation.maxBytes??51200)} limit`),text2+=`
|
|
1210
|
+
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var lsRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsCall(args,theme2,context.cwd)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsResult(result2,options,theme2,context.showImages)),text2}};var lsSchema=typebox_exports.Object({path:typebox_exports.Optional(typebox_exports.String({description:"Directory to list (default: current directory)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of entries to return (default: 500)"}))}),lsToolSystemPromptContribution={snippet:"List directory contents",guidelines:[]},DEFAULT_LIMIT3=500,defaultLsOperations={exists:pathExists,stat:fsStat2,readdir:fsReaddir};function createLsToolDefinition(cwd,options){let ops=options?.operations??defaultLsOperations;return{name:"ls",label:"ls",description:`List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT3} entries or ${51200/1024}KB (whichever is hit first).`,promptSnippet:lsToolSystemPromptContribution.snippet,parameters:lsSchema,async execute(_toolCallId,{path:path14,limit},signal,_onUpdate,ctx){return new Promise((resolve17,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let onAbort=()=>reject(new Error("Operation aborted"));signal?.addEventListener("abort",onAbort,{once:!0}),(async()=>{try{let dirPath=resolveToCwd(path14||".",ctx?.cwd||cwd),effectiveLimit=limit??DEFAULT_LIMIT3;if(!await ops.exists(dirPath)){reject(new Error(`Path not found: ${dirPath}`));return}if(!(await ops.stat(dirPath)).isDirectory()){reject(new Error(`Not a directory: ${dirPath}`));return}let entries;try{entries=await ops.readdir(dirPath)}catch(e){reject(new Error(`Cannot read directory: ${e.message}`));return}entries.sort((a,b2)=>a.toLowerCase().localeCompare(b2.toLowerCase()));let results=[],entryLimitReached=!1;for(let entry of entries){if(results.length>=effectiveLimit){entryLimitReached=!0;break}let fullPath=nodePath.join(dirPath,entry),suffix="";try{(await ops.stat(fullPath)).isDirectory()&&(suffix="/")}catch{continue}results.push(entry+suffix)}if(signal?.removeEventListener("abort",onAbort),results.length===0){resolve17({content:[{type:"text",text:"(empty directory)"}],details:void 0});return}let rawOutput=results.join(`
|
|
1211
1211
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),output=truncation.content,details={},notices=[];entryLimitReached&&(notices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit*2} for more`),details.entryLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(output+=`
|
|
1212
1212
|
|
|
1213
1213
|
[${notices.join(". ")}]`),resolve17({content:[{type:"text",text:output}],details:Object.keys(details).length>0?details:void 0})}catch(e){signal?.removeEventListener("abort",onAbort),reject(e)}})()})},...lsRenderers}}function createLsTool(cwd,options){return wrapToolDefinition(createLsToolDefinition(cwd,options))}var UTF8_OUTPUT_PREFIX=`try { [Console]::OutputEncoding=[System.Text.Encoding]::UTF8 } catch {}
|
|
1214
|
-
`,powershellToolSystemPromptContribution={snippet:"Execute PowerShell commands, foreground or background",guidelines:["You can inspect PI_* environment variables for current model and session details."]};function createLocalPowerShellOperations(){let operations=createLocalShellOperations("PowerShell",getPowerShellConfig);return{exec:(command,cwd,options)=>operations.exec(`${UTF8_OUTPUT_PREFIX}${command}`,cwd,options)}}var powershellToolConfig={name:"powershell",label:"powershell",shellName:"PowerShell",prompt:"PS>",promptSnippet:powershellToolSystemPromptContribution.snippet,promptGuidelines:powershellToolSystemPromptContribution.guidelines,tempFilePrefix:"pi-powershell"};function createPowerShellToolDefinition(cwd,options){return createShellToolDefinition(cwd,powershellToolConfig,{...options,operations:options?.operations??createLocalPowerShellOperations()})}function createPowerShellTool(cwd,options){let definition=createPowerShellToolDefinition(cwd,options),tool=wrapToolDefinition(definition);return Object.assign(tool,{promptSnippet:definition.promptSnippet,promptGuidelines:definition.promptGuidelines}),tool}import{constants as constants6}from"fs";import{access as fsAccess3,readFile as fsReadFile3}from"fs/promises";function baseMimeType(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function normalizeSupportedImageMimeType(mimeType){switch(baseMimeType(mimeType)){case"image/png":return"image/png";case"image/jpeg":case"image/jpg":return"image/jpeg";case"image/gif":return"image/gif";case"image/webp":return"image/webp";default:return null}}async function normalizeImage(bytes,mimeType){let normalizedMimeType=normalizeSupportedImageMimeType(mimeType);if(normalizedMimeType)return{bytes,mimeType:normalizedMimeType};let pngBytes=await convertImageBytesToPng(bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png",convertedFrom:baseMimeType(mimeType)}:null}function conversionHint(from,to){if(!(!from||from===to))return`[Image converted from ${from} to ${to}.]`}async function processImage(bytes,mimeType,options){let autoResizeImages=options?.autoResizeImages??!0,normalized=await normalizeImage(bytes,mimeType);if(!normalized)return{ok:!1,message:"[Image omitted: could not be converted to a supported inline image format.]"};if(autoResizeImages){let resized=await resizeImage(normalized.bytes,normalized.mimeType,options?.resizeOptions);if(!resized)return{ok:!1,message:"[Image omitted: could not be resized below the inline image size limit.]"};let hints2=[],convertedHint2=conversionHint(normalized.convertedFrom,resized.mimeType);convertedHint2&&hints2.push(convertedHint2);let dimensionNote=formatDimensionNote(resized);return dimensionNote&&hints2.push(dimensionNote),{ok:!0,data:resized.data,mimeType:resized.mimeType,hints:hints2}}let hints=[],convertedHint=conversionHint(normalized.convertedFrom,normalized.mimeType);return convertedHint&&hints.push(convertedHint),{ok:!0,data:Buffer.from(normalized.bytes).toString("base64"),mimeType:normalized.mimeType,hints}}import{basename as basename6,dirname as dirname12,isAbsolute as isAbsolute3,relative as relative4,resolve as resolvePath2,sep as sep6}from"node:path";var COMPACT_RESOURCE_FILE_NAMES=new Set(["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"]);function formatReadLineRange(args,theme2){if(args?.offset===void 0&&args?.limit===void 0)return"";let startLine=args.offset??1,endLine=args.limit!==void 0?startLine+args.limit-1:"";return theme2.fg("
|
|
1214
|
+
`,powershellToolSystemPromptContribution={snippet:"Execute PowerShell commands, foreground or background",guidelines:["You can inspect PI_* environment variables for current model and session details."]};function createLocalPowerShellOperations(){let operations=createLocalShellOperations("PowerShell",getPowerShellConfig);return{exec:(command,cwd,options)=>operations.exec(`${UTF8_OUTPUT_PREFIX}${command}`,cwd,options)}}var powershellToolConfig={name:"powershell",label:"powershell",shellName:"PowerShell",prompt:"PS>",promptSnippet:powershellToolSystemPromptContribution.snippet,promptGuidelines:powershellToolSystemPromptContribution.guidelines,tempFilePrefix:"pi-powershell"};function createPowerShellToolDefinition(cwd,options){return createShellToolDefinition(cwd,powershellToolConfig,{...options,operations:options?.operations??createLocalPowerShellOperations()})}function createPowerShellTool(cwd,options){let definition=createPowerShellToolDefinition(cwd,options),tool=wrapToolDefinition(definition);return Object.assign(tool,{promptSnippet:definition.promptSnippet,promptGuidelines:definition.promptGuidelines}),tool}import{constants as constants6}from"fs";import{access as fsAccess3,readFile as fsReadFile3}from"fs/promises";function baseMimeType(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function normalizeSupportedImageMimeType(mimeType){switch(baseMimeType(mimeType)){case"image/png":return"image/png";case"image/jpeg":case"image/jpg":return"image/jpeg";case"image/gif":return"image/gif";case"image/webp":return"image/webp";default:return null}}async function normalizeImage(bytes,mimeType){let normalizedMimeType=normalizeSupportedImageMimeType(mimeType);if(normalizedMimeType)return{bytes,mimeType:normalizedMimeType};let pngBytes=await convertImageBytesToPng(bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png",convertedFrom:baseMimeType(mimeType)}:null}function conversionHint(from,to){if(!(!from||from===to))return`[Image converted from ${from} to ${to}.]`}async function processImage(bytes,mimeType,options){let autoResizeImages=options?.autoResizeImages??!0,normalized=await normalizeImage(bytes,mimeType);if(!normalized)return{ok:!1,message:"[Image omitted: could not be converted to a supported inline image format.]"};if(autoResizeImages){let resized=await resizeImage(normalized.bytes,normalized.mimeType,options?.resizeOptions);if(!resized)return{ok:!1,message:"[Image omitted: could not be resized below the inline image size limit.]"};let hints2=[],convertedHint2=conversionHint(normalized.convertedFrom,resized.mimeType);convertedHint2&&hints2.push(convertedHint2);let dimensionNote=formatDimensionNote(resized);return dimensionNote&&hints2.push(dimensionNote),{ok:!0,data:resized.data,mimeType:resized.mimeType,hints:hints2}}let hints=[],convertedHint=conversionHint(normalized.convertedFrom,normalized.mimeType);return convertedHint&&hints.push(convertedHint),{ok:!0,data:Buffer.from(normalized.bytes).toString("base64"),mimeType:normalized.mimeType,hints}}import{basename as basename6,dirname as dirname12,isAbsolute as isAbsolute3,relative as relative4,resolve as resolvePath2,sep as sep6}from"node:path";var COMPACT_RESOURCE_FILE_NAMES=new Set(["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"]);function formatReadLineRange(args,theme2){if(args?.offset===void 0&&args?.limit===void 0)return"";let startLine=args.offset??1,endLine=args.limit!==void 0?startLine+args.limit-1:"";return theme2.fg("warning",`:${startLine}${endLine?`-${endLine}`:""}`)}function formatReadCall(args,theme2,cwd){let pathDisplay=renderToolPath(str(args?.file_path??args?.path),theme2,cwd);return`${theme2.fg("toolTitle",theme2.bold("read"))} ${pathDisplay}${formatReadLineRange(args,theme2)}`}function trimTrailingEmptyLines(lines){let end=lines.length;for(;end>0&&lines[end-1]==="";)end--;return lines.slice(0,end)}function toPosixPath4(filePath){return filePath.split(sep6).join("/")}function getPiDocsClassification(absolutePath){let packageRoot=dirname12(getReadmePath()),relativePath=relative4(resolvePath2(packageRoot),resolvePath2(absolutePath));if(relativePath===""||relativePath===".."||relativePath.startsWith(`..${sep6}`)||isAbsolute3(relativePath))return;let label=toPosixPath4(relativePath);if(label==="README.md"||label.startsWith("docs/")||label.startsWith("examples/"))return{kind:"docs",label}}function getCompactReadClassification(args,cwd){let rawPath=str(args?.file_path??args?.path);if(!rawPath)return;let absolutePath=resolveToCwd(rawPath,cwd),fileName=basename6(absolutePath);if(fileName==="SKILL.md")return{kind:"skill",label:basename6(dirname12(absolutePath))||fileName};let docsClassification=getPiDocsClassification(absolutePath);if(docsClassification)return docsClassification;if(COMPACT_RESOURCE_FILE_NAMES.has(fileName))return{kind:"resource",label:formatPathRelativeToCwdOrAbsolute(absolutePath,cwd)}}function formatCompactReadCall(classification,args,theme2){let expandHint=theme2.fg("dim",` (${keyText("app.tools.expand")} to expand)`);return classification.kind==="skill"?theme2.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme2.fg("customMessageText",classification.label)+formatReadLineRange(args,theme2)+expandHint:theme2.fg("toolTitle",theme2.bold(`read ${classification.kind}`))+" "+theme2.fg("accent",classification.label)+formatReadLineRange(args,theme2)+expandHint}function formatReadResult(args,result2,options,theme2,showImages,_cwd,isError){let rawPath=str(args?.file_path??args?.path),output=getTextOutput(result2,showImages),lang=!isError&&rawPath?getLanguageFromPath(rawPath):void 0,renderedLines=lang?highlightCode(replaceTabs(output),lang):output.split(`
|
|
1215
1215
|
`),lines=trimTrailingEmptyLines(renderedLines),maxLines=options.expanded?lines.length:10,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines,text2=`
|
|
1216
1216
|
${displayLines.map(line=>lang?replaceTabs(line):theme2.fg("toolOutput",replaceTabs(line))).join(`
|
|
1217
|
-
`)}`;remaining>0&&(text2
|
|
1218
|
-
${
|
|
1217
|
+
`)}`;remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1218
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`);let truncation=result2.details?.truncation;return truncation?.truncated&&(truncation.firstLineExceedsLimit?text2+=`
|
|
1219
1219
|
${theme2.fg("warning",`[First line exceeds ${formatSize(truncation.maxBytes??51200)} limit]`)}`:truncation.truncatedBy==="lines"?text2+=`
|
|
1220
1220
|
${theme2.fg("warning",`[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines??2e3} line limit)]`)}`:text2+=`
|
|
1221
|
-
${theme2.fg("warning",`[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes??51200)} limit)]`)}`),text2}var readRenderers={renderCall(rawArgs,theme2,context){let args=rawArgs,text2=context.lastComponent??new Text("",0,0),classification=context.expanded?void 0:getCompactReadClassification(args,context.cwd);return text2.setText(classification?formatCompactReadCall(classification,args,theme2
|
|
1221
|
+
${theme2.fg("warning",`[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes??51200)} limit)]`)}`),text2}var readRenderers={renderCall(rawArgs,theme2,context){let args=rawArgs,text2=context.lastComponent??new Text("",0,0),classification=context.expanded?void 0:getCompactReadClassification(args,context.cwd);return text2.setText(classification?formatCompactReadCall(classification,args,theme2):formatReadCall(args,theme2,context.cwd)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatReadResult(context.args,result2,options,theme2,context.showImages,context.cwd,context.isError)),text2}};var readSchema2=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to read (relative or absolute)"}),offset:typebox_exports.Optional(typebox_exports.Number({description:"Line number to start reading from (1-indexed)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of lines to read"}))}),readToolSystemPromptContribution={snippet:"Read file contents",guidelines:["Use read to examine files instead of cat or sed."]},defaultReadOperations={readFile:path14=>fsReadFile3(path14),access:path14=>fsAccess3(path14,constants6.R_OK),detectImageMimeType:detectSupportedImageMimeTypeFromFile};function getNonVisionImageNote(model){if(!(!model||model.input.includes("image")))return"[Current model does not support images. The image will be omitted from this request.]"}function createReadToolDefinition(cwd,options){let autoResizeImages=options?.autoResizeImages??!0,fallbackResizeOptions=options?.resizeOptions,ops=options?.operations??defaultReadOperations;return{name:"read",label:"read",description:`Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp). Images are sent as attachments. For text files, output is truncated to ${2e3} lines or ${51200/1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,promptSnippet:readToolSystemPromptContribution.snippet,promptGuidelines:[...readToolSystemPromptContribution.guidelines],parameters:readSchema2,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_toolCallId,{path:path14,offset,limit},signal,_onUpdate,ctx){return new Promise((resolve17,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let aborted=!1,onAbort=()=>{aborted=!0,reject(new Error("Operation aborted"))};signal?.addEventListener("abort",onAbort,{once:!0}),(async()=>{try{let absolutePath=await resolveReadPathAsync(path14,ctx?.cwd||cwd);if(aborted||(await ops.access(absolutePath),aborted))return;let mimeType=ops.detectImageMimeType?await ops.detectImageMimeType(absolutePath):void 0,content,details,nonVisionImageNote=getNonVisionImageNote(ctx?.model);if(mimeType){let buffer=await ops.readFile(absolutePath),processed=await processImage(buffer,mimeType,{autoResizeImages,resizeOptions:ctx?.model?.inputLimits?.images?.resize??fallbackResizeOptions});if(processed.ok){let textNote=`Read image file [${processed.mimeType}]`;processed.hints.length>0&&(textNote+=`
|
|
1222
1222
|
${processed.hints.join(`
|
|
1223
1223
|
`)}`),nonVisionImageNote&&(textNote+=`
|
|
1224
1224
|
${nonVisionImageNote}`),content=[{type:"text",text:textNote},{type:"image",data:processed.data,mimeType:processed.mimeType}]}else{let textNote=`Read image file [${mimeType}]
|
|
@@ -1241,8 +1241,8 @@ ${theme2.fg("error","[invalid content arg - expected string]")}`;else if(fileCon
|
|
|
1241
1241
|
`),lines=trimTrailingEmptyLines2(renderedLines),totalLines=lines.length,maxLines=options.expanded?lines.length:10,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
1242
1242
|
|
|
1243
1243
|
${displayLines.map(line=>lang?line:theme2.fg("toolOutput",replaceTabs(line))).join(`
|
|
1244
|
-
`)}`,remaining>0&&(text2
|
|
1245
|
-
${
|
|
1244
|
+
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1245
|
+
... (${remaining} more lines, ${totalLines} total,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`)}return text2}function formatWriteResult(result2,theme2){if(!result2.isError)return;let output=result2.content.filter(c=>c.type==="text").map(c=>c.text||"").join(`
|
|
1246
1246
|
`);if(output)return`
|
|
1247
1247
|
${theme2.fg("error",output)}`}var writeRenderers={renderCall(args,theme2,context){let renderArgs=args,rawPath=str(renderArgs?.file_path??renderArgs?.path),fileContent=str(renderArgs?.content),component=context.lastComponent??new WriteCallRenderComponent;return fileContent!==null?component.cache=context.argsComplete?rebuildWriteHighlightCacheFull(rawPath,fileContent):updateWriteHighlightCacheIncremental(component.cache,rawPath,fileContent):component.cache=void 0,component.setText(formatWriteCall(renderArgs,{expanded:context.expanded,isPartial:context.isPartial},theme2,component.cache,context.cwd)),component},renderResult(result2,_options,theme2,context){let output=formatWriteResult({...result2,isError:context.isError},theme2);if(!output){let component=context.lastComponent??new Container;return component.clear(),component}let text2=context.lastComponent??new Text("",0,0);return text2.setText(output),text2}};var writeSchema2=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to write (relative or absolute)"}),content:typebox_exports.String({description:"Content to write to the file"})}),writeToolSystemPromptContribution={snippet:"Create or overwrite files",guidelines:["Use write only for new files or complete rewrites."]},defaultWriteOperations={writeFile:(path14,content)=>fsWriteFile2(path14,content,"utf-8"),mkdir:dir=>fsMkdir(dir,{recursive:!0}).then(()=>{})};function createWriteToolDefinition(cwd,options){let ops=options?.operations??defaultWriteOperations;return{name:"write",label:"write",description:"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",promptSnippet:writeToolSystemPromptContribution.snippet,promptGuidelines:[...writeToolSystemPromptContribution.guidelines],parameters:writeSchema2,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_toolCallId,{path:path14,content},signal,_onUpdate,ctx){let absolutePath=resolveToCwd(path14,ctx?.cwd||cwd),dir=dirname13(absolutePath);return withFileMutationQueue2(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};return throwIfAborted(),await ops.mkdir(dir),throwIfAborted(),await ops.writeFile(absolutePath,content),throwIfAborted(),{content:[{type:"text",text:`Successfully wrote to ${path14}`}],details:void 0}})},...writeRenderers}}function createWriteTool2(cwd,options){return wrapToolDefinition(createWriteToolDefinition(cwd,options))}function createAllToolDefinitions(cwd,options){return{read:createReadToolDefinition(cwd,options?.read),bash:createBashToolDefinition(cwd,options?.bash),powershell:createPowerShellToolDefinition(cwd,options?.powershell),edit:createEditToolDefinition(cwd,options?.edit),write:createWriteToolDefinition(cwd,options?.write),grep:createGrepToolDefinition(cwd,options?.grep),find:createFindToolDefinition(cwd,options?.find),ls:createLsToolDefinition(cwd,options?.ls)}}function createCodingTools(cwd,options){return[createReadTool2(cwd,options?.read),createBashTool2(cwd,options?.bash),createEditTool2(cwd,options?.edit),createWriteTool2(cwd,options?.write)]}function createReadOnlyTools(cwd,options){return[createReadTool2(cwd,options?.read),createGrepTool(cwd,options?.grep),createFindTool(cwd,options?.find),createLsTool(cwd,options?.ls)]}import{readFileSync as readFileSync11}from"node:fs";import{basename as basename9,dirname as dirname17}from"node:path";function sleep3(ms,signal){return new Promise((resolve17,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve17,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}async function normalizeToolResultImages(content,options){if(!content.some(block=>block.type==="image"))return content;let autoResizeImages=options?.autoResizeImages??!0,normalized=[],changed=!1;for(let block of content){if(block.type!=="image"){normalized.push(block);continue}let processed=await processImage(Buffer.from(block.data,"base64"),block.mimeType,{autoResizeImages,resizeOptions:options?.resizeOptions});if(!processed.ok){normalized.push(block);continue}if(processed.data===block.data&&processed.mimeType===block.mimeType&&processed.hints.length===0){normalized.push(block);continue}normalized.push({type:"image",data:processed.data,mimeType:processed.mimeType}),processed.hints.length>0&&normalized.push({type:"text",text:processed.hints.join(`
|
|
1248
1248
|
`)}),changed=!0}return changed?normalized:content}import{join as join22}from"node:path";var UNKNOWN_PROVIDER="unknown";function getProviderLoginHelp(){return["Use /login to log into a provider via OAuth or API key. See:",` ${join22(getDocsPath(),"providers.md")}`,` ${join22(getDocsPath(),"models.md")}`].join(`
|
|
@@ -1253,7 +1253,7 @@ ${getProviderLoginHelp()}
|
|
|
1253
1253
|
Then use /model to select a model.`}function formatNoApiKeyFoundMessage(provider){return`No API key found for ${provider===UNKNOWN_PROVIDER?"the selected model":provider}.
|
|
1254
1254
|
|
|
1255
1255
|
${getProviderLoginHelp()}`}import{appendFileSync as appendFileSync4,mkdirSync as mkdirSync7}from"node:fs";import{dirname as dirname14}from"node:path";function createUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0}}function addUsageToTotals(totals,usage){totals.input+=usage.input,totals.output+=usage.output,totals.cacheRead+=usage.cacheRead,totals.cacheWrite+=usage.cacheWrite,totals.cost+=usage.cost.total}var BACKGROUND_USAGE_TYPE="background-usage";function isRecord4(value2){return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)}function isUsageValue(value2){return typeof value2=="number"&&Number.isFinite(value2)&&value2>=0}function getBackgroundUsageRecord(entry){if(entry.type!=="custom"||entry.customType!==BACKGROUND_USAGE_TYPE)return;let data=entry.data;if(!isRecord4(data)||data.version!==1||typeof data.taskId!="string"||!data.taskId.trim())return;let usage=data.usage;if(!isRecord4(usage)||!isRecord4(usage.cost))return;let{input:input2,output,cacheRead,cacheWrite,totalTokens,reasoning,cacheWrite1h}=usage,cost=usage.cost;if(!(!isUsageValue(input2)||!isUsageValue(output)||!isUsageValue(cacheRead)||!isUsageValue(cacheWrite)||!isUsageValue(totalTokens)||!isUsageValue(cost.input)||!isUsageValue(cost.output)||!isUsageValue(cost.cacheRead)||!isUsageValue(cost.cacheWrite)||!isUsageValue(cost.total)||reasoning!==void 0&&!isUsageValue(reasoning)||cacheWrite1h!==void 0&&!isUsageValue(cacheWrite1h)))return{version:1,taskId:data.taskId,usage:{input:input2,output,cacheRead,cacheWrite,totalTokens,...reasoning===void 0?{}:{reasoning},...cacheWrite1h===void 0?{}:{cacheWrite1h},cost:{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite,total:cost.total}}}}function*accountedUsageEntries(entries){let backgroundTasks=new Set;for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant")yield{key:`${entry.message.provider}/${entry.message.responseModel??entry.message.model}`,usage:entry.message.usage};else if(entry.type==="usage")yield{key:`${entry.provider}/${entry.model}`,usage:entry.usage};else if(entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage)yield{key:"Tools/summaries",usage:entry.message.usage};else if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage)yield{key:"Tools/summaries",usage:entry.usage};else{let record=getBackgroundUsageRecord(entry);if(!record||backgroundTasks.has(record.taskId))continue;backgroundTasks.add(record.taskId),yield{key:"Tools/summaries",usage:record.usage}}}function getAccountedUsages(entries){return Array.from(accountedUsageEntries(entries),({usage})=>usage)}function getUsageCostBreakdown(entries){let totalsByKey=new Map;for(let{key,usage}of accountedUsageEntries(entries)){let totals=totalsByKey.get(key);totals||(totals=createUsageTotals(),totalsByKey.set(key,totals)),addUsageToTotals(totals,usage)}return Array.from(totalsByKey,([key,totals])=>({key,cost:totals.cost,tokens:totals.input+totals.output+totals.cacheRead+totals.cacheWrite})).filter(entry=>entry.cost>0||entry.tokens>0).sort((a,b2)=>b2.cost-a.cost)}var BackgroundSession=class{constructor(options){this.enabled=!1,this.disposed=!1,this.generation=0,this.pauses=0,this.failures=new Set,this.quarantine=[],this.options=options,this._service=this.createService()}get service(){return this._service}get quarantinedSettlements(){return structuredClone(this.quarantine)}setEnabled(enabled){this.enabled=enabled&&this.options.role==="main",this.service.setEnabled(this.enabled)}replaceService(){this.service.close(),this._service=this.createService(),this.failures.clear()}createService(){let{manager,role}=this.options,generation=++this.generation,sessionId=manager.getSessionId(),sessionFile=manager.getSessionFile(),service=new BackgroundService({enabled:this.enabled,role,anchor:()=>manager.getLeafId(),onCleanupError:message=>this.warn("background_cleanup",message),onSettled:(task,usage)=>{let onBranch=manager.getSessionId()===sessionId&&(task.anchorId===null||manager.getBranch().some(entry=>entry.id===task.anchorId));if(this.disposed||this.service!==service||!onBranch){this.quarantineSettlement({sessionId,generation,task,usage},sessionFile);return}this.persistSettlement(task,usage)}});return this.restoreHistory(service),service.subscribe(()=>this.schedule()),service}restoreHistory(service=this.service){service.restoreHistory(this.options.manager.getBranch().flatMap(entry=>entry.type==="custom"&&entry.customType==="background-task-result"?[entry.data]:[]))}quarantineSettlement(record,sessionFile){this.quarantine.push(structuredClone(record)),this.quarantine.length>32&&this.quarantine.shift();let persistence="Not persisted: only the latest 32 snapshots are retained in quarantinedBackgroundSettlements; late usage is not accounted in session totals.";if(sessionFile)try{mkdirSync7(dirname14(sessionFile),{recursive:!0}),appendFileSync4(`${sessionFile}.background-late.jsonl`,`${JSON.stringify({version:1,...record})}
|
|
1256
|
-
`),persistence=`Saved diagnostic sidecar: ${sessionFile}.background-late.jsonl (not included in normal session totals).`}catch{persistence=`Sidecar write failed. ${persistence}`}this.warn("background_settlement_quarantined",`Late background settlement ${record.task.id} was quarantined. ${persistence}`)}persistSettlement(task,usage){let manager=this.options.manager,appended=[],append=(customType,data)=>{let entry=manager.getEntry(manager.appendCustomEntry(customType,data));entry&&appended.push(entry)};try{usage&&!manager.getEntries().some(entry=>getBackgroundUsageRecord(entry)?.taskId===task.id)&&append(BACKGROUND_USAGE_TYPE,{version:1,taskId:task.id,usage}),append("background-task-result",JSON.parse(JSON.stringify({version:BACKGROUND_HISTORY_VERSION,task})))}finally{for(let entry of appended)try{this.options.onEntry(entry)}catch{}}}warn(event,message){try{this.options.onError(event,truncateHead(message,{maxBytes:4096,maxLines:32}).content)}catch{}}pause(){this.pauses++;let releaseService=this.service.pause(),released=!1;return()=>{released||(released=!0,this.pauses--,releaseService(),this.schedule())}}retry(){this.failures.clear(),this.schedule()}schedule(){this.disposed||this.timer||this.delivery||(this.timer=setTimeout(()=>{this.timer=void 0,this.drain().catch(()=>this.warn("background_delivery","Background notification drain failed; delivery was not confirmed."))},0),this.timer.unref?.())}canDeliver(service){return!this.disposed&&service===this.service&&service.enabled&&this.pauses===0&&this.options.canDeliver()}async drain(){let service=this.service;if(this.delivery||!this.canDeliver(service))return;if(this.failures.size){let retained=new Set(service.list().map(task2=>task2.id));for(let id of this.failures)retained.has(id)||this.failures.delete(id)}let task=service.pendingNotifications().find(task2=>!this.failures.has(task2.id));if(!task||!service.claimNotification(task.id))return;let delivery={id:task.id,service,persisted:!1};this.delivery=delivery;let deliveryError;try{await this.options.deliver(backgroundCompletionMessage(task))}catch(error){deliveryError=error}finally{if(!delivery.persisted){service.releaseNotification(task.id),service===this.service&&this.failures.add(task.id);let reason=deliveryError instanceof Error?`: ${deliveryError.message}`:"";this.warn("background_delivery",`Background completion delivery failed for ${task.id}${reason}; it will retry on the next prompt.`)}this.delivery=void 0;let current=this.service;this.canDeliver(current)&¤t.pendingNotifications().some(task2=>!this.failures.has(task2.id))&&this.schedule()}}messageAcknowledgement(message){if(message.role!=="custom"||message.customType!=="background-completion")return;let details=message.details,delivery=this.delivery;if(!(!delivery||details?.taskId!==delivery.id))return()=>{delivery.persisted||(delivery.persisted=!0,delivery.service.markDelivered(delivery.id))}}acknowledgeWaitResult(details){if(!details||typeof details!="object"||!("backgroundTaskId"in details))return;let id=details.backgroundTaskId;typeof id=="string"&&this.service.list().some(task=>task.id===id&&task.mode==="background"&&isBackgroundTerminal(task.status))&&this.service.markDelivered(id)}dispose(){this.disposed=!0,this.service.close(),this.timer&&clearTimeout(this.timer),this.timer=void 0}};import{randomBytes as randomBytes2}from"node:crypto";import{createWriteStream as createWriteStream3}from"node:fs";import{tmpdir as tmpdir3}from"node:os";import{join as join23}from"node:path";async function executeBashWithOperations(command,cwd,operations,options){let outputChunks=[],outputBytes=0,maxOutputBytes=51200*2,tempFilePath,tempFileStream,totalBytes=0,ensureTempFile=()=>{if(tempFilePath)return;let id=randomBytes2(8).toString("hex");tempFilePath=join23(tmpdir3(),`pi-bash-${id}.log`),tempFileStream=createWriteStream3(tempFilePath);for(let chunk of outputChunks)tempFileStream.write(chunk)},decoder=new TextDecoder,onData=data=>{totalBytes+=data.length;let text2=sanitizeBinaryOutput(stripAnsi(decoder.decode(data,{stream:!0}))).replace(/\r/g,"");for(totalBytes>51200&&ensureTempFile(),tempFileStream&&tempFileStream.write(text2),outputChunks.push(text2),outputBytes+=text2.length;outputBytes>maxOutputBytes&&outputChunks.length>1;){let removed=outputChunks.shift();outputBytes-=removed.length}options?.onChunk&&options.onChunk(text2)};try{let result2=await operations.exec(command,cwd,{onData,signal:options?.signal}),fullOutput=outputChunks.join(""),truncationResult=truncateTail(fullOutput);truncationResult.truncated&&ensureTempFile(),tempFileStream&&tempFileStream.end();let cancelled=options?.signal?.aborted??!1;return{output:truncationResult.truncated?truncationResult.content:fullOutput,exitCode:cancelled?void 0:result2.exitCode??void 0,cancelled,truncated:truncationResult.truncated,fullOutputPath:tempFilePath}}catch(err2){if(options?.signal?.aborted){let fullOutput=outputChunks.join(""),truncationResult=truncateTail(fullOutput);return truncationResult.truncated&&ensureTempFile(),tempFileStream&&tempFileStream.end(),{output:truncationResult.truncated?truncationResult.content:fullOutput,exitCode:void 0,cancelled:!0,truncated:truncationResult.truncated,fullOutputPath:tempFilePath}}throw tempFileStream&&tempFileStream.end(),err2}}import*as os5 from"node:os";import{writeFile}from"node:fs/promises";import{crc32,deflateRawSync}from"node:zlib";function dosDateTime(date){return{time:date.getHours()<<11|date.getMinutes()<<5|date.getSeconds()>>1,day:Math.max(1980,date.getFullYear())-1980<<9|date.getMonth()+1<<5|date.getDate()}}function createZipArchive(entries){let files=[],directory=[],{time:time2,day}=dosDateTime(new Date),offset=0;for(let entry of entries){let name=Buffer.from(entry.name),data=(typeof entry.data=="string",Buffer.from(entry.data)),compressed=deflateRawSync(data),checksum=crc32(data),local=Buffer.alloc(30);local.writeUInt32LE(67324752,0),local.writeUInt16LE(20,4),local.writeUInt16LE(2048,6),local.writeUInt16LE(8,8),local.writeUInt16LE(time2,10),local.writeUInt16LE(day,12),local.writeUInt32LE(checksum,14),local.writeUInt32LE(compressed.length,18),local.writeUInt32LE(data.length,22),local.writeUInt16LE(name.length,26);let central=Buffer.alloc(46);central.writeUInt32LE(33639248,0),central.writeUInt16LE(20,4),central.writeUInt16LE(20,6),central.writeUInt16LE(2048,8),central.writeUInt16LE(8,10),central.writeUInt16LE(time2,12),central.writeUInt16LE(day,14),central.writeUInt32LE(checksum,16),central.writeUInt32LE(compressed.length,20),central.writeUInt32LE(data.length,24),central.writeUInt16LE(name.length,28),central.writeUInt32LE(offset,42),files.push(local,name,compressed),directory.push(central,name),offset+=local.length+name.length+compressed.length}let centralDirectory=Buffer.concat(directory),end=Buffer.alloc(22);return end.writeUInt32LE(101010256,0),end.writeUInt16LE(entries.length,8),end.writeUInt16LE(entries.length,10),end.writeUInt32LE(centralDirectory.length,12),end.writeUInt32LE(offset,16),Buffer.concat([...files,centralDirectory,end])}function writeZipArchive(filePath,entries){return writeFile(filePath,createZipArchive(entries))}var BUG_REPORT_CUSTOM_ENTRY_TYPE="pi.bug-report",BUG_REPORT_SCHEMA_VERSION=1,REDACTED="<redacted>",SENSITIVE_KEY=/(?:^|[-_])(api[-_]?key|secret|token|password|passwd|credential|authorization|cookie)(?:$|[-_])/i;function isSensitiveKey(key){return SENSITIVE_KEY.test(key.replace(/([a-z0-9])([A-Z])/g,"$1_$2"))}function redactUrl(value2){let nested=/^([a-z][a-z0-9+.-]*:)([a-z][a-z0-9+.-]*:\/\/.*)$/i.exec(value2);if(nested)return`${nested[1]}${redactUrl(nested[2])}`;try{let url=new URL(value2),changed=!1;(url.username||url.password)&&(url.username="",url.password="",changed=!0);for(let key of url.searchParams.keys())isSensitiveKey(key)&&(url.searchParams.set(key,REDACTED),changed=!0);return changed?url.toString():value2}catch{return value2}}function redactJsonValue(value2){if(value2!==void 0)return JSON.parse(JSON.stringify(value2,(key,child)=>child!=null&&isSensitiveKey(key)?REDACTED:typeof child=="string"?redactUrl(child):child))}function redactSettings(settings2){let{trackingId:_trackingId,...rest}=settings2;return redactJsonValue(rest)}function collectEnvironment(){let env2=name=>process.env[name]||null;return{version:VERSION,userAgent:getPiUserAgent(VERSION),runtime:process.versions.bun?`bun/${process.versions.bun}`:`node/${process.version}`,platform:process.platform,arch:process.arch,osRelease:os5.release(),osVersion:os5.version(),shell:process.env.SHELL?.split(/[\\/]/).pop()||null,terminal:{term:env2("TERM"),program:env2("TERM_PROGRAM"),programVersion:env2("TERM_PROGRAM_VERSION"),colorterm:env2("COLORTERM"),tmux:!!process.env.TMUX,ssh:!!(process.env.SSH_CONNECTION||process.env.SSH_CLIENT||process.env.SSH_TTY),ci:!!process.env.CI},piEnvironmentVariables:Object.keys(process.env).filter(name=>name.startsWith("PI_")).sort()}}function describeModel(model){return{provider:model.provider,id:model.id,name:model.name,api:model.api,baseUrl:redactUrl(model.baseUrl),reasoning:model.reasoning,input:model.input,contextWindow:model.contextWindow,maxTokens:model.maxTokens,samplingParams:model.samplingParams?redactJsonValue(model.samplingParams):null,compat:model.compat?redactJsonValue(model.compat):null,thinkingLevelMap:model.thinkingLevelMap??null,headerNames:Object.keys(model.headers??{}).sort()}}function describeProvider(modelRuntime,provider){let authTypes=[];return provider.auth.apiKey&&authTypes.push("api_key"),provider.auth.oauth&&authTypes.push("oauth"),{id:provider.id,name:provider.name,baseUrl:provider.baseUrl?redactUrl(provider.baseUrl):null,headerNames:Object.keys(provider.headers??{}).sort(),authTypes,authStatus:modelRuntime.getProviderAuthStatus(provider.id),usingOAuth:modelRuntime.isUsingOAuth(provider.id),registeredByExtension:modelRuntime.getRegisteredProviderIds().includes(provider.id)}}function describeExtension(extension){return{path:extension.path,source:redactUrl(extension.sourceInfo.source),scope:extension.sourceInfo.scope,origin:extension.sourceInfo.origin,hidden:extension.hidden===!0}}function collectBugReportMetadata(options){let hint2=options.hint?.trim()||null,provider=options.model?options.modelRuntime.getProvider(options.model.provider):void 0;return{schemaVersion:BUG_REPORT_SCHEMA_VERSION,id:options.id??uuidv7(),createdAt:new Date().toISOString(),hint:hint2,environment:collectEnvironment(),session:{id:options.sessionId,included:options.includeSession,summaryIncluded:options.includeSummary,messageCount:options.messageCount,...options.includeSession?{cwd:options.cwd}:{}},model:options.model?describeModel(options.model):null,provider:provider?describeProvider(options.modelRuntime,provider):null,thinkingLevel:options.thinkingLevel,extensions:options.extensions.map(describeExtension),extensionErrors:options.extensionErrors.map(({path:path14,error})=>({path:path14,error})),settings:{global:redactSettings(options.globalSettings),project:redactSettings(options.projectSettings)}}}function collectBugReportDiagnostics(sessionManager,crashes=[]){let entries=sessionManager.getEntries(),assistant=[],assistantMessageCount=0;for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="assistant")continue;assistantMessageCount++;let message=entry.message,diagnostics=message.diagnostics??[];diagnostics.length===0&&message.stopReason!=="error"&&message.stopReason!=="aborted"&&!message.errorMessage||assistant.push({entryId:entry.id,timestamp:entry.timestamp,provider:message.provider,model:message.model,api:message.api,stopReason:message.stopReason,...message.rawStopReason===void 0?{}:{rawStopReason:message.rawStopReason},...message.errorMessage===void 0?{}:{errorMessage:message.errorMessage},diagnostics})}return{schemaVersion:BUG_REPORT_SCHEMA_VERSION,sessionId:sessionManager.getSessionId(),entryCount:entries.length,assistantMessageCount,assistant,crashes:crashes.map(({notified:_notified,...record})=>record)}}function bugReportFiles(bundle){let files=[{name:"report.json",contentType:"application/json",data:`${JSON.stringify(bundle.metadata,null,2)}
|
|
1256
|
+
`),persistence=`Saved diagnostic sidecar: ${sessionFile}.background-late.jsonl (not included in normal session totals).`}catch{persistence=`Sidecar write failed. ${persistence}`}this.warn("background_settlement_quarantined",`Late background settlement ${record.task.id} was quarantined. ${persistence}`)}persistSettlement(task,usage){let manager=this.options.manager,appended=[],append=(customType,data)=>{let entry=manager.getEntry(manager.appendCustomEntry(customType,data));entry&&appended.push(entry)};try{usage&&!manager.getEntries().some(entry=>getBackgroundUsageRecord(entry)?.taskId===task.id)&&append(BACKGROUND_USAGE_TYPE,{version:1,taskId:task.id,usage}),append("background-task-result",JSON.parse(JSON.stringify({version:BACKGROUND_HISTORY_VERSION,task})))}finally{for(let entry of appended)try{this.options.onEntry(entry)}catch{}}}warn(event,message){try{this.options.onError(event,truncateHead(message,{maxBytes:4096,maxLines:32}).content)}catch{}}pause(){this.pauses++;let releaseService=this.service.pause(),released=!1;return()=>{released||(released=!0,this.pauses--,releaseService(),this.schedule())}}retry(){this.failures.clear(),this.schedule()}schedule(){this.disposed||this.timer||this.delivery||(this.timer=setTimeout(()=>{this.timer=void 0,this.drain().catch(()=>this.warn("background_delivery","Background notification drain failed; delivery was not confirmed."))},0),this.timer.unref?.())}canDeliver(service){return!this.disposed&&service===this.service&&service.enabled&&this.pauses===0&&this.options.canDeliver()}async drain(){let service=this.service;if(this.delivery||!this.canDeliver(service))return;if(this.failures.size){let retained=new Set(service.list().map(task2=>task2.id));for(let id of this.failures)retained.has(id)||this.failures.delete(id)}let task=service.pendingNotifications().find(task2=>!this.failures.has(task2.id));if(!task)return;let message=backgroundCompletionMessage(task);if(!service.claimNotification(task.id))return;let delivery={id:task.id,service,message,phase:"pending"};this.delivery=delivery;let deliveryError;try{await this.options.deliver(delivery.message,()=>new Promise((resolve17,reject)=>{delivery.phase==="persisted"?resolve17():delivery.queued={resolve:resolve17,reject}}))}catch(error){deliveryError=error}finally{if(delivery.phase!=="persisted"){service.releaseNotification(task.id),service===this.service&&this.failures.add(task.id);let reason=deliveryError instanceof Error?`: ${deliveryError.message}`:"";this.warn("background_delivery",`Background completion delivery failed for ${task.id}${reason}; it will retry on the next prompt.`)}this.delivery=void 0;let current=this.service;this.canDeliver(current)&¤t.pendingNotifications().some(task2=>!this.failures.has(task2.id))&&this.schedule()}}messageStarted(message){let delivery=this.delivery;delivery?.message===message&&delivery.phase==="pending"&&(delivery.phase="started")}agentEnded(){let delivery=this.delivery;delivery?.phase==="started"&&delivery.queued?.reject(new Error("the completion message was not persisted"))}queueCleared(){this.delivery?.queued?.reject(new Error("the completion message was dequeued before delivery"))}messagePersisted(message){let delivery=this.delivery;delivery?.message===message&&delivery.phase!=="persisted"&&(delivery.phase="persisted",delivery.service.markDelivered(delivery.id),delivery.queued?.resolve()),message.role==="toolResult"&&this.acknowledgeWaitResult(message.details)}acknowledgeWaitResult(details){if(!details||typeof details!="object"||!("backgroundTaskId"in details))return;let id=details.backgroundTaskId;typeof id=="string"&&this.service.list().some(task=>task.id===id&&task.mode==="background"&&isBackgroundTerminal(task.status))&&this.service.markDelivered(id)}dispose(){this.disposed=!0,this.service.close(),this.delivery?.queued?.reject(new Error("the session was disposed")),this.timer&&clearTimeout(this.timer),this.timer=void 0}};import{randomBytes as randomBytes2}from"node:crypto";import{createWriteStream as createWriteStream3}from"node:fs";import{tmpdir as tmpdir3}from"node:os";import{join as join23}from"node:path";async function executeBashWithOperations(command,cwd,operations,options){let outputChunks=[],outputBytes=0,maxOutputBytes=51200*2,tempFilePath,tempFileStream,totalBytes=0,ensureTempFile=()=>{if(tempFilePath)return;let id=randomBytes2(8).toString("hex");tempFilePath=join23(tmpdir3(),`pi-bash-${id}.log`),tempFileStream=createWriteStream3(tempFilePath);for(let chunk of outputChunks)tempFileStream.write(chunk)},decoder=new TextDecoder,onData=data=>{totalBytes+=data.length;let text2=sanitizeBinaryOutput(stripAnsi(decoder.decode(data,{stream:!0}))).replace(/\r/g,"");for(totalBytes>51200&&ensureTempFile(),tempFileStream&&tempFileStream.write(text2),outputChunks.push(text2),outputBytes+=text2.length;outputBytes>maxOutputBytes&&outputChunks.length>1;){let removed=outputChunks.shift();outputBytes-=removed.length}options?.onChunk&&options.onChunk(text2)};try{let result2=await operations.exec(command,cwd,{onData,signal:options?.signal}),fullOutput=outputChunks.join(""),truncationResult=truncateTail(fullOutput);truncationResult.truncated&&ensureTempFile(),tempFileStream&&tempFileStream.end();let cancelled=options?.signal?.aborted??!1;return{output:truncationResult.truncated?truncationResult.content:fullOutput,exitCode:cancelled?void 0:result2.exitCode??void 0,cancelled,truncated:truncationResult.truncated,fullOutputPath:tempFilePath}}catch(err2){if(options?.signal?.aborted){let fullOutput=outputChunks.join(""),truncationResult=truncateTail(fullOutput);return truncationResult.truncated&&ensureTempFile(),tempFileStream&&tempFileStream.end(),{output:truncationResult.truncated?truncationResult.content:fullOutput,exitCode:void 0,cancelled:!0,truncated:truncationResult.truncated,fullOutputPath:tempFilePath}}throw tempFileStream&&tempFileStream.end(),err2}}import*as os5 from"node:os";import{writeFile}from"node:fs/promises";import{crc32,deflateRawSync}from"node:zlib";function dosDateTime(date){return{time:date.getHours()<<11|date.getMinutes()<<5|date.getSeconds()>>1,day:Math.max(1980,date.getFullYear())-1980<<9|date.getMonth()+1<<5|date.getDate()}}function createZipArchive(entries){let files=[],directory=[],{time:time2,day}=dosDateTime(new Date),offset=0;for(let entry of entries){let name=Buffer.from(entry.name),data=(typeof entry.data=="string",Buffer.from(entry.data)),compressed=deflateRawSync(data),checksum=crc32(data),local=Buffer.alloc(30);local.writeUInt32LE(67324752,0),local.writeUInt16LE(20,4),local.writeUInt16LE(2048,6),local.writeUInt16LE(8,8),local.writeUInt16LE(time2,10),local.writeUInt16LE(day,12),local.writeUInt32LE(checksum,14),local.writeUInt32LE(compressed.length,18),local.writeUInt32LE(data.length,22),local.writeUInt16LE(name.length,26);let central=Buffer.alloc(46);central.writeUInt32LE(33639248,0),central.writeUInt16LE(20,4),central.writeUInt16LE(20,6),central.writeUInt16LE(2048,8),central.writeUInt16LE(8,10),central.writeUInt16LE(time2,12),central.writeUInt16LE(day,14),central.writeUInt32LE(checksum,16),central.writeUInt32LE(compressed.length,20),central.writeUInt32LE(data.length,24),central.writeUInt16LE(name.length,28),central.writeUInt32LE(offset,42),files.push(local,name,compressed),directory.push(central,name),offset+=local.length+name.length+compressed.length}let centralDirectory=Buffer.concat(directory),end=Buffer.alloc(22);return end.writeUInt32LE(101010256,0),end.writeUInt16LE(entries.length,8),end.writeUInt16LE(entries.length,10),end.writeUInt32LE(centralDirectory.length,12),end.writeUInt32LE(offset,16),Buffer.concat([...files,centralDirectory,end])}function writeZipArchive(filePath,entries){return writeFile(filePath,createZipArchive(entries))}var BUG_REPORT_CUSTOM_ENTRY_TYPE="pi.bug-report",BUG_REPORT_SCHEMA_VERSION=1,REDACTED="<redacted>",SENSITIVE_KEY=/(?:^|[-_])(api[-_]?key|secret|token|password|passwd|credential|authorization|cookie)(?:$|[-_])/i;function isSensitiveKey(key){return SENSITIVE_KEY.test(key.replace(/([a-z0-9])([A-Z])/g,"$1_$2"))}function redactUrl(value2){let nested=/^([a-z][a-z0-9+.-]*:)([a-z][a-z0-9+.-]*:\/\/.*)$/i.exec(value2);if(nested)return`${nested[1]}${redactUrl(nested[2])}`;try{let url=new URL(value2),changed=!1;(url.username||url.password)&&(url.username="",url.password="",changed=!0);for(let key of url.searchParams.keys())isSensitiveKey(key)&&(url.searchParams.set(key,REDACTED),changed=!0);return changed?url.toString():value2}catch{return value2}}function redactJsonValue(value2){if(value2!==void 0)return JSON.parse(JSON.stringify(value2,(key,child)=>child!=null&&isSensitiveKey(key)?REDACTED:typeof child=="string"?redactUrl(child):child))}function redactSettings(settings2){let{trackingId:_trackingId,...rest}=settings2;return redactJsonValue(rest)}function collectEnvironment(){let env2=name=>process.env[name]||null;return{version:VERSION,userAgent:getPiUserAgent(VERSION),runtime:process.versions.bun?`bun/${process.versions.bun}`:`node/${process.version}`,platform:process.platform,arch:process.arch,osRelease:os5.release(),osVersion:os5.version(),shell:process.env.SHELL?.split(/[\\/]/).pop()||null,terminal:{term:env2("TERM"),program:env2("TERM_PROGRAM"),programVersion:env2("TERM_PROGRAM_VERSION"),colorterm:env2("COLORTERM"),tmux:!!process.env.TMUX,ssh:!!(process.env.SSH_CONNECTION||process.env.SSH_CLIENT||process.env.SSH_TTY),ci:!!process.env.CI},piEnvironmentVariables:Object.keys(process.env).filter(name=>name.startsWith("PI_")).sort()}}function describeModel(model){return{provider:model.provider,id:model.id,name:model.name,api:model.api,baseUrl:redactUrl(model.baseUrl),reasoning:model.reasoning,input:model.input,contextWindow:model.contextWindow,maxTokens:model.maxTokens,samplingParams:model.samplingParams?redactJsonValue(model.samplingParams):null,compat:model.compat?redactJsonValue(model.compat):null,thinkingLevelMap:model.thinkingLevelMap??null,headerNames:Object.keys(model.headers??{}).sort()}}function describeProvider(modelRuntime,provider){let authTypes=[];return provider.auth.apiKey&&authTypes.push("api_key"),provider.auth.oauth&&authTypes.push("oauth"),{id:provider.id,name:provider.name,baseUrl:provider.baseUrl?redactUrl(provider.baseUrl):null,headerNames:Object.keys(provider.headers??{}).sort(),authTypes,authStatus:modelRuntime.getProviderAuthStatus(provider.id),usingOAuth:modelRuntime.isUsingOAuth(provider.id),registeredByExtension:modelRuntime.getRegisteredProviderIds().includes(provider.id)}}function describeExtension(extension){return{path:extension.path,source:redactUrl(extension.sourceInfo.source),scope:extension.sourceInfo.scope,origin:extension.sourceInfo.origin,hidden:extension.hidden===!0}}function collectBugReportMetadata(options){let hint2=options.hint?.trim()||null,provider=options.model?options.modelRuntime.getProvider(options.model.provider):void 0;return{schemaVersion:BUG_REPORT_SCHEMA_VERSION,id:options.id??uuidv7(),createdAt:new Date().toISOString(),hint:hint2,environment:collectEnvironment(),session:{id:options.sessionId,included:options.includeSession,summaryIncluded:options.includeSummary,messageCount:options.messageCount,...options.includeSession?{cwd:options.cwd}:{}},model:options.model?describeModel(options.model):null,provider:provider?describeProvider(options.modelRuntime,provider):null,thinkingLevel:options.thinkingLevel,extensions:options.extensions.map(describeExtension),extensionErrors:options.extensionErrors.map(({path:path14,error})=>({path:path14,error})),settings:{global:redactSettings(options.globalSettings),project:redactSettings(options.projectSettings)}}}function collectBugReportDiagnostics(sessionManager,crashes=[]){let entries=sessionManager.getEntries(),assistant=[],assistantMessageCount=0;for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="assistant")continue;assistantMessageCount++;let message=entry.message,diagnostics=message.diagnostics??[];diagnostics.length===0&&message.stopReason!=="error"&&message.stopReason!=="aborted"&&!message.errorMessage||assistant.push({entryId:entry.id,timestamp:entry.timestamp,provider:message.provider,model:message.model,api:message.api,stopReason:message.stopReason,...message.rawStopReason===void 0?{}:{rawStopReason:message.rawStopReason},...message.errorMessage===void 0?{}:{errorMessage:message.errorMessage},diagnostics})}return{schemaVersion:BUG_REPORT_SCHEMA_VERSION,sessionId:sessionManager.getSessionId(),entryCount:entries.length,assistantMessageCount,assistant,crashes:crashes.map(({notified:_notified,...record})=>record)}}function bugReportFiles(bundle){let files=[{name:"report.json",contentType:"application/json",data:`${JSON.stringify(bundle.metadata,null,2)}
|
|
1257
1257
|
`},{name:"diagnostics.json",contentType:"application/json",data:`${JSON.stringify(bundle.diagnostics,null,2)}
|
|
1258
1258
|
`}];return bundle.sessionJsonl!==void 0&&files.push({name:"session.jsonl",contentType:"application/x-ndjson",data:bundle.sessionJsonl}),bundle.summary!==void 0&&files.push({name:"summary.md",contentType:"text/markdown",data:bundle.summary.endsWith(`
|
|
1259
1259
|
`)?bundle.summary:`${bundle.summary}
|
|
@@ -1280,12 +1280,12 @@ ${hint2}
|
|
|
1280
1280
|
</user-report>`:void 0,BUG_SUMMARY_INSTRUCTIONS].filter(part=>part!==void 0).join(`
|
|
1281
1281
|
|
|
1282
1282
|
`),requestOptions={maxTokens:Math.min(4096,model.maxTokens>0?model.maxTokens:Number.POSITIVE_INFINITY),signal:options.signal,apiKey:options.apiKey,headers:options.headers,env:options.env,sessionId:options.sessionId,...model.reasoning&&options.thinkingLevel&&options.thinkingLevel!=="off"?{reasoning:options.thinkingLevel}:{}},response=await completeSummarization(model,normalizeContext({systemPrompt:BUG_SUMMARY_SYSTEM_PROMPT,messages:[{role:"user",content:[{type:"text",text:prompt}],timestamp:Date.now()}]}),requestOptions,options.streamFn,options.retry);if(response.stopReason==="aborted")throw new Error("Bug report summary was cancelled");let failure=getSummarizationFailure(response,"Bug report summary");if(failure)throw new Error(failure);if(response.content.some(block=>block.type==="toolCall"))throw new Error("Bug report summary attempted to call a tool");let text2=contentText(response.content).trim();if(!text2)throw new Error("Bug report summary was empty");return text2}import{existsSync as existsSync13,readFileSync as readFileSync9,writeFileSync as writeFileSync6}from"fs";import{basename as basename7,join as join24}from"path";function parseColor(color2){let hexMatch=color2.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);if(hexMatch)return{r:Number.parseInt(hexMatch[1],16),g:Number.parseInt(hexMatch[2],16),b:Number.parseInt(hexMatch[3],16)};let rgbMatch=color2.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);if(rgbMatch)return{r:Number.parseInt(rgbMatch[1],10),g:Number.parseInt(rgbMatch[2],10),b:Number.parseInt(rgbMatch[3],10)}}function getLuminance(r,g,b2){let toLinear=c=>{let s=c/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4};return .2126*toLinear(r)+.7152*toLinear(g)+.0722*toLinear(b2)}function adjustBrightness(color2,factor){let parsed=parseColor(color2);if(!parsed)return color2;let adjust=c=>Math.min(255,Math.max(0,Math.round(c*factor)));return`rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`}function deriveExportColors(baseColor){let parsed=parseColor(baseColor);return parsed?getLuminance(parsed.r,parsed.g,parsed.b)>.5?{pageBg:adjustBrightness(baseColor,.96),cardBg:baseColor,infoBg:`rgb(${Math.min(255,parsed.r+10)}, ${Math.min(255,parsed.g+5)}, ${Math.max(0,parsed.b-20)})`}:{pageBg:adjustBrightness(baseColor,.7),cardBg:adjustBrightness(baseColor,.85),infoBg:`rgb(${Math.min(255,parsed.r+20)}, ${Math.min(255,parsed.g+15)}, ${parsed.b})`}:{pageBg:"rgb(24, 24, 30)",cardBg:"rgb(30, 30, 36)",infoBg:"rgb(60, 55, 40)"}}function generateThemeVars(themeName){let colors=getResolvedThemeColors(themeName),lines=[];for(let[key,value2]of Object.entries(colors))lines.push(`--${key}: ${value2};`);let themeExport=getThemeExportColors(themeName),userMessageBg=colors.userMessageBg||"#343541",derivedColors=deriveExportColors(userMessageBg);return lines.push(`--exportPageBg: ${themeExport.pageBg??derivedColors.pageBg};`),lines.push(`--exportCardBg: ${themeExport.cardBg??derivedColors.cardBg};`),lines.push(`--exportInfoBg: ${themeExport.infoBg??derivedColors.infoBg};`),lines.join(`
|
|
1283
|
-
`)}function generateHtml(sessionData,themeName){let templateDir=getExportTemplateDir(),template=readFileSync9(join24(templateDir,"template.html"),"utf-8"),templateCss=readFileSync9(join24(templateDir,"template.css"),"utf-8"),templateJs=readFileSync9(join24(templateDir,"template.js"),"utf-8"),markedJs=readFileSync9(join24(templateDir,"vendor","marked.min.js"),"utf-8"),hljsJs=readFileSync9(join24(templateDir,"vendor","highlight.min.js"),"utf-8"),themeVars=generateThemeVars(themeName),colors=getResolvedThemeColors(themeName),themeExport=getThemeExportColors(themeName),derivedExportColors=deriveExportColors(colors.userMessageBg||"#343541"),bodyBg=themeExport.pageBg??derivedExportColors.pageBg,containerBg=themeExport.cardBg??derivedExportColors.cardBg,infoBg=themeExport.infoBg??derivedExportColors.infoBg,sessionDataBase64=Buffer.from(JSON.stringify(sessionData)).toString("base64"),css=templateCss.replace("{{THEME_VARS}}",themeVars).replace("{{BODY_BG}}",bodyBg).replace("{{CONTAINER_BG}}",containerBg).replace("{{INFO_BG}}",infoBg);return template.replace("{{CSS}}",css).replace("{{JS}}",templateJs).replace("{{SESSION_DATA}}",sessionDataBase64).replace("{{MARKED_JS}}",markedJs).replace("{{HIGHLIGHT_JS}}",hljsJs)}var TEMPLATE_RENDERED_TOOLS=new Set(["bash","read","write","edit","ls"]);function preRenderCustomTools(entries,toolRenderer){let renderedTools={};for(let entry of entries){if(entry.type!=="message")continue;let msg=entry.message;if(msg.role==="assistant"&&Array.isArray(msg.content)){for(let block of msg.content)if(block.type==="toolCall"&&!TEMPLATE_RENDERED_TOOLS.has(block.name)){let callHtml=toolRenderer.renderCall(block.id,block.name,block.arguments);callHtml&&(renderedTools[block.id]={callHtml})}}if(msg.role==="toolResult"&&msg.toolCallId){let toolName=msg.toolName||"",existing=renderedTools[msg.toolCallId];if(existing||!TEMPLATE_RENDERED_TOOLS.has(toolName)){let rendered=toolRenderer.renderResult(msg.toolCallId,toolName,msg.content,msg.details,msg.isError||!1);rendered&&(renderedTools[msg.toolCallId]={...existing,resultHtmlCollapsed:rendered.collapsed,resultHtmlExpanded:rendered.expanded})}}}return renderedTools}async function exportSessionToHtml(sm,state2,options){let opts=typeof options=="string"?{outputPath:options}:options||{},sessionFile=sm.getSessionFile();if(!sessionFile)throw new Error("Cannot export in-memory session to HTML");if(!existsSync13(sessionFile))throw new Error("Nothing to export yet - start a conversation first");let entries=sm.getEntries(),renderedTools;opts.toolRenderer&&(renderedTools=preRenderCustomTools(entries,opts.toolRenderer),Object.keys(renderedTools).length===0&&(renderedTools=void 0));let sessionData={header:sm.getHeader(),entries,leafId:sm.getLeafId(),systemPrompt:state2?.systemPrompt,tools:state2?.tools?.map(t=>({name:t.name,description:t.description,parameters:t.parameters})),renderedTools},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let sessionBasename=basename7(sessionFile,".jsonl");outputPath=`${APP_NAME}-session-${sessionBasename}.html`}return writeFileSync6(outputPath,html,"utf8"),outputPath}async function exportFromFile(inputPath,options){let opts=typeof options=="string"?{outputPath:options}:options||{},resolvedInputPath=resolvePath(inputPath);if(!existsSync13(resolvedInputPath))throw new Error(`File not found: ${resolvedInputPath}`);let sm=SessionManager.open(resolvedInputPath),sessionData={header:sm.getHeader(),entries:sm.getEntries(),leafId:sm.getLeafId(),systemPrompt:void 0,tools:void 0},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let inputBasename=basename7(resolvedInputPath,".jsonl");outputPath=`${APP_NAME}-session-${inputBasename}.html`}return writeFileSync6(outputPath,html,"utf8"),outputPath}var ANSI_COLORS=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];function color256ToHex(index3){if(index3<16)return ANSI_COLORS[index3];if(index3<232){let cubeIndex=index3-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex%36/6),b2=cubeIndex%6,toComponent=n=>n===0?0:55+n*40,toHex=n=>toComponent(n).toString(16).padStart(2,"0");return`#${toHex(r)}${toHex(g)}${toHex(b2)}`}let grayHex=(8+(index3-232)*10).toString(16).padStart(2,"0");return`#${grayHex}${grayHex}${grayHex}`}function escapeHtml(text2){return text2.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function createEmptyStyle(){return{fg:null,bg:null,bold:!1,dim:!1,italic:!1,underline:!1}}function styleToInlineCSS(style){let parts=[];return style.fg&&parts.push(`color:${style.fg}`),style.bg&&parts.push(`background-color:${style.bg}`),style.bold&&parts.push("font-weight:bold"),style.dim&&parts.push("opacity:0.6"),style.italic&&parts.push("font-style:italic"),style.underline&&parts.push("text-decoration:underline"),parts.join(";")}function hasStyle(style){return style.fg!==null||style.bg!==null||style.bold||style.dim||style.italic||style.underline}function applySgrCode(params,style){let i=0;for(;i<params.length;){let code=params[i];if(code===0)style.fg=null,style.bg=null,style.bold=!1,style.dim=!1,style.italic=!1,style.underline=!1;else if(code===1)style.bold=!0;else if(code===2)style.dim=!0;else if(code===3)style.italic=!0;else if(code===4)style.underline=!0;else if(code===22)style.bold=!1,style.dim=!1;else if(code===23)style.italic=!1;else if(code===24)style.underline=!1;else if(code>=30&&code<=37)style.fg=ANSI_COLORS[code-30];else if(code===38){if(params[i+1]===5&¶ms.length>i+2)style.fg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g=params[i+3],b2=params[i+4];style.fg=`rgb(${r},${g},${b2})`,i+=4}}else if(code===39)style.fg=null;else if(code>=40&&code<=47)style.bg=ANSI_COLORS[code-40];else if(code===48){if(params[i+1]===5&¶ms.length>i+2)style.bg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g=params[i+3],b2=params[i+4];style.bg=`rgb(${r},${g},${b2})`,i+=4}}else code===49?style.bg=null:code>=90&&code<=97?style.fg=ANSI_COLORS[code-90+8]:code>=100&&code<=107&&(style.bg=ANSI_COLORS[code-100+8]);i++}}var ANSI_REGEX=/\x1b\[([\d;]*)m/g;function ansiToHtml(text2){let style=createEmptyStyle(),result2="",lastIndex=0,inSpan=!1;ANSI_REGEX.lastIndex=0;let match2=ANSI_REGEX.exec(text2);for(;match2!==null;){let beforeText=text2.slice(lastIndex,match2.index);beforeText&&(result2+=escapeHtml(beforeText));let paramStr=match2[1],params=paramStr?paramStr.split(";").map(p=>parseInt(p,10)||0):[0];inSpan&&(result2+="</span>",inSpan=!1),applySgrCode(params,style),hasStyle(style)&&(result2+=`<span style="${styleToInlineCSS(style)}">`,inSpan=!0),lastIndex=match2.index+match2[0].length,match2=ANSI_REGEX.exec(text2)}let remainingText=text2.slice(lastIndex);return remainingText&&(result2+=escapeHtml(remainingText)),inSpan&&(result2+="</span>"),result2}function ansiLinesToHtml(lines){return lines.map(line=>`<div class="ansi-line">${ansiToHtml(line)||" "}</div>`).join("")}var ANSI_ESCAPE_REGEX=/\x1b\[[\d;]*m/g;function isBlankRenderedLine(line){return line.replace(ANSI_ESCAPE_REGEX,"").trim().length===0}function trimRenderedResultLines(lines){let start=0,end=lines.length;for(;start<end&&isBlankRenderedLine(lines[start]);)start++;for(;end>start&&isBlankRenderedLine(lines[end-1]);)end--;return lines.slice(start,end)}function createToolHtmlRenderer(deps){let{getToolDefinition,theme:theme2,cwd,width=100}=deps,renderedCallComponents=new Map,renderedResultComponents=new Map,renderedStates=new Map,renderedArgs=new Map,getState2=toolCallId=>{let state2=renderedStates.get(toolCallId);return state2||(state2={},renderedStates.set(toolCallId,state2)),state2},createRenderContext=(toolCallId,lastComponent,expanded,isPartial,isError)=>({args:renderedArgs.get(toolCallId),toolCallId,invalidate:()=>{},lastComponent,state:getState2(toolCallId),cwd,executionStarted:!0,argsComplete:!0,isPartial,expanded,showImages:!1,isError});return{renderCall(toolCallId,toolName,args){try{renderedArgs.set(toolCallId,args);let toolDef=getToolDefinition(toolName);if(!toolDef?.renderCall)return;let component=toolDef.renderCall(args,theme2,createRenderContext(toolCallId,renderedCallComponents.get(toolCallId),!1,!1,!1));renderedCallComponents.set(toolCallId,component);let lines=component.render(width);return ansiLinesToHtml(lines)}catch{return}},renderResult(toolCallId,toolName,result2,details,isError){try{let toolDef=getToolDefinition(toolName);if(!toolDef?.renderResult)return;let agentToolResult={content:result2,details,isError},collapsedComponent=toolDef.renderResult(agentToolResult,{expanded:!1,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!1,!1,isError));renderedResultComponents.set(toolCallId,collapsedComponent);let collapsed=ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width))),expandedComponent=toolDef.renderResult(agentToolResult,{expanded:!0,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!0,!1,isError));renderedResultComponents.set(toolCallId,expandedComponent);let expanded=ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));return{...collapsed&&collapsed!==expanded?{collapsed}:{},expanded}}catch{return}}}}function isTruthyEnvFlag(value2){return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}function isInstallTelemetryEnabled(settingsManager,telemetryEnv=process.env.PI_TELEMETRY){return telemetryEnv!==void 0?isTruthyEnvFlag(telemetryEnv):settingsManager.getEnableInstallTelemetry()}var OPENROUTER_HOST="openrouter.ai",NVIDIA_NIM_HOST="integrate.api.nvidia.com",CLOUDFLARE_API_HOST="api.cloudflare.com",CLOUDFLARE_AI_GATEWAY_HOST="gateway.ai.cloudflare.com",OPENCODE_HOST="opencode.ai";function matchesHost(baseUrl,expectedHost){try{return new URL(baseUrl).hostname===expectedHost}catch{return!1}}function isOpenRouterModel(model){return model.provider==="openrouter"||model.baseUrl.includes(OPENROUTER_HOST)}function isNvidiaNimModel(model){return model.provider==="nvidia"||matchesHost(model.baseUrl,NVIDIA_NIM_HOST)}function isCloudflareModel(model){return model.provider==="cloudflare-workers-ai"||model.provider==="cloudflare-ai-gateway"||matchesHost(model.baseUrl,CLOUDFLARE_API_HOST)||matchesHost(model.baseUrl,CLOUDFLARE_AI_GATEWAY_HOST)}function getDefaultAttributionHeaders(model,settingsManager){if(isInstallTelemetryEnabled(settingsManager)){if(isOpenRouterModel(model))return{"HTTP-Referer":"https://pi.dev","X-OpenRouter-Title":"pi","X-OpenRouter-Categories":"cli-agent"};if(isNvidiaNimModel(model))return{"X-BILLING-INVOKE-ORIGIN":"Pi"};if(isCloudflareModel(model))return{"User-Agent":"pi-coding-agent"}}}function getSessionHeaders(model,sessionId){if(sessionId&&!(model.provider!=="opencode"&&model.provider!=="opencode-go"&&!matchesHost(model.baseUrl,OPENCODE_HOST)))return{"x-opencode-session":sessionId,"x-opencode-client":"pi"}}function mergeProviderAttributionHeaders(model,settingsManager,sessionId,...headerSources){let merged={...getSessionHeaders(model,sessionId),...getDefaultAttributionHeaders(model,settingsManager)};for(let headers of headerSources)headers&&Object.assign(merged,headers);return Object.keys(merged).length>0?merged:void 0}function resolveModelStreamOptions(model,settings2,runner,options={}){let retry=settings2.getProviderRetrySettings(),idleTimeout=settings2.getHttpIdleTimeoutMs(),attribution=mergeProviderAttributionHeaders(model,settings2,options.sessionId);return{...options,timeoutMs:options.timeoutMs??retry.timeoutMs??(idleTimeout===0?2147483647:idleTimeout),websocketConnectTimeoutMs:options.websocketConnectTimeoutMs??settings2.getWebSocketConnectTimeoutMs(),maxRetries:options.maxRetries??retry.maxRetries,maxRetryDelayMs:options.maxRetryDelayMs??retry.maxRetryDelayMs,transformHeaders:async requestHeaders=>{let headers={...attribution,...requestHeaders};return runner?.hasHandlers("before_provider_headers")?runner.emitBeforeProviderHeaders(headers):headers}}}import{existsSync as existsSync14,readdirSync as readdirSync8,readFileSync as readFileSync10,statSync as statSync8}from"fs";import{basename as basename8,dirname as dirname15,join as join25,resolve as resolve7,sep as sep7}from"path";function parseCommandArgs2(argsString){let args=[],current="",inQuote=null;for(let i=0;i<argsString.length;i++){let char=argsString[i];inQuote?char===inQuote?inQuote=null:current+=char:char==='"'||char==="'"?inQuote=char:/\s/.test(char)?current&&(args.push(current),current=""):current+=char}return current&&args.push(current),args}function substituteArgs2(content,args){let allArgs=args.join(" ");return content.replace(/\$\{(\d+|ARGUMENTS|@):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g,(_match,defaultTarget,defaultValue,sliceStart,sliceLength,simple)=>{if(defaultTarget){let value2=defaultTarget==="@"||defaultTarget==="ARGUMENTS"?allArgs:args[parseInt(defaultTarget,10)-1];return value2||defaultValue}if(sliceStart){let start=parseInt(sliceStart,10)-1;if(start<0&&(start=0),sliceLength){let length=parseInt(sliceLength,10);return args.slice(start,start+length).join(" ")}return args.slice(start).join(" ")}if(simple==="ARGUMENTS"||simple==="@")return allArgs;let index3=parseInt(simple,10)-1;return args[index3]??""})}function loadTemplateFromFile2(filePath,sourceInfo){let diagnostics=[],rawContent;try{rawContent=readFileSync10(filePath,"utf-8")}catch(error){let message=error instanceof Error?error.message:"failed to read prompt template file";return diagnostics.push({type:"warning",message,path:filePath}),{template:null,diagnostics}}let frontmatter,body;try{({frontmatter,body}=parseFrontmatter(rawContent))}catch(error){let message=error instanceof Error?error.message:"failed to parse prompt template file";return diagnostics.push({type:"warning",message,path:filePath}),{template:null,diagnostics}}let name=basename8(filePath).replace(/\.md$/,""),description=typeof frontmatter.description=="string"?frontmatter.description:"";if(!description){let firstLine=body.split(`
|
|
1283
|
+
`)}function generateHtml(sessionData,themeName){let templateDir=getExportTemplateDir(),template=readFileSync9(join24(templateDir,"template.html"),"utf-8"),templateCss=readFileSync9(join24(templateDir,"template.css"),"utf-8"),templateJs=readFileSync9(join24(templateDir,"template.js"),"utf-8"),markedJs=readFileSync9(join24(templateDir,"vendor","marked.min.js"),"utf-8"),hljsJs=readFileSync9(join24(templateDir,"vendor","highlight.min.js"),"utf-8"),themeVars=generateThemeVars(themeName),colors=getResolvedThemeColors(themeName),themeExport=getThemeExportColors(themeName),derivedExportColors=deriveExportColors(colors.userMessageBg||"#343541"),bodyBg=themeExport.pageBg??derivedExportColors.pageBg,containerBg=themeExport.cardBg??derivedExportColors.cardBg,infoBg=themeExport.infoBg??derivedExportColors.infoBg,sessionDataBase64=Buffer.from(JSON.stringify(sessionData)).toString("base64"),css=templateCss.replace("{{THEME_VARS}}",themeVars).replace("{{BODY_BG}}",bodyBg).replace("{{CONTAINER_BG}}",containerBg).replace("{{INFO_BG}}",infoBg);return template.replace("{{CSS}}",css).replace("{{JS}}",templateJs).replace("{{SESSION_DATA}}",sessionDataBase64).replace("{{MARKED_JS}}",markedJs).replace("{{HIGHLIGHT_JS}}",hljsJs)}var TEMPLATE_RENDERED_TOOLS=new Set(["bash","read","write","edit","ls"]);function preRenderCustomTools(entries,toolRenderer){let renderedTools={};for(let entry of entries){if(entry.type!=="message")continue;let msg=entry.message;if(msg.role==="assistant"&&Array.isArray(msg.content)){for(let block of msg.content)if(block.type==="toolCall"&&!TEMPLATE_RENDERED_TOOLS.has(block.name)){let callHtml=toolRenderer.renderCall(block.id,block.name,block.arguments);callHtml&&(renderedTools[block.id]={callHtml})}}if(msg.role==="toolResult"&&msg.toolCallId){let toolName=msg.toolName||"",existing=renderedTools[msg.toolCallId];if(existing||!TEMPLATE_RENDERED_TOOLS.has(toolName)){let rendered=toolRenderer.renderResult(msg.toolCallId,toolName,msg.content,msg.details,msg.isError||!1);rendered&&(renderedTools[msg.toolCallId]={...existing,resultHtmlCollapsed:rendered.collapsed,resultHtmlExpanded:rendered.expanded})}}}return renderedTools}async function exportSessionToHtml(sm,state2,options){let opts=typeof options=="string"?{outputPath:options}:options||{},sessionFile=sm.getSessionFile();if(!sessionFile)throw new Error("Cannot export in-memory session to HTML");if(!existsSync13(sessionFile))throw new Error("Nothing to export yet - start a conversation first");let entries=sm.getEntries(),renderedTools;opts.toolRenderer&&(renderedTools=preRenderCustomTools(entries,opts.toolRenderer),Object.keys(renderedTools).length===0&&(renderedTools=void 0));let sessionData={header:sm.getHeader(),entries,leafId:sm.getLeafId(),systemPrompt:state2?.systemPrompt,tools:state2?.tools?.map(t=>({name:t.name,description:t.description,parameters:t.parameters})),renderedTools},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let sessionBasename=basename7(sessionFile,".jsonl");outputPath=`${APP_NAME}-session-${sessionBasename}.html`}return writeFileSync6(outputPath,html,"utf8"),outputPath}async function exportFromFile(inputPath,options){let opts=typeof options=="string"?{outputPath:options}:options||{},resolvedInputPath=resolvePath(inputPath);if(!existsSync13(resolvedInputPath))throw new Error(`File not found: ${resolvedInputPath}`);let sm=SessionManager.open(resolvedInputPath),sessionData={header:sm.getHeader(),entries:sm.getEntries(),leafId:sm.getLeafId(),systemPrompt:void 0,tools:void 0},html=generateHtml(sessionData,opts.themeName),outputPath=opts.outputPath?normalizePath(opts.outputPath):void 0;if(!outputPath){let inputBasename=basename7(resolvedInputPath,".jsonl");outputPath=`${APP_NAME}-session-${inputBasename}.html`}return writeFileSync6(outputPath,html,"utf8"),outputPath}var ANSI_COLORS=["#000000","#800000","#008000","#808000","#000080","#800080","#008080","#c0c0c0","#808080","#ff0000","#00ff00","#ffff00","#0000ff","#ff00ff","#00ffff","#ffffff"];function color256ToHex(index3){if(index3<16)return ANSI_COLORS[index3];if(index3<232){let cubeIndex=index3-16,r=Math.floor(cubeIndex/36),g=Math.floor(cubeIndex%36/6),b2=cubeIndex%6,toComponent=n=>n===0?0:55+n*40,toHex=n=>toComponent(n).toString(16).padStart(2,"0");return`#${toHex(r)}${toHex(g)}${toHex(b2)}`}let grayHex=(8+(index3-232)*10).toString(16).padStart(2,"0");return`#${grayHex}${grayHex}${grayHex}`}function escapeHtml(text2){return text2.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function createEmptyStyle(){return{fg:null,bg:null,bold:!1,dim:!1,italic:!1,underline:!1}}function styleToInlineCSS(style){let parts=[];return style.fg&&parts.push(`color:${style.fg}`),style.bg&&parts.push(`background-color:${style.bg}`),style.bold&&parts.push("font-weight:bold"),style.dim&&parts.push("opacity:0.6"),style.italic&&parts.push("font-style:italic"),style.underline&&parts.push("text-decoration:underline"),parts.join(";")}function hasStyle(style){return style.fg!==null||style.bg!==null||style.bold||style.dim||style.italic||style.underline}function applySgrCode(params,style){let i=0;for(;i<params.length;){let code=params[i];if(code===0)style.fg=null,style.bg=null,style.bold=!1,style.dim=!1,style.italic=!1,style.underline=!1;else if(code===1)style.bold=!0;else if(code===2)style.dim=!0;else if(code===3)style.italic=!0;else if(code===4)style.underline=!0;else if(code===22)style.bold=!1,style.dim=!1;else if(code===23)style.italic=!1;else if(code===24)style.underline=!1;else if(code>=30&&code<=37)style.fg=ANSI_COLORS[code-30];else if(code===38){if(params[i+1]===5&¶ms.length>i+2)style.fg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g=params[i+3],b2=params[i+4];style.fg=`rgb(${r},${g},${b2})`,i+=4}}else if(code===39)style.fg=null;else if(code>=40&&code<=47)style.bg=ANSI_COLORS[code-40];else if(code===48){if(params[i+1]===5&¶ms.length>i+2)style.bg=color256ToHex(params[i+2]),i+=2;else if(params[i+1]===2&¶ms.length>i+4){let r=params[i+2],g=params[i+3],b2=params[i+4];style.bg=`rgb(${r},${g},${b2})`,i+=4}}else code===49?style.bg=null:code>=90&&code<=97?style.fg=ANSI_COLORS[code-90+8]:code>=100&&code<=107&&(style.bg=ANSI_COLORS[code-100+8]);i++}}var ANSI_REGEX=/\x1b\[([\d;]*)m/g;function ansiToHtml(text2){let style=createEmptyStyle(),result2="",lastIndex=0,inSpan=!1;ANSI_REGEX.lastIndex=0;let match2=ANSI_REGEX.exec(text2);for(;match2!==null;){let beforeText=text2.slice(lastIndex,match2.index);beforeText&&(result2+=escapeHtml(beforeText));let paramStr=match2[1],params=paramStr?paramStr.split(";").map(p=>parseInt(p,10)||0):[0];inSpan&&(result2+="</span>",inSpan=!1),applySgrCode(params,style),hasStyle(style)&&(result2+=`<span style="${styleToInlineCSS(style)}">`,inSpan=!0),lastIndex=match2.index+match2[0].length,match2=ANSI_REGEX.exec(text2)}let remainingText=text2.slice(lastIndex);return remainingText&&(result2+=escapeHtml(remainingText)),inSpan&&(result2+="</span>"),result2}function ansiLinesToHtml(lines){return lines.map(line=>`<div class="ansi-line">${ansiToHtml(line)||" "}</div>`).join("")}var ANSI_ESCAPE_REGEX=/\x1b\[[\d;]*m/g;function isBlankRenderedLine(line){return line.replace(ANSI_ESCAPE_REGEX,"").trim().length===0}function trimRenderedResultLines(lines){let start=0,end=lines.length;for(;start<end&&isBlankRenderedLine(lines[start]);)start++;for(;end>start&&isBlankRenderedLine(lines[end-1]);)end--;return lines.slice(start,end)}function createToolHtmlRenderer(deps){let{getToolDefinition,theme:theme2,cwd,width=100}=deps,renderedCallComponents=new Map,renderedResultComponents=new Map,renderedStates=new Map,renderedArgs=new Map,getState2=toolCallId=>{let state2=renderedStates.get(toolCallId);return state2||(state2={},renderedStates.set(toolCallId,state2)),state2},createRenderContext=(toolCallId,lastComponent,expanded,isPartial,isError)=>({args:renderedArgs.get(toolCallId),toolCallId,invalidate:()=>{},lastComponent,state:getState2(toolCallId),cwd,executionStarted:!0,argsComplete:!0,isPartial,expanded,showImages:!1,isError});return{renderCall(toolCallId,toolName,args){try{renderedArgs.set(toolCallId,args);let toolDef=getToolDefinition(toolName);if(!toolDef?.renderCall)return;let component=toolDef.renderCall(args,theme2,createRenderContext(toolCallId,renderedCallComponents.get(toolCallId),!1,!1,!1));renderedCallComponents.set(toolCallId,component);let lines=component.render(width);return ansiLinesToHtml(lines)}catch{return}},renderResult(toolCallId,toolName,result2,details,isError){try{let toolDef=getToolDefinition(toolName);if(!toolDef?.renderResult)return;let agentToolResult={content:result2,details,isError},collapsedComponent=toolDef.renderResult(agentToolResult,{expanded:!1,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!1,!1,isError));renderedResultComponents.set(toolCallId,collapsedComponent);let collapsed=ansiLinesToHtml(trimRenderedResultLines(collapsedComponent.render(width))),expandedComponent=toolDef.renderResult(agentToolResult,{expanded:!0,isPartial:!1},theme2,createRenderContext(toolCallId,renderedResultComponents.get(toolCallId),!0,!1,isError));renderedResultComponents.set(toolCallId,expandedComponent);let expanded=ansiLinesToHtml(trimRenderedResultLines(expandedComponent.render(width)));return{...collapsed&&collapsed!==expanded?{collapsed}:{},expanded}}catch{return}}}}import{existsSync as existsSync14,readdirSync as readdirSync8,readFileSync as readFileSync10,statSync as statSync8}from"fs";import{basename as basename8,dirname as dirname15,join as join25,resolve as resolve7,sep as sep7}from"path";function parseCommandArgs2(argsString){let args=[],current="",inQuote=null;for(let i=0;i<argsString.length;i++){let char=argsString[i];inQuote?char===inQuote?inQuote=null:current+=char:char==='"'||char==="'"?inQuote=char:/\s/.test(char)?current&&(args.push(current),current=""):current+=char}return current&&args.push(current),args}function substituteArgs2(content,args){let allArgs=args.join(" ");return content.replace(/\$\{(\d+|ARGUMENTS|@):-([^}]*)\}|\$\{@:(\d+)(?::(\d+))?\}|\$(ARGUMENTS|@|\d+)/g,(_match,defaultTarget,defaultValue,sliceStart,sliceLength,simple)=>{if(defaultTarget){let value2=defaultTarget==="@"||defaultTarget==="ARGUMENTS"?allArgs:args[parseInt(defaultTarget,10)-1];return value2||defaultValue}if(sliceStart){let start=parseInt(sliceStart,10)-1;if(start<0&&(start=0),sliceLength){let length=parseInt(sliceLength,10);return args.slice(start,start+length).join(" ")}return args.slice(start).join(" ")}if(simple==="ARGUMENTS"||simple==="@")return allArgs;let index3=parseInt(simple,10)-1;return args[index3]??""})}function loadTemplateFromFile2(filePath,sourceInfo){let diagnostics=[],rawContent;try{rawContent=readFileSync10(filePath,"utf-8")}catch(error){let message=error instanceof Error?error.message:"failed to read prompt template file";return diagnostics.push({type:"warning",message,path:filePath}),{template:null,diagnostics}}let frontmatter,body;try{({frontmatter,body}=parseFrontmatter(rawContent))}catch(error){let message=error instanceof Error?error.message:"failed to parse prompt template file";return diagnostics.push({type:"warning",message,path:filePath}),{template:null,diagnostics}}let name=basename8(filePath).replace(/\.md$/,""),description=typeof frontmatter.description=="string"?frontmatter.description:"";if(!description){let firstLine=body.split(`
|
|
1284
1284
|
`).find(line=>line.trim());firstLine&&(description=firstLine.slice(0,60),firstLine.length>60&&(description+="..."))}let argumentHint=typeof frontmatter["argument-hint"]=="string"?frontmatter["argument-hint"]:void 0;return{template:{name,description,...argumentHint&&{argumentHint},content:body,sourceInfo,filePath},diagnostics}}function loadTemplatesFromDir2(dir,getSourceInfo){let templates=[],diagnostics=[];if(!existsSync14(dir))return{templates,diagnostics};try{let entries=readdirSync8(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=join25(dir,entry.name),isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync8(fullPath).isFile()}catch{continue}if(isFile&&entry.name.endsWith(".md")){let result2=loadTemplateFromFile2(fullPath,getSourceInfo(fullPath));result2.template&&templates.push(result2.template),diagnostics.push(...result2.diagnostics)}}}catch{return{templates,diagnostics}}return{templates,diagnostics}}function loadPromptTemplates2(options){let resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(options.agentDir),promptPaths=options.promptPaths,includeDefaults=options.includeDefaults,templates=[],diagnostics=[],addResult=result2=>{templates.push(...result2.templates),diagnostics.push(...result2.diagnostics)},globalPromptsDir=join25(resolvedAgentDir,"prompts"),projectPromptsDir=resolve7(resolvedCwd,CONFIG_DIR_NAME,"prompts"),isUnderPath=(target,root)=>{let normalizedRoot=resolve7(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep7)?normalizedRoot:`${normalizedRoot}${sep7}`;return target.startsWith(prefix)},getSourceInfo=resolvedPath=>isUnderPath(resolvedPath,globalPromptsDir)?createSyntheticSourceInfo(resolvedPath,{source:"local",scope:"user",baseDir:globalPromptsDir}):isUnderPath(resolvedPath,projectPromptsDir)?createSyntheticSourceInfo(resolvedPath,{source:"local",scope:"project",baseDir:projectPromptsDir}):createSyntheticSourceInfo(resolvedPath,{source:"local",baseDir:statSync8(resolvedPath).isDirectory()?resolvedPath:dirname15(resolvedPath)});includeDefaults&&(addResult(loadTemplatesFromDir2(globalPromptsDir,getSourceInfo)),addResult(loadTemplatesFromDir2(projectPromptsDir,getSourceInfo)));for(let rawPath of promptPaths){let resolvedPath=resolvePath(rawPath,resolvedCwd,{trim:!0});if(existsSync14(resolvedPath))try{let stats=statSync8(resolvedPath);if(stats.isDirectory())addResult(loadTemplatesFromDir2(resolvedPath,getSourceInfo));else if(stats.isFile()&&resolvedPath.endsWith(".md")){let result2=loadTemplateFromFile2(resolvedPath,getSourceInfo(resolvedPath));result2.template&&templates.push(result2.template),diagnostics.push(...result2.diagnostics)}}catch(error){let message=error instanceof Error?error.message:"failed to read prompt template path";diagnostics.push({type:"warning",message,path:resolvedPath})}}return{templates,diagnostics}}function expandPromptTemplate(text2,templates){if(!text2.startsWith("/"))return text2;let match2=text2.match(/^\/([^\s]+)(?:\s+([\s\S]*))?$/);if(!match2)return text2;let templateName=match2[1],argsString=match2[2]??"",template=templates.find(t=>t.name===templateName);if(template){let args=parseCommandArgs2(argsString);return substituteArgs2(template.content,args)}return text2}import{existsSync as existsSync15,mkdirSync as mkdirSync8,writeFileSync as writeFileSync7}from"node:fs";import{dirname as dirname16}from"node:path";function serializeSessionBranch(sessionManager,createTrailingEntries){let timestamp=new Date().toISOString(),entries=[{type:"session",version:CURRENT_SESSION_VERSION,id:sessionManager.getSessionId(),timestamp,cwd:sessionManager.getCwd()}],parentId=null;for(let entry of sessionManager.getBranch())entries.push({...entry,parentId}),parentId=entry.id;return entries.push(...createTrailingEntries?.(parentId,timestamp)??[]),`${entries.map(entry=>JSON.stringify(entry)).join(`
|
|
1285
1285
|
`)}
|
|
1286
|
-
`}function exportSessionToJsonl(sessionManager,outputPath,createTrailingEntries){let filePath=resolvePath(outputPath??`session-${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`,process.cwd()),dir=dirname16(filePath);return existsSync15(dir)||mkdirSync8(dir,{recursive:!0}),writeFileSync7(filePath,serializeSessionBranch(sessionManager,createTrailingEntries)),filePath}function parseSkillBlock(text2){let match2=text2.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);return match2?{name:match2[1],location:match2[2],content:match2[3],userMessage:match2[4]?.trim()||void 0}:null}function withoutDeletedHeaders(headers){return headers?Object.fromEntries(Object.entries(headers).filter(entry=>entry[1]!==null)):void 0}function estimateMessagesTokens(messages){let tokens2=0;for(let message of messages)tokens2+=estimateTokens3(message);return tokens2}var AgentSession=class{constructor(config){this._eventListeners=[],this._isAgentRunActive=!1,this._agentRunAbortRequested=!1,this._steeringMessages=[],this._followUpMessages=[],this._pendingNextTurnMessages=[],this._pendingCustomMessages=[],this._queuedBackgroundCompletions=new Map,this._compactionAbortController=void 0,this._autoCompactionAbortController=void 0,this._overflowRecoveryAttempted=!1,this._branchSummaryAbortController=void 0,this._retryAbortController=void 0,this._retryAttempt=0,this._bashAbortControllers=new Set,this._pendingBashMessages=[],this._turnIndex=0,this._entryIdsByMessage=new WeakMap,this._boundaryDispatchedMessages=new WeakSet,this._lastAssistantToolResults=[],this._lastActivityOutcome="completed",this._isBeforeSettle=!1,this._abortDuringBeforeSettle=!1,this._isEmittingAgentSettled=!1,this._deferredSettledActions=[],this._baseToolDefinitions=new Map,this._extensionMode="print",this._toolRegistry=new Map,this._toolDefinitions=new Map,this._toolPromptSnippets=new Map,this._toolPromptGuidelines=new Map,this._handleAgentEvent=async event=>{let acknowledgeBackground=event.type==="message_end"?this._backgroundHost.messageAcknowledgement(event.message):void 0,queuedBackgroundCompletion=event.type==="message_start"||event.type==="message_end"?this._queuedBackgroundCompletions.get(event.message):void 0;if(event.type==="message_start"&&queuedBackgroundCompletion&&(queuedBackgroundCompletion.drained=!0),event.type==="message_start"&&event.message.role==="user"){this._overflowRecoveryAttempted=!1;let messageText=contentText(event.message.content,"");if(messageText){let steeringIndex=this._steeringMessages.indexOf(messageText);if(steeringIndex!==-1)this._steeringMessages.splice(steeringIndex,1),this._emitQueueUpdate();else{let followUpIndex=this._followUpMessages.indexOf(messageText);followUpIndex!==-1&&(this._followUpMessages.splice(followUpIndex,1),this._emitQueueUpdate())}}}if(await this._emitExtensionEvent(event),this._emit(event.type==="agent_end"?{...event,willRetry:this._willRetryAfterAgentEnd(event)}:event),event.type==="message_end"&&(this._persistMessage(event.message)&&(acknowledgeBackground?.(),queuedBackgroundCompletion?.resolve()),event.message.role==="assistant")){let assistantMsg=event.message;this._lastAssistantMessage=assistantMsg,assistantMsg.stopReason!=="error"&&assistantMsg.stopReason!=="length"&&(this._overflowRecoveryAttempted=!1),assistantMsg.stopReason!=="error"&&this._retryAttempt>0&&(this._emit({type:"auto_retry_end",success:!0,attempt:this._retryAttempt}),this._retryAttempt=0)}event.type==="turn_end"&&(this._lastAssistantToolResults=event.toolResults,this._flushPendingCustomMessages()),event.type==="agent_end"&&this._failDrainedBackgroundCompletions()},this.agent=config.agent,this.sessionManager=config.sessionManager,this.settingsManager=config.settingsManager,this._backgroundHost=new BackgroundSession({manager:this.sessionManager,role:config.executionRole??"main",canDeliver:()=>this.model===void 0||this.isCompacting?!1:this.isStreaming||this.pendingMessageCount===0&&!this.agent.hasQueuedMessages(),deliver:message=>this._deliverBackgroundCompletion(message),onEntry:entry=>this._emit({type:"entry_appended",entry}),onError:(event,error)=>this._extensionRunner?.emitError({extensionPath:"<background>",event,error})}),this._scopedModels=config.scopedModels??[],this._resourceLoader=config.resourceLoader,this._customTools=config.customTools??[],this._cwd=config.cwd,this._modelRuntime=config.modelRuntime,this._captureModelContext=config.captureModelContext,this._cacheWarmer=config.cacheWarmer,this._cacheWarmer&&(this._cacheWarmer.onWarmed=entry=>this._emit({type:"entry_appended",entry})),this._extensionRunnerRef=config.extensionRunnerRef,this._initialActiveToolNames=config.initialActiveToolNames,this._allowedToolNames=config.allowedToolNames?new Set(config.allowedToolNames):void 0,this._excludedToolNames=config.excludedToolNames?new Set(config.excludedToolNames):void 0,this._baseToolsOverride=config.baseToolsOverride,this._sessionStartEvent=config.sessionStartEvent??{type:"session_start",reason:"startup"},this._unsubscribeAgent=this.agent.subscribe(this._handleAgentEvent),this._installAgentToolHooks(),this._installAgentNextTurnRefresh(),this._installAgentRequestProjection(),this._installAgentBoundaryHooks(),this._installAgentForcedPromptProjection(),this._buildRuntime({activeToolNames:this._initialActiveToolNames,includeAllExtensionTools:!0}),this._initialActiveToolNames===void 0&&this._restoreToolsFromTranscript()}get background(){return this._backgroundHost.service}get quarantinedBackgroundSettlements(){return this._backgroundHost.quarantinedSettlements}pauseBackgroundNotifications(){return this._backgroundHost.pause()}retryBackgroundNotifications(){this._backgroundHost.retry()}async _withBackgroundPaused(operation){let resumeBackground=this.pauseBackgroundNotifications();try{return await operation()}finally{resumeBackground()}}get modelRuntime(){return this._modelRuntime}async getContextSnapshot(){let model=this.model;if(!model)throw new Error("No model selected");let snapshot={capturedAt:Date.now(),sessionId:this.sessionManager.getSessionId(),leafId:this.sessionManager.getLeafId(),model:structuredClone(model),thinkingLevel:this.thinkingLevel,tools:this.agent.state.tools.map(({name,description,parameters,constrainedSampling})=>({name,description,parameters:structuredClone(parameters),...constrainedSampling===void 0?{}:{constrainedSampling:structuredClone(constrainedSampling)}})),streamOptions:resolveModelStreamOptions(model,this.settingsManager,this._extensionRunner,{sessionId:this.agent.sessionId??this.sessionManager.getSessionId(),transport:this.agent.transport,thinkingBudgets:structuredClone(this.agent.thinkingBudgets),maxRetryDelayMs:this.agent.maxRetryDelayMs,onPayload:this.agent.onPayload,onResponse:this.agent.onResponse})},currentSystemPrompt=this.systemPrompt,messages=structuredClone(this.sessionManager.buildSessionProjection().messages),convert=this.agent.convertToLlm,transform=this.agent.transformContext,prepared=this._captureModelContext?await this._captureModelContext(messages):await convert(transform?await transform(messages):messages),declared=getCurrentSystemMessage(prepared);return{...snapshot,systemPrompt:declared?getSystemMessageText(declared):currentSystemPrompt,messages:structuredClone(prepared)}}async _getRequiredRequestAuth(model,signal){let result2;try{result2=await this._modelRuntime.getAuth(model,{signal})}catch(error){let cause=error instanceof Error?error.cause:void 0;throw cause instanceof Error&&cause.message==="authHeader requires a resolved API key"?new Error(formatNoApiKeyFoundMessage(model.provider)):error}if(result2&&(result2.auth.apiKey||result2.auth.headers))return{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env};throw this._modelRuntime.isUsingOAuth(model.provider)?new Error(`Authentication failed for "${model.provider}". Credentials may have expired or network is unavailable. Run '/login ${model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(model.provider))}async _getSummarizationRequestAuth(model,signal){if(this.agent.streamFunction===streamSimple)return this._getRequiredRequestAuth(model,signal);try{let result2=await this._modelRuntime.getAuth(model,{signal});return result2?{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env}:{model}}catch(error){if(signal?.aborted)throw error;return{model}}}_installAgentToolHooks(){this.agent.beforeToolCall=async({toolCall,args})=>{let runner=this._extensionRunner;if(runner.hasHandlers("tool_call"))try{return await runner.emitToolCall({type:"tool_call",toolName:toolCall.name,toolCallId:toolCall.id,input:args})}catch(err2){throw err2 instanceof Error?err2:new Error(`Extension failed, blocking execution: ${String(err2)}`)}},this.agent.afterToolCall=async({toolCall,args,result:result2,isError})=>{let runner=this._extensionRunner,hookResult=runner.hasHandlers("tool_result")?await runner.emitToolResult({type:"tool_result",toolName:toolCall.name,toolCallId:toolCall.id,input:args,content:result2.content,details:result2.details,isError,usage:result2.usage}):void 0,content=hookResult?.content??result2.content??[],resizeOptions=this.model?.inputLimits?.images?.resize,normalizedContent=await normalizeToolResultImages(content,{autoResizeImages:this.settingsManager.getImageAutoResize(),...resizeOptions?{resizeOptions}:{}});if(!(!hookResult&&normalizedContent===content))return{content:normalizedContent,details:hookResult?.details,isError:hookResult?.isError??isError,usage:hookResult?.usage}}}async _compactBeforeNextAssistantResponse(context){let model=this.model,settings2=this.settingsManager.getCompactionSettings(model),projection=this.sessionManager.buildSessionProjection();return!model||model.contextWindow<=0||!shouldCompact2(estimateProjectedContextTokens(projection,this.sessionManager.getBranch()).tokens,model.contextWindow,settings2)?{...context,messages:projection.messages}:(await this._runAutoCompaction("threshold",!1),{...context,messages:this.sessionManager.buildSessionProjection().messages})}_installAgentRequestProjection(){let previousPrepareRequest=this.agent.prepareRequest;this.agent.prepareRequest=async(request,signal)=>{let canonicalContext={...request.context,messages:this.sessionManager.buildSessionProjection().messages,tools:this.agent.state.tools.slice()},previous=await previousPrepareRequest?.({...request,context:canonicalContext,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel},signal);return{...previous,context:previous?.context??canonicalContext,model:previous?.model??this.agent.state.model,thinkingLevel:previous?.thinkingLevel??this.agent.state.thinkingLevel}}}async _dispatchTurnEndBoundary(message,toolResults){this._lastActivityOutcome=message.stopReason==="aborted"?"aborted":message.stopReason==="error"?"error":"completed";let messageEntryId=this._findPersistedMessageEntryId(message);if(!this._extensionRunner.hasHandlers("turn_end"))return!1;if(!messageEntryId)return this._extensionRunner.emitError({extensionPath:"<boundary>",event:"turn_end",error:"turn_end could not resolve the persisted assistant entry ID"}),!1;let toolResultEntryIds=toolResults.flatMap(result2=>{let entryId=this._findPersistedMessageEntryId(result2);return entryId?[entryId]:[]}),boundary=await this._extensionRunner.emitBoundary({type:"turn_end",turnIndex:this._turnIndex,message,toolResults,messageEntryId,toolResultEntryIds,outcome:this._lastActivityOutcome},entries=>this._buildBoundaryContext(entries,"turn_end"));return this._commitBoundaryDrafts(boundary.entries),boundary.continue&&!this._buildBoundaryContext([],"turn_end").canContinue?(this._reportInvalidBoundaryContinuation("turn_end"),!1):boundary.continue}_installAgentBoundaryHooks(){let previousFinishTurn=this.agent.finishTurn;this.agent.finishTurn=async(turn,signal)=>{this._boundaryDispatchedMessages.add(turn.message);let extensionContinue=await this._dispatchTurnEndBoundary(turn.message,turn.toolResults),previousDecision=await previousFinishTurn?.(turn,signal);if(previousDecision?.action==="end")return previousDecision;if(extensionContinue||previousDecision?.action==="continue")return{action:"continue"}}}_installAgentNextTurnRefresh(){let previousPrepareNextTurnWithContext=this.agent.prepareNextTurnWithContext??(this.agent.prepareNextTurn?async(_turn,signal)=>await this.agent.prepareNextTurn?.(signal):void 0);this.agent.prepareNextTurnWithContext=async(turn,signal)=>{let context=await this._compactBeforeNextAssistantResponse({...turn.context,messages:this.sessionManager.buildSessionProjection().messages}),previousSnapshot=await previousPrepareNextTurnWithContext?.({...turn,context},signal),nextContext=previousSnapshot?.context??context,runOptions=this._runSystemPromptOptions??this._baseSystemPromptOptions,options=normalizeBuildSystemPromptOptions({...runOptions,selectedTools:this.getActiveToolNames(),toolSnippets:{...this._baseSystemPromptOptions.toolSnippets,...runOptions.toolSnippets},toolGuidelines:{...this._baseSystemPromptOptions.toolGuidelines,...runOptions.toolGuidelines}}),updateMessage=this._preparePromptAndToolLoadout(options,nextContext.messages);return this._runSystemPromptOptions=options,{...previousSnapshot,context:{...nextContext,tools:this.agent.state.tools.slice()},messages:updateMessage?[...previousSnapshot?.messages??[],updateMessage]:previousSnapshot?.messages,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel}}}_refreshFinalizedContext(){let projection=this.sessionManager.buildSessionProjection();for(let entry of projection.entries)for(let message of entry.messages)this._entryIdsByMessage.set(message,entry.sourceEntry.id);this.agent.state.messages=projection.messages}_applyBoundaryDrafts(manager,drafts){let appended=[];for(let draft of drafts){let entryId;switch(draft.type){case"custom":entryId=manager.appendCustomEntry(draft.customType,draft.data);break;case"custom_message":entryId=manager.appendCustomMessageEntry(draft.customType,draft.content,draft.display,draft.details);break;case"context_edit":entryId=manager.appendContextEdit(draft.targetId,draft.replacement);break;case"compaction":{let tokensBefore=estimateProjectedContextTokens(manager.buildSessionProjection(),manager.getBranch()).tokens;entryId=manager.appendCompaction(draft.summary,draft.firstKeptEntryId,tokensBefore,draft.details,!0,draft.usage);break}}let entry=manager.getEntry(entryId);entry&&appended.push(entry)}return appended}_createBoundaryPreviewManager(drafts){let header=this.sessionManager.getHeader();if(!header)throw new Error("Session header is missing");let manager=SessionManager.inMemory(this._cwd,void 0,[header,...this.sessionManager.getBranch()]);return this._applyBoundaryDrafts(manager,drafts),manager}_getPendingBoundaryMessages(){return[...this.agent.peekQueuedMessages(),...this._pendingCustomMessages]}_buildBoundaryContext(drafts,boundary){let projection=this._createBoundaryPreviewManager(drafts).buildSessionProjection(),pendingMessages=this._getPendingBoundaryMessages(),llmMessages=convertToLlm(projection.messages),finalRole=llmMessages[llmMessages.length-1]?.role,contextCanContinue=llmMessages.some(message=>message.role!=="system")&&finalRole!=="assistant",pendingCustomContext=this._pendingCustomMessages.length>0;return{contextEntries:projection.entries,contextMessages:projection.messages,llmMessages,pendingMessages,canContinue:contextCanContinue||pendingCustomContext||(boundary==="turn_end"?this.agent.hasQueuedMessages():finalRole==="assistant"&&this.agent.hasQueuedMessages())}}_commitBoundaryDrafts(drafts){let appended=this._applyBoundaryDrafts(this.sessionManager,drafts);this._refreshFinalizedContext();for(let entry of appended)this._emit({type:"entry_appended",entry})}_reportInvalidBoundaryContinuation(event){this._extensionRunner.emitError({extensionPath:"<boundary>",event,error:`${event} requested continuation without runnable model context`})}_emit(event){for(let l3 of this._eventListeners)l3(event)}_emitQueueUpdate(){this._emit({type:"queue_update",steering:[...this._steeringMessages],followUp:[...this._followUpMessages]})}async _emitSessionCompactFailed(event){this._extensionRunner.hasHandlers("session_compact_failed")&&await this._extensionRunner.emit({type:"session_compact_failed",...event})}_getIdleWaitPromise(){return this._idleWaitPromise||(this._idleWaitPromise=new Promise(resolve17=>{this._resolveIdleWait=resolve17})),this._idleWaitPromise}_resolveIdleWaitIfIdle(){if(!this.isIdle||!this._resolveIdleWait)return;let resolve17=this._resolveIdleWait;this._idleWaitPromise=void 0,this._resolveIdleWait=void 0,resolve17()}async _emitAgentSettled(){return this._withBackgroundPaused(()=>this._emitAgentSettledBody())}async _emitAgentSettledBody(){this._cacheWarmer?.onAgentSettled(),this._isAgentRunActive=!1,this._isEmittingAgentSettled=!0;try{await this._extensionRunner.emit({type:"agent_settled"}),this._emit({type:"agent_settled"})}finally{this._isEmittingAgentSettled=!1}let deferred=this._deferredSettledActions.splice(0);if(deferred.length>0){try{for(let action of deferred)await action()}finally{this._resolveIdleWaitIfIdle()}return}this._resolveIdleWaitIfIdle()}_persistMessage(message){let entryId;if(message.role==="custom"){entryId=this.sessionManager.appendCustomMessageEntry(message.customType,message.content,message.display,message.details);let pendingIndex=this._pendingNextTurnMessages.indexOf(message);pendingIndex!==-1&&this._pendingNextTurnMessages.splice(pendingIndex,1)}else if(message.role==="system"||message.role==="user"||message.role==="assistant"||message.role==="toolResult")entryId=this.sessionManager.appendMessage(message);else return;return this._entryIdsByMessage.set(message,entryId),message.role==="toolResult"&&this._backgroundHost.acknowledgeWaitResult(message.details),entryId}_willRetryAfterAgentEnd(event){if(this._agentRunAbortRequested)return!1;let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled||this._retryAttempt>=settings2.maxRetries)return!1;for(let i=event.messages.length-1;i>=0;i--){let message=event.messages[i];if(message.role==="assistant")return this._isRetryableError(message)}return!1}_findPersistedMessageEntryId(message){let mapped=this._entryIdsByMessage.get(message);if(mapped)return mapped;for(let entry of[...this.sessionManager.getBranch()].reverse())if(entry.type==="message"&&entry.message===message)return entry.id;let messageIndex=this.agent.state.messages.indexOf(message);if(messageIndex<0)return;let projection=this.sessionManager.buildSessionProjection(),projectedIndex=0;for(let entry of projection.entries)for(let i=0;i<entry.messages.length;i++){if(projectedIndex===messageIndex)return this._entryIdsByMessage.set(message,entry.sourceEntry.id),entry.sourceEntry.id;projectedIndex++}}_omitRecoveryAttempt(message,toolResults=[]){let targets=[message,...toolResults],targetIds=targets.map(target=>this._findPersistedMessageEntryId(target));if(targets.some((target,index3)=>targetIds[index3]===void 0&&this.agent.state.messages.includes(target)))throw new Error("Cannot persist recovery omission because a projected message has no source entry");for(let targetId of targetIds){if(!targetId)continue;let editId=this.sessionManager.appendContextEdit(targetId,null),entry=this.sessionManager.getEntry(editId);entry&&this._emit({type:"entry_appended",entry})}this._refreshFinalizedContext()}_findLastAssistantMessage(){let messages=this.agent.state.messages;for(let i=messages.length-1;i>=0;i--){let msg=messages[i];if(msg.role==="assistant")return msg}}_replaceMessageInPlace(target,replacement){if(target===replacement)return;let targetRecord=target;for(let key of Object.keys(targetRecord))delete targetRecord[key];Object.assign(targetRecord,replacement)}async _emitExtensionEvent(event){if(event.type==="agent_start")this._turnIndex=0,await this._extensionRunner.emit({type:"agent_start"});else if(event.type==="agent_end")await this._extensionRunner.emit({type:"agent_end",messages:event.messages});else if(event.type==="turn_start"){let extensionEvent={type:"turn_start",turnIndex:this._turnIndex,timestamp:Date.now()};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="turn_end")event.message.role==="assistant"&&!this._boundaryDispatchedMessages.delete(event.message)&&await this._dispatchTurnEndBoundary(event.message,event.toolResults),this._turnIndex++;else if(event.type==="message_start"){let extensionEvent={type:"message_start",message:event.message};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_update"){let extensionEvent={type:"message_update",message:event.message,assistantMessageEvent:event.assistantMessageEvent};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_end"){let extensionEvent={type:"message_end",message:event.message},replacement=await this._extensionRunner.emitMessageEnd(extensionEvent);if(replacement){let normalized=(replacement.role==="user"||replacement.role==="assistant"||replacement.role==="toolResult"||replacement.role==="custom")&&replacement.content==null?{...replacement,content:[]}:replacement;this._replaceMessageInPlace(event.message,normalized)}}else if(event.type==="tool_execution_start"){let extensionEvent={type:"tool_execution_start",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_update"){let extensionEvent={type:"tool_execution_update",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args,partialResult:event.partialResult};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_end"){let extensionEvent={type:"tool_execution_end",toolCallId:event.toolCallId,toolName:event.toolName,result:event.result,isError:event.isError};await this._extensionRunner.emit(extensionEvent)}}subscribe(listener){return this._eventListeners.push(listener),()=>{let index3=this._eventListeners.indexOf(listener);index3!==-1&&this._eventListeners.splice(index3,1)}}_disconnectFromAgent(){this._unsubscribeAgent&&(this._unsubscribeAgent(),this._unsubscribeAgent=void 0)}dispose(){this._backgroundHost.dispose();for(let queued of[...this._queuedBackgroundCompletions.values()])queued.reject(new Error("the session was disposed"));try{this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this.abortBash(),this.agent.abort()}catch{}this._extensionRunner.invalidate(STALE_EXTENSION_CONTEXT_MESSAGE),this._disconnectFromAgent(),this._eventListeners=[],this._cacheWarmer&&(this._cacheWarmer.onWarmed=void 0,this._cacheWarmer.cancel()),cleanupSessionResources(this.sessionId)}refreshContext(){this._refreshFinalizedContext()}get state(){return this.agent.state}get cacheWarmingStatus(){return this._cacheWarmer?.status}setCacheWarmingMode(mode){this.settingsManager.setCacheWarmingMode(mode),this._cacheWarmer?.onModeChanged()}get model(){return this.agent.state.model}get thinkingLevel(){return this.agent.state.thinkingLevel}get isStreaming(){return this._isAgentRunActive}get isIdle(){return!this._isAgentRunActive&&!this.isCompacting}get systemPrompt(){return buildSystemPrompt(this._runSystemPromptOptions??this._baseSystemPromptOptions)}get retryAttempt(){return this._retryAttempt}getActiveToolNames(){return this.agent.state.tools.map(t=>t.name)}getAllTools(){return Array.from(this._toolDefinitions.values()).map(({definition,sourceInfo})=>({name:definition.name,description:definition.description,parameters:definition.parameters,promptGuidelines:definition.promptGuidelines,sourceInfo}))}getToolDefinition(name){return this._toolDefinitions.get(name)?.definition}setActiveToolsByName(toolNames){let tools=[],validToolNames=[];for(let name of toolNames){let tool=this._toolRegistry.get(name);tool&&(tools.push(tool),validToolNames.push(name))}this.agent.state.tools=tools,this._rebuildSystemPrompt(validToolNames)}get isCompacting(){return this._autoCompactionAbortController!==void 0||this._compactionAbortController!==void 0||this._branchSummaryAbortController!==void 0}get messages(){return this.agent.state.messages}get steeringMode(){return this.agent.steeringMode}get followUpMode(){return this.agent.followUpMode}get sessionFile(){return this.sessionManager.getSessionFile()}get sessionId(){return this.sessionManager.getSessionId()}get sessionName(){return this.sessionManager.getSessionName()}get scopedModels(){return this._scopedModels}setScopedModels(scopedModels){this._scopedModels=scopedModels}get promptTemplates(){return this._resourceLoader.getPrompts().prompts}_normalizePromptSnippet(text2){if(!text2)return;let oneLine3=text2.replace(/[\r\n]+/g," ").replace(/\s+/g," ").trim();return oneLine3.length>0?oneLine3:void 0}_normalizePromptGuidelines(guidelines){if(!guidelines||guidelines.length===0)return[];let unique=new Set;for(let guideline of guidelines){let normalized=guideline.trim();normalized.length>0&&unique.add(normalized)}return Array.from(unique)}_rebuildSystemPrompt(toolNames){let validToolNames=toolNames.filter(name=>this._toolRegistry.has(name)),toolSnippets={};for(let name of this._toolRegistry.keys()){let snippet=this._toolPromptSnippets.get(name);snippet&&(toolSnippets[name]=snippet)}let loaderSystemPrompt=this._resourceLoader.getSystemPrompt(),loaderAppendSystemPrompt=this._resourceLoader.getAppendSystemPrompt(),appendSystemPrompt=loaderAppendSystemPrompt.length>0?loaderAppendSystemPrompt.join(`
|
|
1286
|
+
`}function exportSessionToJsonl(sessionManager,outputPath,createTrailingEntries){let filePath=resolvePath(outputPath??`session-${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`,process.cwd()),dir=dirname16(filePath);return existsSync15(dir)||mkdirSync8(dir,{recursive:!0}),writeFileSync7(filePath,serializeSessionBranch(sessionManager,createTrailingEntries)),filePath}function parseSkillBlock(text2){let match2=text2.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);return match2?{name:match2[1],location:match2[2],content:match2[3],userMessage:match2[4]?.trim()||void 0}:null}function withoutDeletedHeaders(headers){return headers?Object.fromEntries(Object.entries(headers).filter(entry=>entry[1]!==null)):void 0}function estimateMessagesTokens(messages){let tokens2=0;for(let message of messages)tokens2+=estimateTokens3(message);return tokens2}var AgentSession=class{constructor(config){this._eventListeners=[],this._isAgentRunActive=!1,this._agentRunAbortRequested=!1,this._steeringMessages=[],this._followUpMessages=[],this._pendingNextTurnMessages=[],this._pendingCustomMessages=[],this._compactionAbortController=void 0,this._autoCompactionAbortController=void 0,this._overflowRecoveryAttempted=!1,this._branchSummaryAbortController=void 0,this._retryAbortController=void 0,this._retryAttempt=0,this._bashAbortControllers=new Set,this._pendingBashMessages=[],this._turnIndex=0,this._entryIdsByMessage=new WeakMap,this._boundaryDispatchedMessages=new WeakSet,this._lastAssistantToolResults=[],this._lastActivityOutcome="completed",this._isBeforeSettle=!1,this._abortDuringBeforeSettle=!1,this._isEmittingAgentSettled=!1,this._deferredSettledActions=[],this._baseToolDefinitions=new Map,this._extensionMode="print",this._toolRegistry=new Map,this._toolDefinitions=new Map,this._toolPromptSnippets=new Map,this._toolPromptGuidelines=new Map,this._handleAgentEvent=async event=>{if(event.type==="message_start"&&this._backgroundHost.messageStarted(event.message),event.type==="message_start"&&event.message.role==="user"){this._overflowRecoveryAttempted=!1;let messageText=contentText(event.message.content,"");if(messageText){let steeringIndex=this._steeringMessages.indexOf(messageText);if(steeringIndex!==-1)this._steeringMessages.splice(steeringIndex,1),this._emitQueueUpdate();else{let followUpIndex=this._followUpMessages.indexOf(messageText);followUpIndex!==-1&&(this._followUpMessages.splice(followUpIndex,1),this._emitQueueUpdate())}}}if(await this._emitExtensionEvent(event),this._emit(event.type==="agent_end"?{...event,willRetry:this._willRetryAfterAgentEnd(event)}:event),event.type==="message_end"){let entryId;if(event.message.role==="custom"?entryId=this.sessionManager.appendCustomMessageEntry(event.message.customType,event.message.content,event.message.display,event.message.details):(event.message.role==="system"||event.message.role==="user"||event.message.role==="assistant"||event.message.role==="toolResult")&&(entryId=this.sessionManager.appendMessage(event.message)),entryId&&this._entryIdsByMessage.set(event.message,entryId),entryId&&this._messagePersisted(event.message),event.message.role==="assistant"){let assistantMsg=event.message;this._lastAssistantMessage=assistantMsg,assistantMsg.stopReason!=="error"&&assistantMsg.stopReason!=="length"&&(this._overflowRecoveryAttempted=!1),assistantMsg.stopReason!=="error"&&this._retryAttempt>0&&(this._emit({type:"auto_retry_end",success:!0,attempt:this._retryAttempt}),this._retryAttempt=0)}}event.type==="turn_end"&&(this._lastAssistantToolResults=event.toolResults,this._flushPendingCustomMessages()),event.type==="agent_end"&&this._backgroundHost.agentEnded()},this.agent=config.agent,this.sessionManager=config.sessionManager,this.settingsManager=config.settingsManager,this._backgroundHost=new BackgroundSession({manager:this.sessionManager,role:config.executionRole??"main",canDeliver:()=>this.model===void 0||this.isCompacting?!1:this.isStreaming||this.pendingMessageCount===0&&!this.agent.hasQueuedMessages(),deliver:(message,waitForPersistence)=>this.isStreaming?(this.agent.steer(message),waitForPersistence()):this._runAgentPrompt([message,...this._pendingNextTurnMessages]),onEntry:entry=>this._emit({type:"entry_appended",entry}),onError:(event,error)=>this._extensionRunner?.emitError({extensionPath:"<background>",event,error})}),this._scopedModels=config.scopedModels??[],this._resourceLoader=config.resourceLoader,this._customTools=config.customTools??[],this._cwd=config.cwd,this._modelRuntime=config.modelRuntime,this._contextSource=config.contextSource,this._cacheWarmer=config.cacheWarmer,this._cacheWarmer&&(this._cacheWarmer.onWarmed=entry=>this._emit({type:"entry_appended",entry})),this._extensionRunnerRef=config.extensionRunnerRef,this._initialActiveToolNames=config.initialActiveToolNames,this._allowedToolNames=config.allowedToolNames?new Set(config.allowedToolNames):void 0,this._excludedToolNames=config.excludedToolNames?new Set(config.excludedToolNames):void 0,this._baseToolsOverride=config.baseToolsOverride,this._sessionStartEvent=config.sessionStartEvent??{type:"session_start",reason:"startup"},this._unsubscribeAgent=this.agent.subscribe(this._handleAgentEvent),this._installAgentToolHooks(),this._installAgentNextTurnRefresh(),this._installAgentRequestProjection(),this._installAgentBoundaryHooks(),this._installAgentForcedPromptProjection(),this._buildRuntime({activeToolNames:this._initialActiveToolNames,includeAllExtensionTools:!0}),this._initialActiveToolNames===void 0&&this._restoreToolsFromTranscript()}get background(){return this._backgroundHost.service}get quarantinedBackgroundSettlements(){return this._backgroundHost.quarantinedSettlements}pauseBackgroundNotifications(){return this._backgroundHost.pause()}retryBackgroundNotifications(){this._backgroundHost.retry()}async _withBackgroundPaused(operation){let resumeBackground=this.pauseBackgroundNotifications();try{return await operation()}finally{resumeBackground()}}get modelRuntime(){return this._modelRuntime}async getContextSnapshot(){let model=this.model;if(!model)throw new Error("No model selected");let requestOptions={sessionId:this.agent.sessionId??this.sessionManager.getSessionId(),transport:this.agent.transport,thinkingBudgets:structuredClone(this.agent.thinkingBudgets),maxRetryDelayMs:this.agent.maxRetryDelayMs,onPayload:this.agent.onPayload,onResponse:this.agent.onResponse},snapshot={capturedAt:Date.now(),sessionId:this.sessionManager.getSessionId(),leafId:this.sessionManager.getLeafId(),model:structuredClone(model),thinkingLevel:this.thinkingLevel,tools:this.agent.state.tools.map(({name,description,parameters,constrainedSampling})=>({name,description,parameters:structuredClone(parameters),...constrainedSampling===void 0?{}:{constrainedSampling:structuredClone(constrainedSampling)}})),streamOptions:this._contextSource?.resolveStreamOptions(model,requestOptions)??requestOptions},currentSystemPrompt=this.systemPrompt,messages=structuredClone(this.sessionManager.buildSessionProjection().messages),convert=this.agent.convertToLlm,transform=this.agent.transformContext,prepared=this._contextSource?await this._contextSource.prepareMessages(messages):await convert(transform?await transform(messages):messages),declared=getCurrentSystemMessage(prepared);return{...snapshot,systemPrompt:declared?getSystemMessageText(declared):currentSystemPrompt,messages:structuredClone(prepared)}}async _getRequiredRequestAuth(model,signal){let result2;try{result2=await this._modelRuntime.getAuth(model,{signal})}catch(error){let cause=error instanceof Error?error.cause:void 0;throw cause instanceof Error&&cause.message==="authHeader requires a resolved API key"?new Error(formatNoApiKeyFoundMessage(model.provider)):error}if(result2&&(result2.auth.apiKey||result2.auth.headers))return{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env};throw this._modelRuntime.isUsingOAuth(model.provider)?new Error(`Authentication failed for "${model.provider}". Credentials may have expired or network is unavailable. Run '/login ${model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(model.provider))}async _getSummarizationRequestAuth(model,signal){if(this.agent.streamFunction===streamSimple)return this._getRequiredRequestAuth(model,signal);try{let result2=await this._modelRuntime.getAuth(model,{signal});return result2?{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env}:{model}}catch(error){if(signal?.aborted)throw error;return{model}}}_installAgentToolHooks(){this.agent.beforeToolCall=async({toolCall,args})=>{let runner=this._extensionRunner;if(runner.hasHandlers("tool_call"))try{return await runner.emitToolCall({type:"tool_call",toolName:toolCall.name,toolCallId:toolCall.id,input:args})}catch(err2){throw err2 instanceof Error?err2:new Error(`Extension failed, blocking execution: ${String(err2)}`)}},this.agent.afterToolCall=async({toolCall,args,result:result2,isError})=>{let runner=this._extensionRunner,hookResult=runner.hasHandlers("tool_result")?await runner.emitToolResult({type:"tool_result",toolName:toolCall.name,toolCallId:toolCall.id,input:args,content:result2.content,details:result2.details,isError,usage:result2.usage}):void 0,content=hookResult?.content??result2.content??[],resizeOptions=this.model?.inputLimits?.images?.resize,normalizedContent=await normalizeToolResultImages(content,{autoResizeImages:this.settingsManager.getImageAutoResize(),...resizeOptions?{resizeOptions}:{}});if(!(!hookResult&&normalizedContent===content))return{content:normalizedContent,details:hookResult?.details,isError:hookResult?.isError??isError,usage:hookResult?.usage}}}async _compactBeforeNextAssistantResponse(context){let model=this.model,settings2=this.settingsManager.getCompactionSettings(model),projection=this.sessionManager.buildSessionProjection();return!model||model.contextWindow<=0||!shouldCompact2(estimateProjectedContextTokens(projection,this.sessionManager.getBranch()).tokens,model.contextWindow,settings2)?{...context,messages:projection.messages}:(await this._runAutoCompaction("threshold",!1),{...context,messages:this.sessionManager.buildSessionProjection().messages})}_installAgentRequestProjection(){let previousPrepareRequest=this.agent.prepareRequest;this.agent.prepareRequest=async(request,signal)=>{let canonicalContext={...request.context,messages:this.sessionManager.buildSessionProjection().messages,tools:this.agent.state.tools.slice()},previous=await previousPrepareRequest?.({...request,context:canonicalContext,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel},signal);return{...previous,context:previous?.context??canonicalContext,model:previous?.model??this.agent.state.model,thinkingLevel:previous?.thinkingLevel??this.agent.state.thinkingLevel}}}async _dispatchTurnEndBoundary(message,toolResults){this._lastActivityOutcome=message.stopReason==="aborted"?"aborted":message.stopReason==="error"?"error":"completed";let messageEntryId=this._findPersistedMessageEntryId(message);if(!this._extensionRunner.hasHandlers("turn_end"))return!1;if(!messageEntryId)return this._extensionRunner.emitError({extensionPath:"<boundary>",event:"turn_end",error:"turn_end could not resolve the persisted assistant entry ID"}),!1;let toolResultEntryIds=toolResults.flatMap(result2=>{let entryId=this._findPersistedMessageEntryId(result2);return entryId?[entryId]:[]}),boundary=await this._extensionRunner.emitBoundary({type:"turn_end",turnIndex:this._turnIndex,message,toolResults,messageEntryId,toolResultEntryIds,outcome:this._lastActivityOutcome},entries=>this._buildBoundaryContext(entries,"turn_end"));return this._commitBoundaryDrafts(boundary.entries),boundary.continue&&!this._buildBoundaryContext([],"turn_end").canContinue?(this._reportInvalidBoundaryContinuation("turn_end"),!1):boundary.continue}_installAgentBoundaryHooks(){let previousFinishTurn=this.agent.finishTurn;this.agent.finishTurn=async(turn,signal)=>{this._boundaryDispatchedMessages.add(turn.message);let extensionContinue=await this._dispatchTurnEndBoundary(turn.message,turn.toolResults),previousDecision=await previousFinishTurn?.(turn,signal);if(previousDecision?.action==="end")return previousDecision;if(extensionContinue||previousDecision?.action==="continue")return{action:"continue"}}}_installAgentNextTurnRefresh(){let previousPrepareNextTurnWithContext=this.agent.prepareNextTurnWithContext??(this.agent.prepareNextTurn?async(_turn,signal)=>await this.agent.prepareNextTurn?.(signal):void 0);this.agent.prepareNextTurnWithContext=async(turn,signal)=>{let context=await this._compactBeforeNextAssistantResponse({...turn.context,messages:this.sessionManager.buildSessionProjection().messages}),previousSnapshot=await previousPrepareNextTurnWithContext?.({...turn,context},signal),nextContext=previousSnapshot?.context??context,runOptions=this._runSystemPromptOptions??this._baseSystemPromptOptions,options=normalizeBuildSystemPromptOptions({...runOptions,selectedTools:this.getActiveToolNames(),toolSnippets:{...this._baseSystemPromptOptions.toolSnippets,...runOptions.toolSnippets},toolGuidelines:{...this._baseSystemPromptOptions.toolGuidelines,...runOptions.toolGuidelines}}),updateMessage=this._preparePromptAndToolLoadout(options,nextContext.messages);return this._runSystemPromptOptions=options,{...previousSnapshot,context:{...nextContext,tools:this.agent.state.tools.slice()},messages:updateMessage?[...previousSnapshot?.messages??[],updateMessage]:previousSnapshot?.messages,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel}}}_refreshFinalizedContext(){let projection=this.sessionManager.buildSessionProjection();for(let entry of projection.entries)for(let message of entry.messages)this._entryIdsByMessage.set(message,entry.sourceEntry.id);this.agent.state.messages=projection.messages}_applyBoundaryDrafts(manager,drafts){let appended=[];for(let draft of drafts){let entryId;switch(draft.type){case"custom":entryId=manager.appendCustomEntry(draft.customType,draft.data);break;case"custom_message":entryId=manager.appendCustomMessageEntry(draft.customType,draft.content,draft.display,draft.details);break;case"context_edit":entryId=manager.appendContextEdit(draft.targetId,draft.replacement);break;case"compaction":{let tokensBefore=estimateProjectedContextTokens(manager.buildSessionProjection(),manager.getBranch()).tokens;entryId=manager.appendCompaction(draft.summary,draft.firstKeptEntryId,tokensBefore,draft.details,!0,draft.usage);break}}let entry=manager.getEntry(entryId);entry&&appended.push(entry)}return appended}_createBoundaryPreviewManager(drafts){let header=this.sessionManager.getHeader();if(!header)throw new Error("Session header is missing");let manager=SessionManager.inMemory(this._cwd,void 0,[header,...this.sessionManager.getBranch()]);return this._applyBoundaryDrafts(manager,drafts),manager}_getPendingBoundaryMessages(){return[...this.agent.peekQueuedMessages(),...this._pendingCustomMessages]}_buildBoundaryContext(drafts,boundary){let projection=this._createBoundaryPreviewManager(drafts).buildSessionProjection(),pendingMessages=this._getPendingBoundaryMessages(),llmMessages=convertToLlm(projection.messages),finalRole=llmMessages[llmMessages.length-1]?.role,contextCanContinue=llmMessages.some(message=>message.role!=="system")&&finalRole!=="assistant",pendingCustomContext=this._pendingCustomMessages.length>0;return{contextEntries:projection.entries,contextMessages:projection.messages,llmMessages,pendingMessages,canContinue:contextCanContinue||pendingCustomContext||(boundary==="turn_end"?this.agent.hasQueuedMessages():finalRole==="assistant"&&this.agent.hasQueuedMessages())}}_commitBoundaryDrafts(drafts){let appended=this._applyBoundaryDrafts(this.sessionManager,drafts);this._refreshFinalizedContext();for(let entry of appended)this._emit({type:"entry_appended",entry})}_reportInvalidBoundaryContinuation(event){this._extensionRunner.emitError({extensionPath:"<boundary>",event,error:`${event} requested continuation without runnable model context`})}_emit(event){for(let l3 of this._eventListeners)l3(event)}_emitQueueUpdate(){this._emit({type:"queue_update",steering:[...this._steeringMessages],followUp:[...this._followUpMessages]})}async _emitSessionCompactFailed(event){this._extensionRunner.hasHandlers("session_compact_failed")&&await this._extensionRunner.emit({type:"session_compact_failed",...event})}_getIdleWaitPromise(){return this._idleWaitPromise||(this._idleWaitPromise=new Promise(resolve17=>{this._resolveIdleWait=resolve17})),this._idleWaitPromise}_resolveIdleWaitIfIdle(){if(!this.isIdle||!this._resolveIdleWait)return;let resolve17=this._resolveIdleWait;this._idleWaitPromise=void 0,this._resolveIdleWait=void 0,resolve17()}async _emitAgentSettled(){return this._withBackgroundPaused(()=>this._emitAgentSettledBody())}async _emitAgentSettledBody(){this._cacheWarmer?.onAgentSettled(),this._isAgentRunActive=!1,this._isEmittingAgentSettled=!0;try{await this._extensionRunner.emit({type:"agent_settled"}),this._emit({type:"agent_settled"})}finally{this._isEmittingAgentSettled=!1}let deferred=this._deferredSettledActions.splice(0);if(deferred.length>0){try{for(let action of deferred)await action()}finally{this._resolveIdleWaitIfIdle()}return}this._resolveIdleWaitIfIdle()}_messagePersisted(message){if(message.role==="custom"){let pendingIndex=this._pendingNextTurnMessages.indexOf(message);pendingIndex!==-1&&this._pendingNextTurnMessages.splice(pendingIndex,1)}this._backgroundHost.messagePersisted(message)}_willRetryAfterAgentEnd(event){if(this._agentRunAbortRequested)return!1;let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled||this._retryAttempt>=settings2.maxRetries)return!1;for(let i=event.messages.length-1;i>=0;i--){let message=event.messages[i];if(message.role==="assistant")return this._isRetryableError(message)}return!1}_findPersistedMessageEntryId(message){let mapped=this._entryIdsByMessage.get(message);if(mapped)return mapped;for(let entry of[...this.sessionManager.getBranch()].reverse())if(entry.type==="message"&&entry.message===message)return entry.id;let messageIndex=this.agent.state.messages.indexOf(message);if(messageIndex<0)return;let projection=this.sessionManager.buildSessionProjection(),projectedIndex=0;for(let entry of projection.entries)for(let i=0;i<entry.messages.length;i++){if(projectedIndex===messageIndex)return this._entryIdsByMessage.set(message,entry.sourceEntry.id),entry.sourceEntry.id;projectedIndex++}}_omitRecoveryAttempt(message,toolResults=[]){let targets=[message,...toolResults],targetIds=targets.map(target=>this._findPersistedMessageEntryId(target));if(targets.some((target,index3)=>targetIds[index3]===void 0&&this.agent.state.messages.includes(target)))throw new Error("Cannot persist recovery omission because a projected message has no source entry");for(let targetId of targetIds){if(!targetId)continue;let editId=this.sessionManager.appendContextEdit(targetId,null),entry=this.sessionManager.getEntry(editId);entry&&this._emit({type:"entry_appended",entry})}this._refreshFinalizedContext()}_findLastAssistantMessage(){let messages=this.agent.state.messages;for(let i=messages.length-1;i>=0;i--){let msg=messages[i];if(msg.role==="assistant")return msg}}_replaceMessageInPlace(target,replacement){if(target===replacement)return;let targetRecord=target;for(let key of Object.keys(targetRecord))delete targetRecord[key];Object.assign(targetRecord,replacement)}async _emitExtensionEvent(event){if(event.type==="agent_start")this._turnIndex=0,await this._extensionRunner.emit({type:"agent_start"});else if(event.type==="agent_end")await this._extensionRunner.emit({type:"agent_end",messages:event.messages});else if(event.type==="turn_start"){let extensionEvent={type:"turn_start",turnIndex:this._turnIndex,timestamp:Date.now()};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="turn_end")event.message.role==="assistant"&&!this._boundaryDispatchedMessages.delete(event.message)&&await this._dispatchTurnEndBoundary(event.message,event.toolResults),this._turnIndex++;else if(event.type==="message_start"){let extensionEvent={type:"message_start",message:event.message};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_update"){let extensionEvent={type:"message_update",message:event.message,assistantMessageEvent:event.assistantMessageEvent};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_end"){let extensionEvent={type:"message_end",message:event.message},replacement=await this._extensionRunner.emitMessageEnd(extensionEvent);if(replacement){let normalized=(replacement.role==="user"||replacement.role==="assistant"||replacement.role==="toolResult"||replacement.role==="custom")&&replacement.content==null?{...replacement,content:[]}:replacement;this._replaceMessageInPlace(event.message,normalized)}}else if(event.type==="tool_execution_start"){let extensionEvent={type:"tool_execution_start",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_update"){let extensionEvent={type:"tool_execution_update",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args,partialResult:event.partialResult};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_end"){let extensionEvent={type:"tool_execution_end",toolCallId:event.toolCallId,toolName:event.toolName,result:event.result,isError:event.isError};await this._extensionRunner.emit(extensionEvent)}}subscribe(listener){return this._eventListeners.push(listener),()=>{let index3=this._eventListeners.indexOf(listener);index3!==-1&&this._eventListeners.splice(index3,1)}}_disconnectFromAgent(){this._unsubscribeAgent&&(this._unsubscribeAgent(),this._unsubscribeAgent=void 0)}dispose(){this._backgroundHost.dispose();try{this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this.abortBash(),this.agent.abort()}catch{}this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."),this._disconnectFromAgent(),this._eventListeners=[],this._cacheWarmer&&(this._cacheWarmer.onWarmed=void 0,this._cacheWarmer.cancel()),cleanupSessionResources(this.sessionId)}refreshContext(){this._refreshFinalizedContext()}get state(){return this.agent.state}get cacheWarmingStatus(){return this._cacheWarmer?.status}setCacheWarmingMode(mode){this.settingsManager.setCacheWarmingMode(mode),this._cacheWarmer?.onModeChanged()}get model(){return this.agent.state.model}get thinkingLevel(){return this.agent.state.thinkingLevel}get isStreaming(){return this._isAgentRunActive}get isIdle(){return!this._isAgentRunActive&&!this.isCompacting}get systemPrompt(){return buildSystemPrompt(this._runSystemPromptOptions??this._baseSystemPromptOptions)}get retryAttempt(){return this._retryAttempt}getActiveToolNames(){return this.agent.state.tools.map(t=>t.name)}getAllTools(){return Array.from(this._toolDefinitions.values()).map(({definition,sourceInfo})=>({name:definition.name,description:definition.description,parameters:definition.parameters,promptGuidelines:definition.promptGuidelines,sourceInfo}))}getToolDefinition(name){return this._toolDefinitions.get(name)?.definition}setActiveToolsByName(toolNames){let tools=[],validToolNames=[];for(let name of toolNames){let tool=this._toolRegistry.get(name);tool&&(tools.push(tool),validToolNames.push(name))}this.agent.state.tools=tools,this._rebuildSystemPrompt(validToolNames)}get isCompacting(){return this._autoCompactionAbortController!==void 0||this._compactionAbortController!==void 0||this._branchSummaryAbortController!==void 0}get messages(){return this.agent.state.messages}get steeringMode(){return this.agent.steeringMode}get followUpMode(){return this.agent.followUpMode}get sessionFile(){return this.sessionManager.getSessionFile()}get sessionId(){return this.sessionManager.getSessionId()}get sessionName(){return this.sessionManager.getSessionName()}get scopedModels(){return this._scopedModels}setScopedModels(scopedModels){this._scopedModels=scopedModels}get promptTemplates(){return this._resourceLoader.getPrompts().prompts}_normalizePromptSnippet(text2){if(!text2)return;let oneLine3=text2.replace(/[\r\n]+/g," ").replace(/\s+/g," ").trim();return oneLine3.length>0?oneLine3:void 0}_normalizePromptGuidelines(guidelines){if(!guidelines||guidelines.length===0)return[];let unique=new Set;for(let guideline of guidelines){let normalized=guideline.trim();normalized.length>0&&unique.add(normalized)}return Array.from(unique)}_rebuildSystemPrompt(toolNames){let validToolNames=toolNames.filter(name=>this._toolRegistry.has(name)),toolSnippets={};for(let name of this._toolRegistry.keys()){let snippet=this._toolPromptSnippets.get(name);snippet&&(toolSnippets[name]=snippet)}let loaderSystemPrompt=this._resourceLoader.getSystemPrompt(),loaderAppendSystemPrompt=this._resourceLoader.getAppendSystemPrompt(),appendSystemPrompt=loaderAppendSystemPrompt.length>0?loaderAppendSystemPrompt.join(`
|
|
1287
1287
|
|
|
1288
|
-
`):"",loadedSkills=this._resourceLoader.getSkills().skills,loadedContextFiles=this._resourceLoader.getAgentsFiles().agentsFiles;this._baseSystemPromptOptions=normalizeBuildSystemPromptOptions({cwd:this._cwd,skills:loadedSkills,contextFiles:loadedContextFiles,customPrompt:loaderSystemPrompt,appendSystemPrompt,selectedTools:validToolNames,toolSnippets,toolGuidelines:Object.fromEntries(this._toolPromptGuidelines)})}_preparePromptAndToolLoadout(options,messages=this.agent.state.messages){options.selectedTools=[...new Set(options.selectedTools)].filter(name=>this._toolRegistry.has(name)),this.agent.state.tools=options.selectedTools.flatMap(name=>{let tool=this._toolRegistry.get(name);return tool?[tool]:[]});let sections=diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections??{},buildSystemPromptSections(options));return sections?{role:"system",content:"",sections,timestamp:Date.now()}:void 0}_installAgentForcedPromptProjection(){let previousTransformContext=this.agent.transformContext;this.agent.transformContext=async(messages,signal)=>{let transformed=previousTransformContext?await previousTransformContext(messages,signal):messages,forced=this._runSystemPromptOptions?.forceSystemPrompt;if(forced===void 0)return transformed;let current=getCurrentSystemMessage(transformed);return[{role:"system",content:forced,...current?.toolsAdded?{toolsAdded:current.toolsAdded}:{},timestamp:current?.timestamp??Date.now()},...transformed.filter(message=>message.role!=="system")]}}_restoreToolsFromTranscript(){let current=getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);if(!current)return;let toolNames=(current.toolsAdded??[]).map(tool=>tool.name).filter(name=>this._toolRegistry.has(name));this.agent.state.tools=toolNames.flatMap(name=>{let registered2=this._toolRegistry.get(name);return registered2?[registered2]:[]}),this._rebuildSystemPrompt(toolNames)}async _runAgentPrompt(messages){this._agentRunAbortRequested=!1,this._isAgentRunActive=!0;try{for(await this.agent.prompt(messages);!this._agentRunAbortRequested;){if(await this._handlePostAgentRun()){if(this._agentRunAbortRequested)break;await this.agent.continue();continue}if(this._agentRunAbortRequested||!await this._runBeforeSettleBoundary()||this._agentRunAbortRequested)break;await this.agent.continue()}}finally{this._agentRunAbortRequested&&this._finishCancelledRetry(),this._runSystemPromptOptions=void 0,this._flushPendingBashMessages(),this._flushPendingCustomMessages(),await this._emitAgentSettled()}}
|
|
1288
|
+
`):"",loadedSkills=this._resourceLoader.getSkills().skills,loadedContextFiles=this._resourceLoader.getAgentsFiles().agentsFiles;this._baseSystemPromptOptions=normalizeBuildSystemPromptOptions({cwd:this._cwd,skills:loadedSkills,contextFiles:loadedContextFiles,customPrompt:loaderSystemPrompt,appendSystemPrompt,selectedTools:validToolNames,toolSnippets,toolGuidelines:Object.fromEntries(this._toolPromptGuidelines)})}_preparePromptAndToolLoadout(options,messages=this.agent.state.messages){options.selectedTools=[...new Set(options.selectedTools)].filter(name=>this._toolRegistry.has(name)),this.agent.state.tools=options.selectedTools.flatMap(name=>{let tool=this._toolRegistry.get(name);return tool?[tool]:[]});let sections=diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections??{},buildSystemPromptSections(options));return sections?{role:"system",content:"",sections,timestamp:Date.now()}:void 0}_installAgentForcedPromptProjection(){let previousTransformContext=this.agent.transformContext;this.agent.transformContext=async(messages,signal)=>{let transformed=previousTransformContext?await previousTransformContext(messages,signal):messages,forced=this._runSystemPromptOptions?.forceSystemPrompt;if(forced===void 0)return transformed;let current=getCurrentSystemMessage(transformed);return[{role:"system",content:forced,...current?.toolsAdded?{toolsAdded:current.toolsAdded}:{},timestamp:current?.timestamp??Date.now()},...transformed.filter(message=>message.role!=="system")]}}_restoreToolsFromTranscript(){let current=getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);if(!current)return;let toolNames=(current.toolsAdded??[]).map(tool=>tool.name).filter(name=>this._toolRegistry.has(name));this.agent.state.tools=toolNames.flatMap(name=>{let registered2=this._toolRegistry.get(name);return registered2?[registered2]:[]}),this._rebuildSystemPrompt(toolNames)}async _runAgentPrompt(messages){this._agentRunAbortRequested=!1,this._isAgentRunActive=!0;try{for(await this.agent.prompt(messages);!this._agentRunAbortRequested;){if(await this._handlePostAgentRun()){if(this._agentRunAbortRequested)break;await this.agent.continue();continue}if(this._agentRunAbortRequested||!await this._runBeforeSettleBoundary()||this._agentRunAbortRequested)break;await this.agent.continue()}}finally{this._agentRunAbortRequested&&this._finishCancelledRetry(),this._runSystemPromptOptions=void 0,this._flushPendingBashMessages(),this._flushPendingCustomMessages(),await this._emitAgentSettled()}}async _handlePostAgentRun(){let message=this._lastAssistantMessage,toolResults=this._lastAssistantToolResults;return this._lastAssistantMessage=void 0,this._lastAssistantToolResults=[],this._agentRunAbortRequested?(this._finishCancelledRetry(),!1):message?this._isRetryableError(message)&&await this._prepareRetry(message)?(this._agentRunAbortRequested&&this._finishCancelledRetry(),!this._agentRunAbortRequested):this._agentRunAbortRequested?(this._finishCancelledRetry(),!1):(message.stopReason==="error"&&this._retryAttempt>0&&(this._emit({type:"auto_retry_end",success:!1,attempt:this._retryAttempt,finalError:message.errorMessage}),this._retryAttempt=0),await this._checkCompaction(message,!0,toolResults)?!this._agentRunAbortRequested:!this._agentRunAbortRequested&&this.agent.hasQueuedMessages()):this.agent.hasQueuedMessages()}async _runBeforeSettleBoundary(){if(!this._extensionRunner.hasHandlers("agent_before_settle"))return this.agent.hasQueuedMessages();this._isBeforeSettle=!0,this._abortDuringBeforeSettle=!1;try{let result2=await this._extensionRunner.emitBoundary({type:"agent_before_settle",outcome:this._lastActivityOutcome},entries=>this._buildBoundaryContext(entries,"agent_before_settle"));this._commitBoundaryDrafts(result2.entries),this._flushPendingCustomMessages();let finalContext=this._buildBoundaryContext([],"agent_before_settle");if(this._abortDuringBeforeSettle)return!1;let shouldContinue=result2.continue||this.agent.hasQueuedMessages();return shouldContinue&&!finalContext.canContinue?(result2.continue&&this._reportInvalidBoundaryContinuation("agent_before_settle"),!1):shouldContinue}finally{this._isBeforeSettle=!1}}async _runInputHandlers(text2,images,source,streamingBehavior){if(!this._extensionRunner.hasHandlers("input"))return{text:text2,images};let inputResult=await this._extensionRunner.emitInput(text2,images,source,streamingBehavior);if(inputResult.action!=="handled")return inputResult.action==="transform"?{text:inputResult.text,images:inputResult.images??images}:{text:text2,images}}async _normalizePromptImages(images){if(!images)return{images:[],hints:[]};let normalizedImages=[],hints=[];for(let image of images){let processed=await processImage(Buffer.from(image.data,"base64"),image.mimeType,{autoResizeImages:this.settingsManager.getImageAutoResize(),resizeOptions:this.model?.inputLimits?.images?.resize});if(!processed.ok){hints.push(processed.message);continue}normalizedImages.push({type:"image",data:processed.data,mimeType:processed.mimeType}),hints.push(...processed.hints)}return{images:normalizedImages,hints}}async prompt(text2,options){if(this._isEmittingAgentSettled){this._deferredSettledActions.push(async()=>await this.prompt(text2,options));return}this.retryBackgroundNotifications();let expandPromptTemplates=options?.expandPromptTemplates??!0,preflightResult=options?.preflightResult,messages,resumeBackground;try{if(expandPromptTemplates&&text2.startsWith("/")&&await this._tryExecuteExtensionCommand(text2)){preflightResult?.(!0);return}if(resumeBackground=this.pauseBackgroundNotifications(),this._compactionAbortController!==void 0)throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");let processedInput=await this._runInputHandlers(text2,options?.images,options?.source??"interactive",this.isStreaming?options?.streamingBehavior:void 0);if(!processedInput){preflightResult?.(!0);return}let{text:currentText,images:currentImages}=processedInput,expandedText=currentText;if(expandPromptTemplates&&(expandedText=this._expandSkillCommand(expandedText),expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates])),this.isStreaming){if(!options?.streamingBehavior)throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");options.streamingBehavior==="followUp"?await this._queueFollowUp(expandedText,currentImages):await this._queueSteer(expandedText,currentImages),preflightResult?.(!0);return}if(this._flushPendingBashMessages(),this._flushPendingCustomMessages(),!this.model)throw new Error(formatNoModelSelectedMessage());if(!(this._modelRuntime.hasConfiguredAuth(this.model.provider)||await this._modelRuntime.checkAuth(this.model.provider)!==void 0))throw this._modelRuntime.isUsingOAuth(this.model.provider)?new Error(`Authentication failed for "${this.model.provider}". Credentials may have expired or network is unavailable. Run '/login ${this.model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(this.model.provider));let lastAssistant=this._findLastAssistantMessage();lastAssistant&&await this._checkCompaction(lastAssistant,!1);let selectedToolsBefore=this._baseSystemPromptOptions.selectedTools,result2=await this._extensionRunner.emitBeforeAgentStart(expandedText,currentImages,this._baseSystemPromptOptions);result2.systemPromptOptions.selectedTools.length!==selectedToolsBefore.length||result2.systemPromptOptions.selectedTools.some((name,index3)=>name!==selectedToolsBefore[index3])||(result2.systemPromptOptions.selectedTools=this.getActiveToolNames());let normalized=await this._normalizePromptImages(currentImages),userText=normalized.hints.length>0?`${expandedText}
|
|
1289
1289
|
|
|
1290
1290
|
${normalized.hints.join(`
|
|
1291
1291
|
`)}`:expandedText;messages=[];let userContent=[{type:"text",text:userText}];userContent.push(...normalized.images),messages.push({role:"user",content:userContent,timestamp:Date.now()});for(let msg of this._pendingNextTurnMessages)messages.push(msg);for(let msg of result2.messages)messages.push({role:"custom",customType:msg.customType,content:msg.content??[],display:msg.display,details:msg.details,timestamp:Date.now()});let updateMessage=this._preparePromptAndToolLoadout(result2.systemPromptOptions);this._runSystemPromptOptions=result2.systemPromptOptions,updateMessage&&messages.unshift(updateMessage)}catch(error){throw preflightResult?.(!1),error}finally{resumeBackground?.()}messages&&(preflightResult?.(!0),await this._runAgentPrompt(messages))}async _tryExecuteExtensionCommand(text2){let spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex),args=spaceIndex===-1?"":text2.slice(spaceIndex+1),command=this._extensionRunner.getCommand(commandName);if(!command)return!1;let ctx=this._extensionRunner.createCommandContext();try{return await command.handler(args,ctx),!0}catch(err2){return this._extensionRunner.emitError({extensionPath:`command:${commandName}`,event:"command",error:err2 instanceof Error?err2.message:String(err2)}),!0}}_expandSkillCommand(text2){if(!text2.startsWith("/skill:"))return text2;let spaceIndex=text2.indexOf(" "),skillName=spaceIndex===-1?text2.slice(7):text2.slice(7,spaceIndex),args=spaceIndex===-1?"":text2.slice(spaceIndex+1).trim(),skill=this.resourceLoader.getSkills().skills.find(s=>s.name===skillName);if(!skill)return text2;try{let content=readFileSync11(skill.filePath,"utf-8"),body=stripFrontmatter(content).trim(),skillBlock=`<skill name="${skill.name}" location="${skill.filePath}">
|
|
@@ -1294,15 +1294,15 @@ References are relative to ${skill.baseDir}.
|
|
|
1294
1294
|
${body}
|
|
1295
1295
|
</skill>`;return args?`${skillBlock}
|
|
1296
1296
|
|
|
1297
|
-
${args}`:skillBlock}catch(err2){return this._extensionRunner.emitError({extensionPath:skill.filePath,event:"skill_expansion",error:err2 instanceof Error?err2.message:String(err2)}),text2}}async _queueUserInput(text2,images,behavior,source){text2.startsWith("/")&&this._throwIfExtensionCommand(text2);let processedInput=await this._runInputHandlers(text2,images,source,this.isStreaming?behavior:void 0);if(!processedInput)return;let expandedText=this._expandSkillCommand(processedInput.text);expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates]),behavior==="steer"?await this._queueSteer(expandedText,processedInput.images):await this._queueFollowUp(expandedText,processedInput.images)}async steer(text2,images,options){await this._queueUserInput(text2,images,"steer",options?.source??"interactive")}async followUp(text2,images,options){await this._queueUserInput(text2,images,"followUp",options?.source??"interactive")}async _queueSteer(text2,images){this._steeringMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.steer({role:"user",content,timestamp:Date.now()})}async _queueFollowUp(text2,images){this._followUpMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.followUp({role:"user",content,timestamp:Date.now()})}_throwIfExtensionCommand(text2){let spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);if(this._extensionRunner.getCommand(commandName))throw new Error(`Extension command "/${commandName}" cannot be queued. Use prompt() or execute the command when not streaming.`)}async sendCustomMessage(message,options){let appMessage={role:"custom",customType:message.customType,content:message.content??[],display:message.display,details:message.details,timestamp:Date.now()};if(options?.deliverAs==="nextTurn")this._pendingNextTurnMessages.push(appMessage);else if(this.isStreaming&&options?.triggerTurn!==!1)options?.deliverAs==="followUp"?this.agent.followUp(appMessage):this.agent.steer(appMessage);else if(options?.triggerTurn){if(this._isEmittingAgentSettled){this._deferredSettledActions.push(async()=>await this._runAgentPrompt(appMessage));return}await this._runAgentPrompt(appMessage)}else this.isStreaming?this._pendingCustomMessages.push(appMessage):this._appendCustomMessage(appMessage)}_appendCustomMessage(appMessage){this.
|
|
1298
|
-
`),images.length===0&&(images=void 0)}await this.prompt(text2,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues();for(let queued of[...this._queuedBackgroundCompletions.values()])queued.reject(new Error("the completion message was dequeued before delivery"));return this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._isAgentRunActive&&(this._agentRunAbortRequested=!0),this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this._isBeforeSettle&&(this._abortDuringBeforeSettle=!0),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source})}async setModel(model,options={}){if(!await this._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model);this.agent.state.model=model,this.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model.provider,model.id),this._addPersistedDefaultToNonEmptyScope(model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;this._scopedModels=[...this._scopedModels,{model}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||this.settingsManager.setEnabledModels([...enabledModels,modelReference])}async cycleModel(direction="forward",options={}){return this._scopedModels.length>0?this._cycleScopedModel(direction,options):this._cycleAvailableModel(direction,options)}async _cycleScopedModel(direction,options){let availableIds=new Set(this._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=this._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=this.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return this.agent.state.model=next.model,this.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),this._addPersistedDefaultToNonEmptyScope(next.model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:this.thinkingLevel,isScoped:!0}}async _cycleAvailableModel(direction,options){let availableModels=this._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=this.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(nextModel);return this.agent.state.model=nextModel,this.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),this._addPersistedDefaultToNonEmptyScope(nextModel)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:this.thinkingLevel,isScoped:!1}}setThinkingLevel(level,options={}){let availableLevels=this.getAvailableThinkingLevels(),effectiveLevel=availableLevels.includes(level)?level:this._clampThinkingLevel(level,availableLevels),previousLevel=this.agent.state.thinkingLevel,isChanging=effectiveLevel!==previousLevel;this.agent.state.thinkingLevel=effectiveLevel,options.persist&&this.settingsManager.setDefaultThinkingLevel(level),isChanging&&(this.sessionManager.appendThinkingLevelChange(effectiveLevel),this._emit({type:"thinking_level_changed",level:effectiveLevel}),this._extensionRunner.emit({type:"thinking_level_select",level:effectiveLevel,previousLevel}))}cycleThinkingLevel(options={}){if(!this.supportsThinking())return;let levels=this.getAvailableThinkingLevels(),nextIndex=(levels.indexOf(this.thinkingLevel)+1)%levels.length,nextLevel=levels[nextIndex];return this.setThinkingLevel(nextLevel,options),nextLevel}getAvailableThinkingLevels(){return this.model?getSupportedThinkingLevels(this.model):[...THINKING_LEVEL_OPTIONS]}supportsThinking(){return!!this.model?.reasoning}_getThinkingLevelForModelSwitch(targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=this.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return this.settingsManager.getDefaultThinkingLevel()??this.thinkingLevel??DEFAULT_THINKING_LEVEL}_clampThinkingLevel(level,_availableLevels){return this.model?clampThinkingLevel(this.model,level):"off"}syncQueueModesFromSettings(){this.agent.steeringMode=this.settingsManager.getSteeringMode(),this.agent.followUpMode=this.settingsManager.getFollowUpMode()}setSteeringMode(mode){this.agent.steeringMode=mode,this.settingsManager.setSteeringMode(mode)}setFollowUpMode(mode){this.agent.followUpMode=mode,this.settingsManager.setFollowUpMode(mode)}async _runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,signal,env2,reason){return compact2(preparation,requestModel,apiKey,headers,customInstructions,signal,this.thinkingLevel,this.agent.streamFunction,env2,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._withBackgroundPaused(()=>this._compactBody(customInstructions))}async _compactBody(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings2=this.settingsManager.getCompactionSettings(model),{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model,this._compactionAbortController.signal),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction2(pathEntries,settings2);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result2=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result2?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result2?.compaction&&(extensionCompaction=result2.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result2=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,this._compactionAbortController.signal,env2,"manual");summary=result2.summary,firstKeptEntryId=result2.firstKeptEntryId,tokensBefore=result2.tokensBefore,usage=result2.usage,details=result2.details}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason:"manual",willRetry:!1});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage6=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage6,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0,toolResults=[]){let settings2=this.settingsManager.getCompactionSettings(this.model);if(!settings2.enabled||skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let contextWindow=this.model?.contextWindow??0,sameModel=this.model&&assistantMessage.provider===this.model.provider&&assistantMessage.model===this.model.id,compactionEntry=getLatestCompactionEntry(this.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let currentProjection=this.sessionManager.buildSessionProjection(),assistantEntryId=this._findPersistedMessageEntryId(assistantMessage),assistantIsProjected=assistantEntryId===void 0||currentProjection.entries.some(entry=>entry.sourceEntry.id===assistantEntryId&&entry.messages.some(message=>message.role==="assistant")),branch=this.sessionManager.getBranch(),assistantIndex=assistantEntryId?branch.findIndex(entry=>entry.id===assistantEntryId):-1,entriesAfterAssistant=assistantIndex>=0?branch.slice(assistantIndex+1):[],hasPostAssistantContextEdit=entriesAfterAssistant.some(entry=>entry.type==="context_edit"),latestAssistantEdit=entriesAfterAssistant.filter(entry=>entry.type==="context_edit"&&entry.targetId===assistantEntryId).at(-1),assistantRetainedForExplicitRecovery=assistantEntryId===void 0||!entriesAfterAssistant.some(entry=>entry.type==="compaction")&&latestAssistantEdit?.replacement!==null,assistantUsageMatchesProjection=assistantIsProjected&&!hasPostAssistantContextEdit,explicitOverflow=assistantMessage.stopReason==="error"&&isContextOverflow(assistantMessage),contextOverflow=sameModel&&(explicitOverflow&&assistantRetainedForExplicitRecovery||assistantUsageMatchesProjection&&isContextOverflow(assistantMessage,contextWindow)),recoverableLength=sameModel&&assistantIsProjected&&isRecoverableLength(assistantMessage,this.model?.maxTokens??0);if(contextOverflow||recoverableLength){let willRetry=assistantMessage.stopReason!=="stop";if(!willRetry)return await this._runAutoCompaction("overflow",!1);if(this._overflowRecoveryAttempted){let errorMessage6=contextOverflow?"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.":"Truncated response recovery failed after one compact-and-retry attempt.";return this._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage6,aborted:!1,willRetry:!1,fromExtension:!1}),!1}return this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage,toolResults),await this._runAutoCompaction("overflow",willRetry)}let contextTokens,projection=currentProjection,hasContextEdits=projection.entries.some(entry=>entry.sourceEntry.type==="context_edit"),directContextTokens=assistantMessage.usage?calculateContextTokens2(assistantMessage.usage):0;if(hasContextEdits)contextTokens=estimateProjectedContextTokens(projection,branch).tokens;else if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens3(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact2(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){return this._withBackgroundPaused(()=>this._runAutoCompactionBody(reason,willRetry))}async _runAutoCompactionBody(reason,willRetry){let model=this.model,settings2=this.settingsManager.getCompactionSettings(model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction2(pathEntries,settings2);if(!preparation)return!1;abortController=new AbortController,this._autoCompactionAbortController=abortController,started=!0,this._emit({type:"compaction_start",reason}),abortController.signal.throwIfAborted();let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model,abortController.signal);abortController.signal.throwIfAborted();let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let extensionResult=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions:void 0,reason,willRetry,signal:abortController.signal});if(extensionResult?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");extensionResult?.compaction&&(extensionCompaction=extensionResult.compaction,fromExtension=!0)}abortController.signal.throwIfAborted();let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let compactResult=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,void 0,abortController.signal,env2,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry});let result2={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result:result2,aborted:!1,willRetry}),willRetry?!0:this.agent.hasQueuedMessages()}catch(error){let message=error instanceof Error?error.message:"compaction failed",aborted=abortController?.signal.aborted===!0||cancelledByExtension;if(started){let errorMessage6=aborted?void 0:reason==="overflow"?`Context overflow recovery failed: ${message}`:`Auto-compaction failed: ${message}`;this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage6,aborted,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController===abortController&&(this._autoCompactionAbortController=void 0),this._resolveIdleWaitIfIdle()}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){return this._withBackgroundPaused(()=>this._bindExtensionsBody(bindings))}async _bindExtensionsBody(bindings){bindings.backgroundEnabled!==void 0&&this._backgroundHost.setEnabled(bindings.backgroundEnabled),bindings.uiContext!==void 0&&(this._extensionUIContext=bindings.uiContext),bindings.mode!==void 0&&(this._extensionMode=bindings.mode),bindings.commandContextActions!==void 0&&(this._extensionCommandContextActions=bindings.commandContextActions),bindings.abortHandler!==void 0&&(this._extensionAbortHandler=bindings.abortHandler),bindings.shutdownHandler!==void 0&&(this._extensionShutdownHandler=bindings.shutdownHandler),bindings.onError!==void 0&&(this._extensionErrorListener=bindings.onError),this._applyExtensionBindings(this._extensionRunner),await this._extensionRunner.emit(this._sessionStartEvent),await this.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup")}async extendResourcesFromExtensions(reason){if(!this._extensionRunner.hasHandlers("resources_discover"))return;let{skillPaths,promptPaths,themePaths}=await this._extensionRunner.emitResourcesDiscover(this._cwd,reason);if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:this.buildExtensionResourcePaths(skillPaths),promptPaths:this.buildExtensionResourcePaths(promptPaths),themePaths:this.buildExtensionResourcePaths(themePaths)};this._resourceLoader.extendResources(extensionPaths),this._rebuildSystemPrompt(this.getActiveToolNames())}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source=this.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename9(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(err2=>{runner.emitError({extensionPath:"<runtime>",event:"send_message",error:err2 instanceof Error?err2.message:String(err2)})})},sendUserMessage:(content,options)=>{this.sendUserMessage(content,options).catch(err2=>{runner.emitError({extensionPath:"<runtime>",event:"send_user_message",error:err2 instanceof Error?err2.message:String(err2)})})},appendEntry:(customType,data)=>{let entryId=this.sessionManager.appendCustomEntry(customType,data),entry=this.sessionManager.getEntry(entryId);entry&&this._emit({type:"entry_appended",entry})},setSessionName:name=>{this.setSessionName(name)},getSessionName:()=>this.sessionManager.getSessionName(),setLabel:(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label)},getActiveTools:()=>this.getActiveToolNames(),getAllTools:()=>this.getAllTools(),setActiveTools:toolNames=>this.setActiveToolsByName(toolNames),refreshTools:()=>this._refreshToolRegistry(),getCommands,setModel:async model=>this._modelRuntime.hasConfiguredAuth(model.provider)?(await this.setModel(model),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{getBackground:()=>this.background,getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),getContextSnapshot:()=>this.getContextSnapshot(),compact:options=>{(async()=>{try{let result2=await this.compact(options?.customInstructions);options?.onComplete?.(result2)}catch(error){let err2=error instanceof Error?error:new Error(String(error));options?.onError?.(err2)}})()},getSystemPrompt:()=>this.systemPrompt,getSystemPromptOptions:()=>this._baseSystemPromptOptions},{registerProvider:(name,config)=>{this._modelRuntime.registerProvider(name,config),this._refreshCurrentModelFromRegistry()},registerNativeProvider:provider=>{this._modelRuntime.registerNativeProvider(provider),this._refreshCurrentModelFromRegistry()},unregisterProvider:name=>{this._modelRuntime.unregisterProvider(name),this._refreshCurrentModelFromRegistry()}})}_refreshToolRegistry(options){let previousRegistryNames=new Set(this._toolRegistry.keys()),previousActiveToolNames=this.getActiveToolNames(),allowedToolNames=this._allowedToolNames,excludedToolNames=this._excludedToolNames,isAllowedTool=name=>(!allowedToolNames||allowedToolNames.has(name))&&!excludedToolNames?.has(name),allCustomTools=[...this._extensionRunner.getAllRegisteredTools(),...this._customTools.map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<sdk:${definition.name}>`,{source:"sdk"})}))].filter(tool=>isAllowedTool(tool.definition.name)),definitionRegistry=new Map(Array.from(this._baseToolDefinitions.entries()).filter(([name])=>isAllowedTool(name)).map(([name,definition])=>[name,{definition,sourceInfo:createSyntheticSourceInfo(`<builtin:${name}>`,{source:"builtin"})}]));for(let tool of allCustomTools)definitionRegistry.set(tool.definition.name,{definition:tool.definition,sourceInfo:tool.sourceInfo});this._toolDefinitions=definitionRegistry,this._toolPromptSnippets=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let snippet=this._normalizePromptSnippet(definition.promptSnippet);return snippet?[definition.name,snippet]:void 0}).filter(entry=>entry!==void 0)),this._toolPromptGuidelines=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let guidelines=this._normalizePromptGuidelines(definition.promptGuidelines);return guidelines.length>0?[definition.name,guidelines]:void 0}).filter(entry=>entry!==void 0));let runner=this._extensionRunner,wrappedExtensionTools=wrapRegisteredTools(allCustomTools,runner),wrappedBuiltInTools=wrapRegisteredTools(Array.from(this._baseToolDefinitions.values()).filter(definition=>isAllowedTool(definition.name)).map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<builtin:${definition.name}>`,{source:"builtin"})})),runner),toolRegistry=new Map(wrappedBuiltInTools.map(tool=>[tool.name,tool]));for(let tool of wrappedExtensionTools)toolRegistry.set(tool.name,tool);this._toolRegistry=toolRegistry;let nextActiveToolNames=(options?.activeToolNames?[...options.activeToolNames]:[...previousActiveToolNames]).filter(name=>isAllowedTool(name));if(allowedToolNames)for(let toolName of this._toolRegistry.keys())allowedToolNames.has(toolName)&&nextActiveToolNames.push(toolName);else if(options?.includeAllExtensionTools)for(let tool of wrappedExtensionTools)nextActiveToolNames.push(tool.name);else if(!options?.activeToolNames)for(let toolName of this._toolRegistry.keys())previousRegistryNames.has(toolName)||nextActiveToolNames.push(toolName);this.setActiveToolsByName([...new Set(nextActiveToolNames)])}_buildRuntime(options){let autoResizeImages=this.settingsManager.getImageAutoResize(),shellCommandPrefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),baseToolDefinitions=this._baseToolsOverride?Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name,tool])=>[name,createToolDefinitionFromAgentTool(tool)])):createAllToolDefinitions(this._cwd,{read:{autoResizeImages},bash:{commandPrefix:shellCommandPrefix,shellPath}});this._baseToolDefinitions=new Map(Object.entries(baseToolDefinitions).map(([name,tool])=>[name,tool]));let extensionsResult=this._resourceLoader.getExtensions();if(options.flagValues)for(let[name,value2]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value2);this._extensionRunner=new ExtensionRunner(extensionsResult.extensions,extensionsResult.runtime,this._cwd,this.sessionManager,new ModelRegistry(this._modelRuntime)),this._extensionRunnerRef&&(this._extensionRunnerRef.current=this._extensionRunner),this._bindExtensionCore(this._extensionRunner),this._applyExtensionBindings(this._extensionRunner);let defaultActiveToolNames=this._baseToolsOverride?Object.keys(this._baseToolsOverride):["read","bash","edit","write"],baseActiveToolNames=options.activeToolNames??defaultActiveToolNames;this._refreshToolRegistry({activeToolNames:baseActiveToolNames,includeAllExtensionTools:options.includeAllExtensionTools})}async reload(options){return this._withBackgroundPaused(()=>this._reloadBody(options))}async _reloadBody(options){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();this.background.close(),await Promise.all([this.background.shutdown(),this.abort()]),await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate(),await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._backgroundHost.replaceService(),this._buildRuntime({activeToolNames:this.getActiveToolNames(),flagValues:previousFlagValues,includeAllExtensionTools:!0}),(this.background.enabled||this._extensionUIContext||this._extensionCommandContextActions||this._extensionShutdownHandler||this._extensionErrorListener)&&(await options?.beforeSessionStart?.(),await this._extensionRunner.emit({type:"session_start",reason:"reload"}),await this.extendResourcesFromExtensions("reload"))}_isRetryableError(message){return isContextOverflow(message,this.model?.contextWindow??0)?!1:isRetryableAssistantError(message)}_summarizationRetryCallbacks(source){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage6)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage6})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}_finishCancelledRetry(){if(this._retryAttempt===0)return;let attempt2=this._retryAttempt;this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"})}async _prepareRetry(message){let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings2.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings2,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep3(delayMs,this._retryAbortController.signal)}catch{return this._finishCancelledRetry(),!1}finally{this._retryAbortController=void 0}return!0}abortRetry(){this._retryAbortController?.abort()}get isRetrying(){return this._retryAbortController!==void 0}get autoRetryEnabled(){return this.settingsManager.getRetryEnabled()}setAutoRetryEnabled(enabled){this.settingsManager.setRetryEnabled(enabled)}async executeBash(command,onChunk,options){let abortController=new AbortController;this._bashAbortControllers.add(abortController);let prefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),resolvedCommand=prefix?`${prefix}
|
|
1299
|
-
${command}`:command;try{let result2=await executeBashWithOperations(resolvedCommand,this.sessionManager.getCwd(),options?.operations??createLocalBashOperations({shellPath}),{onChunk:delta=>{onChunk?.(delta),this._emit({type:"bash_execution_update",id:options?.id,delta})},signal:abortController.signal});return this.recordBashResult(command,result2,options),result2}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result2,options){let bashMessage={role:"bashExecution",command,output:result2.output,exitCode:result2.exitCode,cancelled:result2.cancelled,truncated:result2.truncated,fullOutputPath:result2.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.sessionManager.appendMessage(bashMessage),this._refreshFinalizedContext())}abortBash(){for(let abortController of[...this._bashAbortControllers])abortController.abort()}get isBashRunning(){return this._bashAbortControllers.size>0}get hasPendingBashMessages(){return this._pendingBashMessages.length>0}_flushPendingBashMessages(){if(this._pendingBashMessages.length!==0){for(let bashMessage of this._pendingBashMessages)this.sessionManager.appendMessage(bashMessage);this._pendingBashMessages=[],this._refreshFinalizedContext()}}setSessionName(name){this.sessionManager.appendSessionInfo(name);let event={type:"session_info_changed",name:this.sessionManager.getSessionName()};this._emit(event),this._extensionRunner.emit(event)}async navigateTree(targetId,options={}){if(this.isStreaming)throw new Error("Wait for the current response to finish before navigating the session tree.");if(this.isCompacting)throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");let oldLeafId=this.sessionManager.getLeafId();if(targetId===oldLeafId)return{cancelled:!1};if(options.summarize&&!this.model)throw new Error("No model available for summarization");let targetEntry=this.sessionManager.getEntry(targetId);if(!targetEntry)throw new Error(`Entry ${targetId} not found`);let{entries:entriesToSummarize,commonAncestorId}=collectEntriesForBranchSummary2(this.sessionManager,oldLeafId,targetId),customInstructions=options.customInstructions,replaceInstructions=options.replaceInstructions,label=options.label,preparation={targetId,oldLeafId,commonAncestorId,entriesToSummarize,userWantsSummary:options.summarize??!1,customInstructions,replaceInstructions,label},resumeBackground=this.pauseBackgroundNotifications();this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result2=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result2?.cancel)return{cancelled:!0};result2?.summary&&options.summarize&&(extensionSummary=result2.summary,fromExtension=!0),result2?.customInstructions!==void 0&&(customInstructions=result2.customInstructions),result2?.replaceInstructions!==void 0&&(replaceInstructions=result2.replaceInstructions),result2?.label!==void 0&&(label=result2.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let model=this.model,{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model),branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result2=await generateBranchSummary2(entriesToSummarize,{model:requestModel,apiKey,headers,env:env2,signal:this._branchSummaryAbortController.signal,customInstructions,replaceInstructions,reserveTokens:branchSummarySettings.reserveTokens,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),callbacks:this._summarizationRetryCallbacks({source:"branchSummary"})});if(result2.aborted)return{cancelled:!0,aborted:!0};if(result2.error)throw new Error(result2.error);summaryText=result2.summary,summaryUsage=result2.usage,summaryDetails={readFiles:result2.readFiles||[],modifiedFiles:result2.modifiedFiles||[]}}else extensionSummary&&(summaryText=extensionSummary.summary,summaryDetails=extensionSummary.details,summaryUsage=extensionSummary.usage);let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId,await this.background.cancelOutsideBranch(new Set(newLeafId===null?[]:this.sessionManager.getBranch(newLeafId).map(entry=>entry.id)));let summaryEntry;if(summaryText){let summaryId=this.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,fromExtension,summaryUsage);summaryEntry=this.sessionManager.getEntry(summaryId),label&&this.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?this.sessionManager.resetLeaf():this.sessionManager.branch(newLeafId);return label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label),this._backgroundHost.restoreHistory(),this._refreshFinalizedContext(),this._restoreToolsFromTranscript(),await this._extensionRunner.emit({type:"session_tree",newLeafId:this.sessionManager.getLeafId(),oldLeafId,summaryEntry,fromExtension:summaryText?fromExtension:void 0}),{editorText,cancelled:!1,summaryEntry}}finally{this._branchSummaryAbortController=void 0,this._resolveIdleWaitIfIdle(),resumeBackground()}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result2=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text2=contentText(entry.message.content,"");text2&&result2.push({entryId:entry.id,text:text2})}return result2}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals(),entries=this.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries){if(entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++;else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c=>c.type==="toolCall").length)}}return{sessionFile:this.sessionFile,sessionId:this.sessionId,userMessages,assistantMessages,toolCalls,toolResults,totalMessages,tokens:{input:usageTotals.input,output:usageTotals.output,cacheRead:usageTotals.cacheRead,cacheWrite:usageTotals.cacheWrite,total:usageTotals.input+usageTotals.output+usageTotals.cacheRead+usageTotals.cacheWrite},cost:usageTotals.cost,contextUsage:this.getContextUsage()}}getContextUsage(){let model=this.model;if(!model)return;let contextWindow=model.contextWindow??0;if(contextWindow<=0)return;let projection=this.sessionManager.buildSessionProjection(),branch=this.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branch);if(latestCompaction){let projectedAssistants=new Set(projection.entries.flatMap(entry=>entry.messages.some(message=>message.role==="assistant"&&message.stopReason!=="aborted"&&message.stopReason!=="error"&&calculateContextTokens2(message.usage)>0)?[entry.sourceEntry.id]:[])),compactionIndex=branch.findIndex(entry=>entry.id===latestCompaction.id);if(!branch.slice(compactionIndex+1).some(entry=>projectedAssistants.has(entry.id)))return{tokens:null,contextWindow,percent:null}}let estimate=estimateProjectedContextTokens(projection,branch),percent=estimate.tokens/contextWindow*100;return{tokens:estimate.tokens,contextWindow,percent}}async exportToHtml(outputPath,options={}){let themeName=[options.themeName,this.settingsManager.getTheme()].find(candidate=>candidate!==void 0&&getThemeByName(candidate)!==void 0),toolRenderer=createToolHtmlRenderer({getToolDefinition:name=>this.getToolDefinition(name),theme,cwd:this.sessionManager.getCwd()});return await exportSessionToHtml(this.sessionManager,this.state,{outputPath,themeName,toolRenderer})}exportToJsonl(outputPath){return exportSessionToJsonl(this.sessionManager,outputPath)}async summarizeForBugReport(options){let model=this.model;if(!model)throw new Error("No model selected");let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model);return generateBugReportSummary({messages:this.messages,hint:options.hint,model:requestModel,apiKey,headers,env:env2,signal:options.signal,thinkingLevel:this.thinkingLevel,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),sessionId:this.sessionId})}getLastAssistantText(){let lastAssistant=this.messages.slice().reverse().find(m2=>{if(m2.role!=="assistant")return!1;let msg=m2;return!(msg.stopReason==="aborted"&&msg.content.length===0)});if(!lastAssistant)return;let text2="";for(let content of lastAssistant.content)content.type==="text"&&(text2+=content.text);return text2.trim()||void 0}createReplacedSessionContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()));return context.sendMessage=(message,options)=>this.sendCustomMessage(message,options),context.sendUserMessage=(content,options)=>this.sendUserMessage(content,options),context}hasExtensionHandlers(eventType){return this._extensionRunner.hasHandlers(eventType)}get extensionRunner(){return this._extensionRunner}};import{join as join31}from"node:path";var MAX_WARMING_AGE_MS=60*6e4,MAX_IDLE_WARMING_AGE_MS=30*6e4,CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS=.05,IDLE_CONTINUATION_PROBABILITY=.15;function getCacheWarmingDelayMs(ttlMs){if(!(ttlMs<=1e4))return Math.max(1,Math.floor(Math.min(ttlMs*.9,ttlMs-1e4)))}function getPromptCacheTtlMs(model,options){let retention=options?.cacheRetention??(getProviderEnvValue("PI_CACHE_RETENTION",options?.env)==="long"?"long":"short");if(retention==="none")return;let seconds=model.promptCache?.[retention];return seconds===void 0?void 0:seconds*1e3}function isReplayable(model,options){return!options?.reasoning||model.api!=="anthropic-messages"?!0:model.compat?.forceAdaptiveThinking===!0}function lastPromptTokens(entries){for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type==="message"&&entry.message.role==="assistant"){let usage=entry.message.usage;return usage.input+usage.cacheRead+usage.cacheWrite}}return 0}function price(model,tokens2){let usage={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},...tokens2};return calculateCost(model,usage).total}var CacheWarmer=class{constructor(models,sessionManager,getMode,decide=async event=>event.action){this.models=models,this.sessionManager=sessionManager,this.getMode=getMode,this.decide=decide,this.inactive={state:"inactive",reason:"waiting for first request"}}get status(){if(this.getMode()==="off")return{state:"inactive",reason:"cache warming disabled"};let run=this.run;if(!run)return this.inactive;if(!run.isCurrent())return{state:"inactive",reason:"conversation context changed"};let decision=this.evaluate(run),refreshing=run.timer===void 0;return!decision.economicsAvailable&&!refreshing?{state:"inactive",reason:"cache economics unavailable"}:{state:refreshing?"refreshing":"scheduled",nextWarmAt:run.nextWarmAt,decision,extensionOverride:run.extensionOverride}}start(request,isCurrent){if(this.clearRun(),this.getMode()==="off"){this.stop("cache warming disabled");return}if(!isReplayable(request.model,request.options)){this.stop("request cannot be replayed safely");return}let ttlMs=getPromptCacheTtlMs(request.model,request.options);if(ttlMs===void 0){this.stop(request.options.cacheRetention==="none"?"request disabled prompt caching":"cache lifetime unavailable");return}let delayMs=getCacheWarmingDelayMs(ttlMs);if(delayMs===void 0){this.stop("cache lifetime unavailable");return}this.run={...request,isCurrent,ttlMs,delayMs,refreshDeadlineAt:0,startedAt:Date.now(),controller:new AbortController,phase:"streaming",nextWarmAt:0,extensionOverride:!1},this.schedule(this.run)}onAgentSettled(){let run=this.run;if(!run)return;if(this.getMode()==="streaming"){this.stop("agent run settled");return}run.phase="idle";let deadline=run.startedAt+MAX_IDLE_WARMING_AGE_MS;(run.nextWarmAt>deadline||Date.now()>=deadline)&&this.stop("30-minute idle safety limit reached")}onModeChanged(){let run=this.run;if(!run)return;let reason=this.getModeStopReason(run);reason&&this.stop(reason)}cancel(){this.stop("inactive")}clearRun(){let run=this.run;run&&(this.run=void 0,run.timer&&clearTimeout(run.timer),run.controller.abort())}stop(reason,stopped){this.clearRun(),this.inactive={state:"inactive",reason,...stopped}}schedule(run){run.extensionOverride=!1,run.nextWarmAt=Date.now()+run.delayMs,run.refreshDeadlineAt=run.nextWarmAt+Math.floor((run.ttlMs-run.delayMs)/2);let deadline=run.startedAt+(run.phase==="idle"?MAX_IDLE_WARMING_AGE_MS:MAX_WARMING_AGE_MS);if(run.nextWarmAt>deadline||Date.now()>=deadline){this.stop(run.phase==="idle"?"30-minute idle safety limit reached":"one-hour safety limit reached");return}run.timer=setTimeout(()=>{this.refresh(run)},Math.max(0,run.nextWarmAt-Date.now())),run.timer.unref?.()}async refresh(run){if(run.timer=void 0,!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let decision=this.evaluate(run),{warmCost,missCost,continuationProbability}=decision,action=decision.action;try{action=await this.decide({type:"cache_warming_decision",warmCost,missCost,continuationProbability,action})}catch{}if(!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let extensionOverride=action!==decision.action;if(action==="stop"){let reason=extensionOverride?"stopped by extension":decision.economicsAvailable?"expected savings below threshold":"cache economics unavailable";this.stop(reason,{decision,extensionOverride});return}run.extensionOverride=extensionOverride;try{let message=await this.models.streamSimple(run.model,run.context,{...run.options,maxTokens:1,maxRetries:0,signal:run.controller.signal}).result();if(!this.validateRun(run))return;if(message.stopReason!=="error"&&message.stopReason!=="aborted"){let entry=this.sessionManager.appendUsage("cache_warm",message.provider,message.responseModel??message.model,message.usage,extensionOverride?"extension override":void 0);this.onWarmed?.(entry)}}catch{}this.run===run&&this.schedule(run)}refreshDeadlineMissed(run){return Date.now()<=run.refreshDeadlineAt?!1:(this.stop("cache refresh deadline missed"),!0)}validateRun(run){if(this.run!==run)return!1;let reason=this.getModeStopReason(run)??(run.isCurrent()?void 0:"conversation context changed");return reason?(this.stop(reason),!1):!0}getModeStopReason(run){let mode=this.getMode();if(mode==="off")return"cache warming disabled";if(mode==="streaming"&&run.phase==="idle")return"agent run settled"}evaluate(run){let model=run.model,promptTokens=lastPromptTokens(this.sessionManager.getBranch()),cacheHitCost=price(model,{cacheRead:promptTokens}),cacheMissCost=price(model,model.cost.cacheWrite>0?{cacheWrite:promptTokens}:{input:promptTokens}),warmCost=price(model,{cacheRead:promptTokens,output:1}),missCost=Math.max(0,cacheMissCost-cacheHitCost),continuationProbability=run.phase==="idle"?IDLE_CONTINUATION_PROBABILITY:1,economicsAvailable=promptTokens>0&&(cacheHitCost>0||cacheMissCost>0),expectedSavings=continuationProbability*missCost-warmCost;return{phase:run.phase,warmCost,missCost,continuationProbability,expectedSavings,economicsAvailable,action:expectedSavings>=CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS?"warm":"stop"}}};function formatDollars(value2){return value2<0?`-$${Math.abs(value2).toFixed(3)}`:`$${value2.toFixed(3)}`}function formatCacheWarmingEconomics(decision){if(!decision.economicsAvailable)return"cache economics unavailable";let probability=Math.round(decision.continuationProbability*100),probabilityText=decision.phase==="streaming"?`${probability}% continuation probability while agent is running`:`${probability}% continuation probability`,comparison=decision.action==="warm"?">=":"<";return`${probabilityText}, expected savings ${formatDollars(decision.expectedSavings)} ${comparison} $${CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS.toFixed(3)}`}function formatCacheWarmingDecisionTime(nextWarmAt,now){if(nextWarmAt===void 0||nextWarmAt<=now)return"Decision now";let remainingSeconds=Math.ceil((nextWarmAt-now)/1e3),hours=Math.floor(remainingSeconds/3600);remainingSeconds%=3600;let minutes=Math.floor(remainingSeconds/60),seconds=remainingSeconds%60,parts=[];return hours>0&&parts.push(`${hours}h`),minutes>0&&parts.push(`${minutes}m`),(seconds>0||parts.length===0)&&parts.push(`${seconds}s`),`Decision in ${parts.join(" ")}`}function formatCacheWarmingStatus(status,now=Date.now()){let decision=status.decision;if(!decision||status.state==="inactive"&&!decision.economicsAvailable&&!status.extensionOverride)return`Inactive (${status.reason??"unknown reason"})`;let details=status.extensionOverride?`extension override, ${formatCacheWarmingEconomics(decision)}`:`${formatCacheWarmingEconomics(decision)} -> ${decision.action}`;return status.state==="inactive"?`Stopped (${details})`:status.state==="refreshing"?`Warming cache (${details})`:`${formatCacheWarmingDecisionTime(status.nextWarmAt,now)} (${details})`}function formatCacheWarmingUsage(entry){let note=entry.note?` (${entry.note})`:"",cost=entry.usage.cost.total.toFixed(6).replace(/(\.\d{3}\d*?)0+$/,"$1");return`Cache warmed${note}: $${cost}`}import{isDeepStrictEqual}from"node:util";function convertWithImagePolicy(messages,blockImages){let converted=convertToLlm(messages);return blockImages?converted.map(message=>{if(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some(part=>part.type==="image"))return message;let content=message.content.map(part=>part.type==="image"?{type:"text",text:"Image reading is disabled."}:part).filter((part,i,all)=>!(part.type==="text"&&part.text==="Image reading is disabled."&&i>0&&all[i-1].type==="text"&&all[i-1].text===part.text));return{...message,content}}):converted}var ContextSnapshotCapture=class{constructor(settings2,runnerRef){this.pending=new WeakMap,this.convertToLlm=messages=>{let blockImages=this.settings.getBlockImages(),converted=convertWithImagePolicy(messages,blockImages),source=this.pending.get(messages);return source&&(this.pending.delete(messages),this.prepared={source,messages:structuredClone(converted),blockImages}),converted},this.capture=async messages=>{let runner=this.runnerRef.current,blockImages=this.settings.getBlockImages(),prepared=this.prepared;if(prepared&&prepared.source.runner===runner&&prepared.blockImages===blockImages&&isDeepStrictEqual(messages.slice(0,prepared.source.messages.length),prepared.source.messages))return[...structuredClone(prepared.messages),...convertWithImagePolicy(messages.slice(prepared.source.messages.length),blockImages)];let transformed=runner?await runner.emitContext(messages):messages;return structuredClone(convertWithImagePolicy(transformed,blockImages))},this.settings=settings2,this.runnerRef=runnerRef}install(agent){let transform=agent.transformContext;agent.transformContext=async(messages,signal)=>{let runner=this.runnerRef.current,source={messages:structuredClone(messages),runner},transformed=transform?await transform(messages,signal):messages;return this.pending.set(transformed,source),transformed},agent.convertToLlm=this.convertToLlm}};import{existsSync as existsSync17,readdirSync as readdirSync9,readFileSync as readFileSync13,statSync as statSync11}from"node:fs";import{basename as basename10,dirname as dirname19,join as join28,resolve as resolve9,sep as sep9}from"node:path";import{statSync as statSync9}from"node:fs";import{homedir as homedir8,userInfo}from"node:os";import{isAbsolute as isAbsolute4,join as join26,relative as relative5,sep as sep8}from"node:path";function samePath(left,right){return left!==void 0&&relative5(canonicalizePath(left),canonicalizePath(right))===""}function isPathInside(parent,child){let relativePath=relative5(canonicalizePath(parent),canonicalizePath(child));return relativePath!==""&&relativePath!==".."&&!relativePath.startsWith(`..${sep8}`)&&!isAbsolute4(relativePath)}function pathKey(value2){let normalized=canonicalizePath(resolvePath(value2));return process.platform==="win32"?normalized.replace(/^([A-Z]):/,(_2,drive)=>`${drive.toLowerCase()}:`):normalized}function fileIdentity(value2){try{let stats=statSync9(value2,{bigint:!0});return stats.ino===0n?void 0:`${stats.dev}:${stats.ino}`}catch{return}}function referToSameLocation(left,right){let leftKey=pathKey(left),rightKey=pathKey(right);if(leftKey===rightKey)return!0;if(process.platform!=="win32")return!1;let leftIdentity=fileIdentity(leftKey);return leftIdentity!==void 0&&leftIdentity===fileIdentity(rightKey)}function findPathKeys(record,path14){return process.platform!=="win32"?Object.hasOwn(record,path14)?[path14]:[]:Object.keys(record).filter(key=>referToSameLocation(key,path14))}function userAgentsSkillsDirMatcher(){let homes=[process.env.HOME||homedir8()];try{homes.push(userInfo().homedir)}catch{}let skillDirs=homes.map(home=>join26(pathKey(home),".agents","skills"));return dir=>skillDirs.some(skillDir=>referToSameLocation(skillDir,dir))}import{execFile,spawnSync as spawnSync5}from"child_process";import{existsSync as existsSync16,readFileSync as readFileSync12,statSync as statSync10,unwatchFile,watchFile}from"fs";import{dirname as dirname18,join as join27,resolve as resolve8}from"path";function findGitPaths(cwd){let dir=cwd;for(;;){let gitPath=join27(dir,".git");if(existsSync16(gitPath))try{let stat3=statSync10(gitPath);if(stat3.isFile()){let content=readFileSync12(gitPath,"utf8").trim();if(content.startsWith("gitdir: ")){let gitDir=resolve8(dir,content.slice(8).trim()),headPath=join27(gitDir,"HEAD");if(!existsSync16(headPath))return null;let commonDirPath=join27(gitDir,"commondir"),commonGitDir=existsSync16(commonDirPath)?resolve8(gitDir,readFileSync12(commonDirPath,"utf8").trim()):gitDir;return{repoDir:dir,commonGitDir,headPath}}}else if(stat3.isDirectory()){let headPath=join27(gitPath,"HEAD");return existsSync16(headPath)?{repoDir:dir,commonGitDir:gitPath,headPath}:null}}catch{return null}let parent=dirname18(dir);if(parent===dir)return null;dir=parent}}function resolveBranchWithGitSync(repoDir){let result2=spawnSync5("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8",stdio:["ignore","pipe","ignore"]});return(result2.status===0?result2.stdout.trim():"")||null}function resolveBranchWithGitAsync(repoDir){return new Promise(resolvePromise=>{execFile("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8"},(error,stdout)=>{if(error){resolvePromise(null);return}let branch=stdout.trim();resolvePromise(branch||null)})})}function isWslEnvironment(){return process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP)}function isWindowsMountedRepoPath(repoDir){return/^\/mnt\/[a-z](?:\/|$)/i.test(repoDir)}function shouldPollGitHead(repoDir){return isWslEnvironment()&&isWindowsMountedRepoPath(repoDir)}var FooterDataProvider=class _FooterDataProvider{static{this.WATCH_DEBOUNCE_MS=500}constructor(cwd){this.extensionStatuses=new Map,this.cachedBranch=void 0,this.gitPaths=void 0,this.headWatcher=null,this.headWatchFilePath=null,this.headWatchFileListener=null,this.reftableWatcher=null,this.reftableTablesListWatcher=null,this.reftableTablesListPath=null,this.branchChangeCallbacks=new Set,this.availableProviderCount=0,this.refreshTimer=null,this.gitWatcherRetryTimer=null,this.refreshInFlight=!1,this.refreshPending=!1,this.disposed=!1,this.cwd=cwd,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher()}getGitBranch(){return this.cachedBranch===void 0&&(this.cachedBranch=this.resolveGitBranchSync()),this.cachedBranch}getExtensionStatuses(){return this.extensionStatuses}onBranchChange(callback){return this.branchChangeCallbacks.add(callback),()=>this.branchChangeCallbacks.delete(callback)}setExtensionStatus(key,text2){text2===void 0?this.extensionStatuses.delete(key):this.extensionStatuses.set(key,text2)}clearExtensionStatuses(){this.extensionStatuses.clear()}getAvailableProviderCount(){return this.availableProviderCount}setAvailableProviderCount(count){this.availableProviderCount=count}setCwd(cwd){this.cwd!==cwd&&(this.cwd=cwd,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.cachedBranch=void 0,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher(),this.notifyBranchChange())}dispose(){this.disposed=!0,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.branchChangeCallbacks.clear()}notifyBranchChange(){for(let cb of this.branchChangeCallbacks)cb()}scheduleRefresh(){if(!(this.disposed||this.refreshTimer)){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.refreshGitBranchAsync()},_FooterDataProvider.WATCH_DEBOUNCE_MS)}}async refreshGitBranchAsync(){if(!this.disposed){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshInFlight=!0;try{let nextBranch=await this.resolveGitBranchAsync();if(this.disposed)return;if(this.cachedBranch!==void 0&&this.cachedBranch!==nextBranch){this.cachedBranch=nextBranch,this.notifyBranchChange();return}this.cachedBranch=nextBranch}finally{this.refreshInFlight=!1,this.refreshPending&&!this.disposed&&(this.refreshPending=!1,this.scheduleRefresh())}}}resolveGitBranchSync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?resolveBranchWithGitSync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}async resolveGitBranchAsync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?await resolveBranchWithGitAsync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}clearGitWatchers(){closeWatcher(this.headWatcher),this.headWatcher=null,this.headWatchFilePath&&this.headWatchFileListener&&(unwatchFile(this.headWatchFilePath,this.headWatchFileListener),this.headWatchFilePath=null,this.headWatchFileListener=null),closeWatcher(this.reftableWatcher),this.reftableWatcher=null,closeWatcher(this.reftableTablesListWatcher),this.reftableTablesListWatcher=null,this.reftableTablesListPath&&(unwatchFile(this.reftableTablesListPath),this.reftableTablesListPath=null),this.gitWatcherRetryTimer&&(clearTimeout(this.gitWatcherRetryTimer),this.gitWatcherRetryTimer=null)}scheduleGitWatcherRetry(){this.disposed||this.gitWatcherRetryTimer||(this.gitWatcherRetryTimer=setTimeout(()=>{this.gitWatcherRetryTimer=null,this.setupGitWatcher()},FS_WATCH_RETRY_DELAY_MS))}handleGitWatcherError(){this.clearGitWatchers(),this.scheduleGitWatcherRetry()}setupGitWatcher(){if(this.clearGitWatchers(),!this.gitPaths)return;let pollGitHead=shouldPollGitHead(this.gitPaths.repoDir);if(this.headWatcher=watchWithErrorHandler(dirname18(this.gitPaths.headPath),(_eventType,filename)=>{(!filename||filename==="HEAD")&&this.scheduleRefresh()},()=>this.handleGitWatcherError()),pollGitHead&&(this.headWatchFilePath=this.gitPaths.headPath,this.headWatchFileListener=(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()},watchFile(this.headWatchFilePath,{interval:1e3},this.headWatchFileListener)),!this.headWatcher&&!pollGitHead)return;let reftableDir=join27(this.gitPaths.commonGitDir,"reftable");if(existsSync16(reftableDir)){if(this.reftableWatcher=watchWithErrorHandler(reftableDir,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableWatcher)return;let tablesListPath=join27(reftableDir,"tables.list");if(existsSync16(tablesListPath)){if(this.reftableTablesListPath=tablesListPath,this.reftableTablesListWatcher=watchWithErrorHandler(tablesListPath,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableTablesListWatcher)return;watchFile(tablesListPath,{interval:250},(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()})}}}};function resolvePromptInput(input2,description){if(input2){if(existsSync17(input2))try{return stripBom(readFileSync13(input2,"utf-8"))}catch(error){return console.error(source_default.yellow(`Warning: Could not read ${description} file ${input2}: ${error}`)),input2}return input2}}function loadContextFileFromDir(dir){let candidates=["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"];for(let filename of candidates){let filePath=join28(dir,filename);if(existsSync17(filePath))try{if(!statSync11(filePath).isFile())continue;return{path:filePath,content:stripBom(readFileSync13(filePath,"utf-8"))}}catch(error){console.error(source_default.yellow(`Warning: Could not read ${filePath}: ${error}`))}}return null}function findShadowedContextFile(cwd){let gitPaths=findGitPaths(cwd);if(!gitPaths)return;let commonGitDir=canonicalizePath(gitPaths.commonGitDir),worktreeRoot=canonicalizePath(gitPaths.repoDir),mainRepoRoot=dirname19(commonGitDir);if(!isPathInside(mainRepoRoot,worktreeRoot)||!samePath(join28(mainRepoRoot,".git"),commonGitDir))return;let worktreeContextFile=loadContextFileFromDir(worktreeRoot);return worktreeContextFile?join28(mainRepoRoot,basename10(worktreeContextFile.path)):void 0}function loadProjectContextFiles(options){let resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(options.agentDir),contextFiles=[],seenPaths=new Set,globalContext=loadContextFileFromDir(resolvedAgentDir);globalContext&&(contextFiles.push(globalContext),seenPaths.add(globalContext.path));let ancestorContextFiles=[],shadowedContextFile=findShadowedContextFile(resolvedCwd),currentDir=resolvedCwd;for(;;){let contextFile=loadContextFileFromDir(currentDir),isShadowed=shadowedContextFile!==void 0&&samePath(contextFile?.path,shadowedContextFile);contextFile&&!isShadowed&&!seenPaths.has(contextFile.path)&&(ancestorContextFiles.unshift(contextFile),seenPaths.add(contextFile.path));let parentDir=dirname19(currentDir);if(parentDir===currentDir)break;currentDir=parentDir}return contextFiles.push(...ancestorContextFiles),contextFiles}var DefaultResourceLoader=class{constructor(options){this.cwd=resolvePath(options.cwd),this.agentDir=resolvePath(options.agentDir),this.settingsManager=options.settingsManager??SettingsManager.create(this.cwd,this.agentDir),this.eventBus=options.eventBus??createEventBus(),this.packageManager=new DefaultPackageManager({cwd:this.cwd,agentDir:this.agentDir,settingsManager:this.settingsManager}),this.additionalExtensionPaths=options.additionalExtensionPaths??[],this.additionalSkillPaths=options.additionalSkillPaths??[],this.additionalPromptTemplatePaths=options.additionalPromptTemplatePaths??[],this.additionalThemePaths=options.additionalThemePaths??[],this.extensionFactories=options.extensionFactories??[],this.noExtensions=options.noExtensions??!1,this.noSkills=options.noSkills??!1,this.noPromptTemplates=options.noPromptTemplates??!1,this.noThemes=options.noThemes??!1,this.noContextFiles=options.noContextFiles??!1,this.systemPromptSource=options.systemPrompt,this.appendSystemPromptSource=options.appendSystemPrompt,this.extensionsOverride=options.extensionsOverride,this.skillsOverride=options.skillsOverride,this.promptsOverride=options.promptsOverride,this.themesOverride=options.themesOverride,this.agentsFilesOverride=options.agentsFilesOverride,this.systemPromptOverride=options.systemPromptOverride,this.appendSystemPromptOverride=options.appendSystemPromptOverride,this.extensionsResult={extensions:[],errors:[],runtime:createExtensionRuntime()},this.skills=[],this.skillDiagnostics=[],this.prompts=[],this.promptDiagnostics=[],this.themes=[],this.themeDiagnostics=[],this.agentsFiles=[],this.appendSystemPrompt=[],this.appendSystemPromptSourcePaths=[],this.lastSkillPaths=[],this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map,this.resourceMetadataByPath=new Map,this.lastPromptPaths=[],this.lastThemePaths=[],this.loaded=!1}getExtensions(){return this.extensionsResult}getSkills(){return{skills:this.skills,diagnostics:this.skillDiagnostics}}getPrompts(){return{prompts:this.prompts,diagnostics:this.promptDiagnostics}}getThemes(){return{themes:this.themes,diagnostics:this.themeDiagnostics}}getAgentsFiles(){return{agentsFiles:this.agentsFiles}}getSystemPrompt(){return this.systemPrompt}getSystemPromptSource(){return this.systemPromptSourcePath?{path:this.systemPromptSourcePath}:void 0}getAppendSystemPrompt(){return this.appendSystemPrompt}getAppendSystemPromptSources(){return this.appendSystemPromptSourcePaths.map(path14=>({path:path14}))}extendResources(paths){let skillPaths=this.normalizeExtensionPaths(paths.skillPaths??[]),promptPaths=this.normalizeExtensionPaths(paths.promptPaths??[]),themePaths=this.normalizeExtensionPaths(paths.themePaths??[]);for(let entry of skillPaths)this.extensionSkillSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of promptPaths)this.extensionPromptSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of themePaths)this.extensionThemeSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));skillPaths.length>0&&(this.lastSkillPaths=this.mergePaths(this.lastSkillPaths,skillPaths.map(entry=>entry.path)),this.updateSkillsFromPaths(this.lastSkillPaths,this.resourceMetadataByPath)),promptPaths.length>0&&(this.lastPromptPaths=this.mergePaths(this.lastPromptPaths,promptPaths.map(entry=>entry.path)),this.updatePromptsFromPaths(this.lastPromptPaths,this.resourceMetadataByPath)),themePaths.length>0&&(this.lastThemePaths=this.mergePaths(this.lastThemePaths,themePaths.map(entry=>entry.path)),this.updateThemesFromPaths(this.lastThemePaths,this.resourceMetadataByPath))}async loadProjectTrustExtensions(){return this.settingsManager.setProjectTrusted(!1),await this.settingsManager.reload(),this.loadCurrentExtensionSet({includeInlineFactories:!0})}async reload(options){resetTimings("extensions"),this.loaded&&clearExtensionCache();let preTrustExtensions;if(options?.resolveProjectTrust){preTrustExtensions=await this.loadProjectTrustExtensions();let projectTrusted=await options.resolveProjectTrust({extensionsResult:preTrustExtensions});this.settingsManager.setProjectTrusted(projectTrusted)}await this.settingsManager.reload();let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0});this.resourceMetadataByPath=new Map;let metadataByPath=this.resourceMetadataByPath;this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map;let getEnabledResources=resources=>{for(let r of resources)metadataByPath.has(r.path)||metadataByPath.set(r.path,r.metadata);return resources.filter(r=>r.enabled)},getEnabledPaths=resources=>getEnabledResources(resources).map(r=>r.path),enabledExtensions=getEnabledPaths(resolvedPaths.extensions),enabledSkillResources=getEnabledResources(resolvedPaths.skills),enabledPrompts=getEnabledPaths(resolvedPaths.prompts),enabledThemes=getEnabledPaths(resolvedPaths.themes),enabledSkills=enabledSkillResources.map(resource=>this.mapSkillPath(resource,metadataByPath));for(let r of cliExtensionPaths.extensions)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});for(let r of cliExtensionPaths.skills)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});let cliEnabledExtensions=getEnabledPaths(cliExtensionPaths.extensions),cliEnabledSkills=getEnabledPaths(cliExtensionPaths.skills),cliEnabledPrompts=getEnabledPaths(cliExtensionPaths.prompts),cliEnabledThemes=getEnabledPaths(cliExtensionPaths.themes),extensionPaths=this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions),extensionsResult=await this.loadFinalExtensionSet(extensionPaths,preTrustExtensions);for(let p of this.additionalExtensionPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);existsSync17(resolved)||extensionsResult.errors.push({path:resolved,error:`Extension path does not exist: ${resolved}`})}this.extensionsResult=this.extensionsOverride?this.extensionsOverride(extensionsResult):extensionsResult,this.applyExtensionSourceInfo(this.extensionsResult.extensions,metadataByPath);let skillPaths=this.noSkills?this.mergePaths(cliEnabledSkills,this.additionalSkillPaths):this.mergePaths([...cliEnabledSkills,...enabledSkills],this.additionalSkillPaths);this.lastSkillPaths=skillPaths,this.updateSkillsFromPaths(skillPaths,metadataByPath);for(let p of this.additionalSkillPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.skillDiagnostics.some(d=>d.path===resolved)&&this.skillDiagnostics.push({type:"error",message:"Skill path does not exist",path:resolved})}let promptPaths=this.noPromptTemplates?this.mergePaths(cliEnabledPrompts,this.additionalPromptTemplatePaths):this.mergePaths([...cliEnabledPrompts,...enabledPrompts],this.additionalPromptTemplatePaths);this.lastPromptPaths=promptPaths,this.updatePromptsFromPaths(promptPaths,metadataByPath);for(let p of this.additionalPromptTemplatePaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.promptDiagnostics.some(d=>d.path===resolved)&&this.promptDiagnostics.push({type:"error",message:"Prompt template path does not exist",path:resolved})}let themePaths=this.noThemes?this.mergePaths(cliEnabledThemes,this.additionalThemePaths):this.mergePaths([...cliEnabledThemes,...enabledThemes],this.additionalThemePaths);this.lastThemePaths=themePaths,this.updateThemesFromPaths(themePaths,metadataByPath);for(let p of this.additionalThemePaths){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.themeDiagnostics.some(d=>d.path===resolved)&&this.themeDiagnostics.push({type:"error",message:"Theme path does not exist",path:resolved})}let agentsFiles={agentsFiles:this.noContextFiles?[]:loadProjectContextFiles({cwd:this.cwd,agentDir:this.agentDir})},resolvedAgentsFiles=this.agentsFilesOverride?this.agentsFilesOverride(agentsFiles):agentsFiles;this.agentsFiles=resolvedAgentsFiles.agentsFiles;let systemPromptSource=this.systemPromptSource??this.discoverSystemPromptFile(),baseSystemPrompt=resolvePromptInput(systemPromptSource,"system prompt");this.systemPrompt=this.systemPromptOverride?this.systemPromptOverride(baseSystemPrompt):baseSystemPrompt,this.systemPromptSourcePath=systemPromptSource&&existsSync17(systemPromptSource)?resolvePath(systemPromptSource):void 0;let appendSources=this.appendSystemPromptSource;if(!appendSources){let discoveredAppendSystemPromptFile=this.discoverAppendSystemPromptFile();appendSources=discoveredAppendSystemPromptFile?[discoveredAppendSystemPromptFile]:[]}let baseAppend=appendSources.map(s=>resolvePromptInput(s,"append system prompt")).filter(s=>s!==void 0);this.appendSystemPrompt=this.appendSystemPromptOverride?this.appendSystemPromptOverride(baseAppend):baseAppend,this.appendSystemPromptSourcePaths=appendSources.filter(source=>existsSync17(source)).map(source=>resolvePath(source)),this.loaded=!0}async loadCurrentExtensionSet(options){let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0}),enabledExtensions=resolvedPaths.extensions.filter(r=>r.enabled).map(r=>r.path),cliEnabledExtensions=cliExtensionPaths.extensions.filter(r=>r.enabled).map(r=>r.path),extensionPaths=this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions),extensionsResult=await loadExtensionsCached(extensionPaths,this.cwd,this.eventBus);if(!options.includeInlineFactories)return extensionsResult;let inlineExtensions=await this.loadExtensionFactories(extensionsResult.runtime);return extensionsResult.extensions.push(...inlineExtensions.extensions),extensionsResult.errors.push(...inlineExtensions.errors),extensionsResult}resolveExtensionLoadPath(path14){return resolvePath(path14,this.cwd,{normalizeUnicodeSpaces:!0})}async loadFinalExtensionSet(extensionPaths,preTrustExtensions){if(!preTrustExtensions){let extensionsResult2=await loadExtensionsCached(extensionPaths,this.cwd,this.eventBus),inlineExtensions2=await this.loadExtensionFactories(extensionsResult2.runtime);return extensionsResult2.extensions.push(...inlineExtensions2.extensions),extensionsResult2.errors.push(...inlineExtensions2.errors),this.addExtensionConflictDiagnostics(extensionsResult2),extensionsResult2}let preloadedByPath=new Map(preTrustExtensions.extensions.filter(extension=>!extension.path.startsWith("<inline:")).map(extension=>[extension.resolvedPath,extension])),failedPreloadPaths=new Set(preTrustExtensions.errors.map(error=>this.resolveExtensionLoadPath(error.path))),remainingPaths=extensionPaths.filter(path14=>{let resolvedPath=this.resolveExtensionLoadPath(path14);return!preloadedByPath.has(resolvedPath)&&!failedPreloadPaths.has(resolvedPath)}),remainingExtensions=await loadExtensionsCached(remainingPaths,this.cwd,this.eventBus,preTrustExtensions.runtime),loadedByPath=new Map(preloadedByPath);for(let extension of remainingExtensions.extensions)loadedByPath.set(extension.resolvedPath,extension);let inlineExtensions=preTrustExtensions.extensions.filter(extension=>extension.path.startsWith("<inline:")),orderedExtensions=extensionPaths.map(path14=>loadedByPath.get(this.resolveExtensionLoadPath(path14))).filter(extension=>extension!==void 0);orderedExtensions.push(...inlineExtensions);let extensionsResult={extensions:orderedExtensions,errors:[...preTrustExtensions.errors,...remainingExtensions.errors],runtime:preTrustExtensions.runtime};return this.addExtensionConflictDiagnostics(extensionsResult),extensionsResult}addExtensionConflictDiagnostics(extensionsResult){let conflicts=this.detectExtensionConflicts(extensionsResult.extensions);for(let conflict of conflicts)extensionsResult.errors.push({path:conflict.path,error:conflict.message})}mapSkillPath(resource,metadataByPath){if(resource.metadata.source!=="auto"&&resource.metadata.origin!=="package")return resource.path;try{if(!statSync11(resource.path).isDirectory())return resource.path}catch{return resource.path}let skillFile=join28(resource.path,"SKILL.md");return existsSync17(skillFile)?(metadataByPath.has(skillFile)||metadataByPath.set(skillFile,resource.metadata),skillFile):resource.path}normalizeExtensionPaths(entries){return entries.map(entry=>{let metadata=entry.metadata.baseDir?{...entry.metadata,baseDir:this.resolveResourcePath(entry.metadata.baseDir)}:entry.metadata;return{path:this.resolveResourcePath(entry.path),metadata}})}updateSkillsFromPaths(skillPaths,metadataByPath){let skillsResult;this.noSkills&&skillPaths.length===0?skillsResult={skills:[],diagnostics:[]}:skillsResult=loadSkills({cwd:this.cwd,agentDir:this.agentDir,skillPaths,includeDefaults:!1});let resolvedSkills=this.skillsOverride?this.skillsOverride(skillsResult):skillsResult;this.skills=resolvedSkills.skills.map(skill=>({...skill,sourceInfo:this.findSourceInfoForPath(skill.filePath,this.extensionSkillSourceInfos,metadataByPath)??skill.sourceInfo??this.getDefaultSourceInfoForPath(skill.filePath)})),this.skillDiagnostics=resolvedSkills.diagnostics}updatePromptsFromPaths(promptPaths,metadataByPath){let promptsResult;if(this.noPromptTemplates&&promptPaths.length===0)promptsResult={prompts:[],diagnostics:[]};else{let loaded=loadPromptTemplates2({cwd:this.cwd,agentDir:this.agentDir,promptPaths,includeDefaults:!1}),deduped=this.dedupePrompts(loaded.templates);promptsResult={prompts:deduped.prompts,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedPrompts=this.promptsOverride?this.promptsOverride(promptsResult):promptsResult;this.prompts=resolvedPrompts.prompts.map(prompt=>({...prompt,sourceInfo:this.findSourceInfoForPath(prompt.filePath,this.extensionPromptSourceInfos,metadataByPath)??prompt.sourceInfo??this.getDefaultSourceInfoForPath(prompt.filePath)})),this.promptDiagnostics=resolvedPrompts.diagnostics}updateThemesFromPaths(themePaths,metadataByPath){let themesResult;if(this.noThemes&&themePaths.length===0)themesResult={themes:[],diagnostics:[]};else{let loaded=this.loadThemes(themePaths,!1),deduped=this.dedupeThemes(loaded.themes);themesResult={themes:deduped.themes,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedThemes=this.themesOverride?this.themesOverride(themesResult):themesResult;this.themes=resolvedThemes.themes.map(theme2=>{let sourcePath=theme2.sourcePath;return theme2.sourceInfo=sourcePath?this.findSourceInfoForPath(sourcePath,this.extensionThemeSourceInfos,metadataByPath)??theme2.sourceInfo??this.getDefaultSourceInfoForPath(sourcePath):theme2.sourceInfo,theme2}),this.themeDiagnostics=resolvedThemes.diagnostics}applyExtensionSourceInfo(extensions,metadataByPath){for(let extension of extensions){extension.sourceInfo=this.findSourceInfoForPath(extension.path,void 0,metadataByPath)??this.getDefaultSourceInfoForPath(extension.path);for(let command of extension.commands.values())command.sourceInfo=extension.sourceInfo;for(let tool of extension.tools.values())tool.sourceInfo=extension.sourceInfo}}findSourceInfoForPath(resourcePath,extraSourceInfos,metadataByPath){if(!resourcePath)return;if(resourcePath.startsWith("<"))return this.getDefaultSourceInfoForPath(resourcePath);let normalizedResourcePath=resolve9(resourcePath);if(extraSourceInfos)for(let[sourcePath,sourceInfo]of extraSourceInfos.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return{...sourceInfo,path:resourcePath}}if(metadataByPath){let exact=metadataByPath.get(normalizedResourcePath)??metadataByPath.get(resourcePath);if(exact)return createSourceInfo(resourcePath,exact);for(let[sourcePath,metadata]of metadataByPath.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return createSourceInfo(resourcePath,metadata)}}}getDefaultSourceInfoForPath(filePath){if(filePath.startsWith("<")&&filePath.endsWith(">"))return{path:filePath,source:filePath.slice(1,-1).split(":")[0]||"temporary",scope:"temporary",origin:"top-level"};let normalizedPath=resolve9(filePath),agentRoots=[join28(this.agentDir,"skills"),join28(this.agentDir,"prompts"),join28(this.agentDir,"themes"),join28(this.agentDir,"extensions")],projectRoots=[join28(this.cwd,CONFIG_DIR_NAME,"skills"),join28(this.cwd,CONFIG_DIR_NAME,"prompts"),join28(this.cwd,CONFIG_DIR_NAME,"themes"),join28(this.cwd,CONFIG_DIR_NAME,"extensions")];for(let root of agentRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"user",origin:"top-level",baseDir:root};for(let root of projectRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"project",origin:"top-level",baseDir:root};return{path:filePath,source:"local",scope:"temporary",origin:"top-level",baseDir:statSync11(normalizedPath).isDirectory()?normalizedPath:resolve9(normalizedPath,"..")}}mergePaths(primary,additional){let merged=[],seen=new Set;for(let p of[...primary,...additional]){let resolved=this.resolveResourcePath(p),canonicalPath=canonicalizePath(resolved);seen.has(canonicalPath)||(seen.add(canonicalPath),merged.push(resolved))}return merged}resolveResourcePath(p){return resolvePath(p,this.cwd,{trim:!0})}loadThemes(paths,includeDefaults=!0){let themes=[],diagnostics=[];if(includeDefaults){let defaultDirs=[join28(this.agentDir,"themes"),join28(this.cwd,CONFIG_DIR_NAME,"themes")];for(let dir of defaultDirs)this.loadThemesFromDir(dir,themes,diagnostics)}for(let p of paths){let resolved=this.resolveResourcePath(p);if(!existsSync17(resolved)){diagnostics.push({type:"warning",message:"theme path does not exist",path:resolved});continue}try{let stats=statSync11(resolved);stats.isDirectory()?this.loadThemesFromDir(resolved,themes,diagnostics):stats.isFile()&&resolved.endsWith(".json")?this.loadThemeFromFile(resolved,themes,diagnostics):diagnostics.push({type:"warning",message:"theme path is not a json file",path:resolved})}catch(error){let message=error instanceof Error?error.message:"failed to read theme path";diagnostics.push({type:"warning",message,path:resolved})}}return{themes,diagnostics}}loadThemesFromDir(dir,themes,diagnostics){if(existsSync17(dir))try{let entries=readdirSync9(dir,{withFileTypes:!0});for(let entry of entries){let isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync11(join28(dir,entry.name)).isFile()}catch{continue}isFile&&entry.name.endsWith(".json")&&this.loadThemeFromFile(join28(dir,entry.name),themes,diagnostics)}}catch(error){let message=error instanceof Error?error.message:"failed to read theme directory";diagnostics.push({type:"warning",message,path:dir})}}loadThemeFromFile(filePath,themes,diagnostics){try{themes.push(loadThemeFromPath(filePath))}catch(error){let message=error instanceof Error?error.message:"failed to load theme";diagnostics.push({type:"warning",message,path:filePath})}}async loadExtensionFactories(runtime){let extensions=[],errors=[];for(let[index3,input2]of this.extensionFactories.entries()){let isNamed=typeof input2!="function",factory=isNamed?input2.factory:input2,extensionPath=`<inline:${isNamed?input2.name:index3+1}>`;try{let extension=await loadExtensionFromFactory(factory,this.cwd,this.eventBus,runtime,extensionPath);extension.hidden=isNamed&&input2.hidden,extensions.push(extension)}catch(error){let message=error instanceof Error?error.message:"failed to load extension";errors.push({path:extensionPath,error:message})}}return{extensions,errors}}dedupePrompts(prompts){let seen=new Map,diagnostics=[];for(let prompt of prompts){let existing=seen.get(prompt.name);existing?diagnostics.push({type:"collision",message:`name "/${prompt.name}" collision`,path:prompt.filePath,collision:{resourceType:"prompt",name:prompt.name,winnerPath:existing.filePath,loserPath:prompt.filePath}}):seen.set(prompt.name,prompt)}return{prompts:Array.from(seen.values()),diagnostics}}dedupeThemes(themes){let seen=new Map,diagnostics=[];for(let t of themes){let name=t.name??"unnamed",existing=seen.get(name);existing?diagnostics.push({type:"collision",message:`name "${name}" collision`,path:t.sourcePath,collision:{resourceType:"theme",name,winnerPath:existing.sourcePath??"<builtin>",loserPath:t.sourcePath??"<builtin>"}}):seen.set(name,t)}return{themes:Array.from(seen.values()),diagnostics}}discoverSystemPromptFile(){let projectPath=join28(this.cwd,CONFIG_DIR_NAME,"SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync17(projectPath))return projectPath;let globalPath=join28(this.agentDir,"SYSTEM.md");if(existsSync17(globalPath))return globalPath}discoverAppendSystemPromptFile(){let projectPath=join28(this.cwd,CONFIG_DIR_NAME,"APPEND_SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync17(projectPath))return projectPath;let globalPath=join28(this.agentDir,"APPEND_SYSTEM.md");if(existsSync17(globalPath))return globalPath}isUnderPath(target,root){let normalizedRoot=resolve9(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep9)?normalizedRoot:`${normalizedRoot}${sep9}`;return target.startsWith(prefix)}detectExtensionConflicts(extensions){let conflicts=[],toolOwners=new Map,flagOwners=new Map;for(let ext2 of extensions){for(let toolName of ext2.tools.keys()){let existingOwner=toolOwners.get(toolName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Tool "${toolName}" conflicts with ${existingOwner}`}):toolOwners.set(toolName,ext2.path)}for(let flagName of ext2.flags.keys()){let existingOwner=flagOwners.get(flagName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Flag "--${flagName}" conflicts with ${existingOwner}`}):flagOwners.set(flagName,ext2.path)}}return conflicts}};import{constants as constants7,copyFileSync,existsSync as existsSync19,mkdirSync as mkdirSync9}from"node:fs";import{basename as basename11,join as join30,parse as parse4,resolve as resolve10}from"node:path";import{existsSync as existsSync18}from"node:fs";function getMissingSessionCwdIssue(sessionManager,fallbackCwd){let sessionFile=sessionManager.getSessionFile();if(!sessionFile)return;let sessionCwd=sessionManager.getCwd();if(!(!sessionCwd||existsSync18(sessionCwd)))return{sessionFile,sessionCwd,fallbackCwd}}function formatMissingSessionCwdError(issue){let sessionFile=issue.sessionFile?`
|
|
1297
|
+
${args}`:skillBlock}catch(err2){return this._extensionRunner.emitError({extensionPath:skill.filePath,event:"skill_expansion",error:err2 instanceof Error?err2.message:String(err2)}),text2}}async _queueUserInput(text2,images,behavior,source){text2.startsWith("/")&&this._throwIfExtensionCommand(text2);let processedInput=await this._runInputHandlers(text2,images,source,this.isStreaming?behavior:void 0);if(!processedInput)return;let expandedText=this._expandSkillCommand(processedInput.text);expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates]),behavior==="steer"?await this._queueSteer(expandedText,processedInput.images):await this._queueFollowUp(expandedText,processedInput.images)}async steer(text2,images,options){await this._queueUserInput(text2,images,"steer",options?.source??"interactive")}async followUp(text2,images,options){await this._queueUserInput(text2,images,"followUp",options?.source??"interactive")}async _queueSteer(text2,images){this._steeringMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.steer({role:"user",content,timestamp:Date.now()})}async _queueFollowUp(text2,images){this._followUpMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.followUp({role:"user",content,timestamp:Date.now()})}_throwIfExtensionCommand(text2){let spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);if(this._extensionRunner.getCommand(commandName))throw new Error(`Extension command "/${commandName}" cannot be queued. Use prompt() or execute the command when not streaming.`)}async sendCustomMessage(message,options){let appMessage={role:"custom",customType:message.customType,content:message.content??[],display:message.display,details:message.details,timestamp:Date.now()};if(options?.deliverAs==="nextTurn")this._pendingNextTurnMessages.push(appMessage);else if(this.isStreaming&&options?.triggerTurn!==!1)options?.deliverAs==="followUp"?this.agent.followUp(appMessage):this.agent.steer(appMessage);else if(options?.triggerTurn){if(this._isEmittingAgentSettled){this._deferredSettledActions.push(async()=>await this._runAgentPrompt(appMessage));return}await this._runAgentPrompt(appMessage)}else this.isStreaming?this._pendingCustomMessages.push(appMessage):this._appendCustomMessage(appMessage)}_appendCustomMessage(appMessage){this.sessionManager.appendCustomMessageEntry(appMessage.customType,appMessage.content,appMessage.display,appMessage.details),this._messagePersisted(appMessage),this._refreshFinalizedContext(),this._emit({type:"message_start",message:appMessage}),this._emit({type:"message_end",message:appMessage})}_flushPendingCustomMessages(){if(this._pendingCustomMessages.length===0)return;let pending=this._pendingCustomMessages;this._pendingCustomMessages=[];for(let appMessage of pending)this._appendCustomMessage(appMessage)}async sendUserMessage(content,options){let text2,images;if(typeof content=="string")text2=content;else{let textParts=[];images=[];for(let part of content)part.type==="text"?textParts.push(part.text):images.push(part);text2=textParts.join(`
|
|
1298
|
+
`),images.length===0&&(images=void 0)}await this.prompt(text2,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];return this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues(),this._backgroundHost.queueCleared(),this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._isAgentRunActive&&(this._agentRunAbortRequested=!0),this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this._isBeforeSettle&&(this._abortDuringBeforeSettle=!0),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source})}async setModel(model,options={}){if(!await this._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model);this.agent.state.model=model,this.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model.provider,model.id),this._addPersistedDefaultToNonEmptyScope(model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;this._scopedModels=[...this._scopedModels,{model}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||this.settingsManager.setEnabledModels([...enabledModels,modelReference])}async cycleModel(direction="forward",options={}){return this._scopedModels.length>0?this._cycleScopedModel(direction,options):this._cycleAvailableModel(direction,options)}async _cycleScopedModel(direction,options){let availableIds=new Set(this._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=this._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=this.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return this.agent.state.model=next.model,this.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),this._addPersistedDefaultToNonEmptyScope(next.model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:this.thinkingLevel,isScoped:!0}}async _cycleAvailableModel(direction,options){let availableModels=this._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=this.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(nextModel);return this.agent.state.model=nextModel,this.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),this._addPersistedDefaultToNonEmptyScope(nextModel)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:this.thinkingLevel,isScoped:!1}}setThinkingLevel(level,options={}){let availableLevels=this.getAvailableThinkingLevels(),effectiveLevel=availableLevels.includes(level)?level:this._clampThinkingLevel(level,availableLevels),previousLevel=this.agent.state.thinkingLevel,isChanging=effectiveLevel!==previousLevel;this.agent.state.thinkingLevel=effectiveLevel,options.persist&&this.settingsManager.setDefaultThinkingLevel(level),isChanging&&(this.sessionManager.appendThinkingLevelChange(effectiveLevel),this._emit({type:"thinking_level_changed",level:effectiveLevel}),this._extensionRunner.emit({type:"thinking_level_select",level:effectiveLevel,previousLevel}))}cycleThinkingLevel(options={}){if(!this.supportsThinking())return;let levels=this.getAvailableThinkingLevels(),nextIndex=(levels.indexOf(this.thinkingLevel)+1)%levels.length,nextLevel=levels[nextIndex];return this.setThinkingLevel(nextLevel,options),nextLevel}getAvailableThinkingLevels(){return this.model?getSupportedThinkingLevels(this.model):[...THINKING_LEVEL_OPTIONS]}supportsThinking(){return!!this.model?.reasoning}_getThinkingLevelForModelSwitch(targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=this.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return this.settingsManager.getDefaultThinkingLevel()??this.thinkingLevel??DEFAULT_THINKING_LEVEL}_clampThinkingLevel(level,_availableLevels){return this.model?clampThinkingLevel(this.model,level):"off"}syncQueueModesFromSettings(){this.agent.steeringMode=this.settingsManager.getSteeringMode(),this.agent.followUpMode=this.settingsManager.getFollowUpMode()}setSteeringMode(mode){this.agent.steeringMode=mode,this.settingsManager.setSteeringMode(mode)}setFollowUpMode(mode){this.agent.followUpMode=mode,this.settingsManager.setFollowUpMode(mode)}async _runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,signal,env2,reason){return compact2(preparation,requestModel,apiKey,headers,customInstructions,signal,this.thinkingLevel,this.agent.streamFunction,env2,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._withBackgroundPaused(()=>this._compactBody(customInstructions))}async _compactBody(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings2=this.settingsManager.getCompactionSettings(model),{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model,this._compactionAbortController.signal),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction2(pathEntries,settings2);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result2=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result2?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result2?.compaction&&(extensionCompaction=result2.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result2=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,this._compactionAbortController.signal,env2,"manual");summary=result2.summary,firstKeptEntryId=result2.firstKeptEntryId,tokensBefore=result2.tokensBefore,usage=result2.usage,details=result2.details}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason:"manual",willRetry:!1});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage6=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage6,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0,toolResults=[]){let settings2=this.settingsManager.getCompactionSettings(this.model);if(!settings2.enabled||skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let contextWindow=this.model?.contextWindow??0,sameModel=this.model&&assistantMessage.provider===this.model.provider&&assistantMessage.model===this.model.id,compactionEntry=getLatestCompactionEntry(this.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let currentProjection=this.sessionManager.buildSessionProjection(),assistantEntryId=this._findPersistedMessageEntryId(assistantMessage),assistantIsProjected=assistantEntryId===void 0||currentProjection.entries.some(entry=>entry.sourceEntry.id===assistantEntryId&&entry.messages.some(message=>message.role==="assistant")),branch=this.sessionManager.getBranch(),assistantIndex=assistantEntryId?branch.findIndex(entry=>entry.id===assistantEntryId):-1,entriesAfterAssistant=assistantIndex>=0?branch.slice(assistantIndex+1):[],hasPostAssistantContextEdit=entriesAfterAssistant.some(entry=>entry.type==="context_edit"),latestAssistantEdit=entriesAfterAssistant.filter(entry=>entry.type==="context_edit"&&entry.targetId===assistantEntryId).at(-1),assistantRetainedForExplicitRecovery=assistantEntryId===void 0||!entriesAfterAssistant.some(entry=>entry.type==="compaction")&&latestAssistantEdit?.replacement!==null,assistantUsageMatchesProjection=assistantIsProjected&&!hasPostAssistantContextEdit,explicitOverflow=assistantMessage.stopReason==="error"&&isContextOverflow(assistantMessage),contextOverflow=sameModel&&(explicitOverflow&&assistantRetainedForExplicitRecovery||assistantUsageMatchesProjection&&isContextOverflow(assistantMessage,contextWindow)),recoverableLength=sameModel&&assistantIsProjected&&isRecoverableLength(assistantMessage,this.model?.maxTokens??0);if(contextOverflow||recoverableLength){let willRetry=assistantMessage.stopReason!=="stop";if(!willRetry)return await this._runAutoCompaction("overflow",!1);if(this._overflowRecoveryAttempted){let errorMessage6=contextOverflow?"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.":"Truncated response recovery failed after one compact-and-retry attempt.";return this._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage6,aborted:!1,willRetry:!1,fromExtension:!1}),!1}return this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage,toolResults),await this._runAutoCompaction("overflow",willRetry)}let contextTokens,projection=currentProjection,hasContextEdits=projection.entries.some(entry=>entry.sourceEntry.type==="context_edit"),directContextTokens=assistantMessage.usage?calculateContextTokens2(assistantMessage.usage):0;if(hasContextEdits)contextTokens=estimateProjectedContextTokens(projection,branch).tokens;else if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens3(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact2(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){return this._withBackgroundPaused(()=>this._runAutoCompactionBody(reason,willRetry))}async _runAutoCompactionBody(reason,willRetry){let model=this.model,settings2=this.settingsManager.getCompactionSettings(model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction2(pathEntries,settings2);if(!preparation)return!1;abortController=new AbortController,this._autoCompactionAbortController=abortController,started=!0,this._emit({type:"compaction_start",reason}),abortController.signal.throwIfAborted();let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model,abortController.signal);abortController.signal.throwIfAborted();let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let extensionResult=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions:void 0,reason,willRetry,signal:abortController.signal});if(extensionResult?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");extensionResult?.compaction&&(extensionCompaction=extensionResult.compaction,fromExtension=!0)}abortController.signal.throwIfAborted();let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let compactResult=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,void 0,abortController.signal,env2,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry});let result2={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result:result2,aborted:!1,willRetry}),willRetry?!0:this.agent.hasQueuedMessages()}catch(error){let message=error instanceof Error?error.message:"compaction failed",aborted=abortController?.signal.aborted===!0||cancelledByExtension;if(started){let errorMessage6=aborted?void 0:reason==="overflow"?`Context overflow recovery failed: ${message}`:`Auto-compaction failed: ${message}`;this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage6}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage6,aborted,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController===abortController&&(this._autoCompactionAbortController=void 0),this._resolveIdleWaitIfIdle()}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){return this._withBackgroundPaused(()=>this._bindExtensionsBody(bindings))}async _bindExtensionsBody(bindings){bindings.backgroundEnabled!==void 0&&this._backgroundHost.setEnabled(bindings.backgroundEnabled),bindings.uiContext!==void 0&&(this._extensionUIContext=bindings.uiContext),bindings.mode!==void 0&&(this._extensionMode=bindings.mode),bindings.commandContextActions!==void 0&&(this._extensionCommandContextActions=bindings.commandContextActions),bindings.abortHandler!==void 0&&(this._extensionAbortHandler=bindings.abortHandler),bindings.shutdownHandler!==void 0&&(this._extensionShutdownHandler=bindings.shutdownHandler),bindings.onError!==void 0&&(this._extensionErrorListener=bindings.onError),this._applyExtensionBindings(this._extensionRunner),await this._extensionRunner.emit(this._sessionStartEvent),await this.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup")}async extendResourcesFromExtensions(reason){if(!this._extensionRunner.hasHandlers("resources_discover"))return;let{skillPaths,promptPaths,themePaths}=await this._extensionRunner.emitResourcesDiscover(this._cwd,reason);if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:this.buildExtensionResourcePaths(skillPaths),promptPaths:this.buildExtensionResourcePaths(promptPaths),themePaths:this.buildExtensionResourcePaths(themePaths)};this._resourceLoader.extendResources(extensionPaths),this._rebuildSystemPrompt(this.getActiveToolNames())}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source=this.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename9(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(err2=>{runner.emitError({extensionPath:"<runtime>",event:"send_message",error:err2 instanceof Error?err2.message:String(err2)})})},sendUserMessage:(content,options)=>{this.sendUserMessage(content,options).catch(err2=>{runner.emitError({extensionPath:"<runtime>",event:"send_user_message",error:err2 instanceof Error?err2.message:String(err2)})})},appendEntry:(customType,data)=>{let entryId=this.sessionManager.appendCustomEntry(customType,data),entry=this.sessionManager.getEntry(entryId);entry&&this._emit({type:"entry_appended",entry})},setSessionName:name=>{this.setSessionName(name)},getSessionName:()=>this.sessionManager.getSessionName(),setLabel:(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label)},getActiveTools:()=>this.getActiveToolNames(),getAllTools:()=>this.getAllTools(),setActiveTools:toolNames=>this.setActiveToolsByName(toolNames),refreshTools:()=>this._refreshToolRegistry(),getCommands,setModel:async model=>this._modelRuntime.hasConfiguredAuth(model.provider)?(await this.setModel(model),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{getBackground:()=>this.background,getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),getContextSnapshot:()=>this.getContextSnapshot(),compact:options=>{(async()=>{try{let result2=await this.compact(options?.customInstructions);options?.onComplete?.(result2)}catch(error){let err2=error instanceof Error?error:new Error(String(error));options?.onError?.(err2)}})()},getSystemPrompt:()=>this.systemPrompt,getSystemPromptOptions:()=>this._baseSystemPromptOptions},{registerProvider:(name,config)=>{this._modelRuntime.registerProvider(name,config),this._refreshCurrentModelFromRegistry()},registerNativeProvider:provider=>{this._modelRuntime.registerNativeProvider(provider),this._refreshCurrentModelFromRegistry()},unregisterProvider:name=>{this._modelRuntime.unregisterProvider(name),this._refreshCurrentModelFromRegistry()}})}_refreshToolRegistry(options){let previousRegistryNames=new Set(this._toolRegistry.keys()),previousActiveToolNames=this.getActiveToolNames(),allowedToolNames=this._allowedToolNames,excludedToolNames=this._excludedToolNames,isAllowedTool=name=>(!allowedToolNames||allowedToolNames.has(name))&&!excludedToolNames?.has(name),allCustomTools=[...this._extensionRunner.getAllRegisteredTools(),...this._customTools.map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<sdk:${definition.name}>`,{source:"sdk"})}))].filter(tool=>isAllowedTool(tool.definition.name)),definitionRegistry=new Map(Array.from(this._baseToolDefinitions.entries()).filter(([name])=>isAllowedTool(name)).map(([name,definition])=>[name,{definition,sourceInfo:createSyntheticSourceInfo(`<builtin:${name}>`,{source:"builtin"})}]));for(let tool of allCustomTools)definitionRegistry.set(tool.definition.name,{definition:tool.definition,sourceInfo:tool.sourceInfo});this._toolDefinitions=definitionRegistry,this._toolPromptSnippets=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let snippet=this._normalizePromptSnippet(definition.promptSnippet);return snippet?[definition.name,snippet]:void 0}).filter(entry=>entry!==void 0)),this._toolPromptGuidelines=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let guidelines=this._normalizePromptGuidelines(definition.promptGuidelines);return guidelines.length>0?[definition.name,guidelines]:void 0}).filter(entry=>entry!==void 0));let runner=this._extensionRunner,wrappedExtensionTools=wrapRegisteredTools(allCustomTools,runner),wrappedBuiltInTools=wrapRegisteredTools(Array.from(this._baseToolDefinitions.values()).filter(definition=>isAllowedTool(definition.name)).map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<builtin:${definition.name}>`,{source:"builtin"})})),runner),toolRegistry=new Map(wrappedBuiltInTools.map(tool=>[tool.name,tool]));for(let tool of wrappedExtensionTools)toolRegistry.set(tool.name,tool);this._toolRegistry=toolRegistry;let nextActiveToolNames=(options?.activeToolNames?[...options.activeToolNames]:[...previousActiveToolNames]).filter(name=>isAllowedTool(name));if(allowedToolNames)for(let toolName of this._toolRegistry.keys())allowedToolNames.has(toolName)&&nextActiveToolNames.push(toolName);else if(options?.includeAllExtensionTools)for(let tool of wrappedExtensionTools)nextActiveToolNames.push(tool.name);else if(!options?.activeToolNames)for(let toolName of this._toolRegistry.keys())previousRegistryNames.has(toolName)||nextActiveToolNames.push(toolName);this.setActiveToolsByName([...new Set(nextActiveToolNames)])}_buildRuntime(options){let autoResizeImages=this.settingsManager.getImageAutoResize(),shellCommandPrefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),baseToolDefinitions=this._baseToolsOverride?Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name,tool])=>[name,createToolDefinitionFromAgentTool(tool)])):createAllToolDefinitions(this._cwd,{read:{autoResizeImages},bash:{commandPrefix:shellCommandPrefix,shellPath}});this._baseToolDefinitions=new Map(Object.entries(baseToolDefinitions).map(([name,tool])=>[name,tool]));let extensionsResult=this._resourceLoader.getExtensions();if(options.flagValues)for(let[name,value2]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value2);this._extensionRunner=new ExtensionRunner(extensionsResult.extensions,extensionsResult.runtime,this._cwd,this.sessionManager,new ModelRegistry(this._modelRuntime)),this._extensionRunnerRef&&(this._extensionRunnerRef.current=this._extensionRunner),this._bindExtensionCore(this._extensionRunner),this._applyExtensionBindings(this._extensionRunner);let defaultActiveToolNames=this._baseToolsOverride?Object.keys(this._baseToolsOverride):["read","bash","edit","write"],baseActiveToolNames=options.activeToolNames??defaultActiveToolNames;this._refreshToolRegistry({activeToolNames:baseActiveToolNames,includeAllExtensionTools:options.includeAllExtensionTools})}async reload(options){return this._withBackgroundPaused(()=>this._reloadBody(options))}async _reloadBody(options){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();this.background.close(),await Promise.all([this.background.shutdown(),this.abort()]),await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate(),await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._backgroundHost.replaceService(),this._buildRuntime({activeToolNames:this.getActiveToolNames(),flagValues:previousFlagValues,includeAllExtensionTools:!0}),(this.background.enabled||this._extensionUIContext||this._extensionCommandContextActions||this._extensionShutdownHandler||this._extensionErrorListener)&&(await options?.beforeSessionStart?.(),await this._extensionRunner.emit({type:"session_start",reason:"reload"}),await this.extendResourcesFromExtensions("reload"))}_isRetryableError(message){return isContextOverflow(message,this.model?.contextWindow??0)?!1:isRetryableAssistantError(message)}_summarizationRetryCallbacks(source){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage6)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage6})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}_finishCancelledRetry(){if(this._retryAttempt===0)return;let attempt2=this._retryAttempt;this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"})}async _prepareRetry(message){let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings2.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings2,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep3(delayMs,this._retryAbortController.signal)}catch{return this._finishCancelledRetry(),!1}finally{this._retryAbortController=void 0}return!0}abortRetry(){this._retryAbortController?.abort()}get isRetrying(){return this._retryAbortController!==void 0}get autoRetryEnabled(){return this.settingsManager.getRetryEnabled()}setAutoRetryEnabled(enabled){this.settingsManager.setRetryEnabled(enabled)}async executeBash(command,onChunk,options){let abortController=new AbortController;this._bashAbortControllers.add(abortController);let prefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),resolvedCommand=prefix?`${prefix}
|
|
1299
|
+
${command}`:command;try{let result2=await executeBashWithOperations(resolvedCommand,this.sessionManager.getCwd(),options?.operations??createLocalBashOperations({shellPath}),{onChunk:delta=>{onChunk?.(delta),this._emit({type:"bash_execution_update",id:options?.id,delta})},signal:abortController.signal});return this.recordBashResult(command,result2,options),result2}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result2,options){let bashMessage={role:"bashExecution",command,output:result2.output,exitCode:result2.exitCode,cancelled:result2.cancelled,truncated:result2.truncated,fullOutputPath:result2.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.sessionManager.appendMessage(bashMessage),this._refreshFinalizedContext())}abortBash(){for(let abortController of[...this._bashAbortControllers])abortController.abort()}get isBashRunning(){return this._bashAbortControllers.size>0}get hasPendingBashMessages(){return this._pendingBashMessages.length>0}_flushPendingBashMessages(){if(this._pendingBashMessages.length!==0){for(let bashMessage of this._pendingBashMessages)this.sessionManager.appendMessage(bashMessage);this._pendingBashMessages=[],this._refreshFinalizedContext()}}setSessionName(name){this.sessionManager.appendSessionInfo(name);let event={type:"session_info_changed",name:this.sessionManager.getSessionName()};this._emit(event),this._extensionRunner.emit(event)}async navigateTree(targetId,options={}){if(this.isStreaming)throw new Error("Wait for the current response to finish before navigating the session tree.");if(this.isCompacting)throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");let oldLeafId=this.sessionManager.getLeafId();if(targetId===oldLeafId)return{cancelled:!1};if(options.summarize&&!this.model)throw new Error("No model available for summarization");let targetEntry=this.sessionManager.getEntry(targetId);if(!targetEntry)throw new Error(`Entry ${targetId} not found`);let{entries:entriesToSummarize,commonAncestorId}=collectEntriesForBranchSummary2(this.sessionManager,oldLeafId,targetId),customInstructions=options.customInstructions,replaceInstructions=options.replaceInstructions,label=options.label,preparation={targetId,oldLeafId,commonAncestorId,entriesToSummarize,userWantsSummary:options.summarize??!1,customInstructions,replaceInstructions,label},resumeBackground=this.pauseBackgroundNotifications();this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result2=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result2?.cancel)return{cancelled:!0};result2?.summary&&options.summarize&&(extensionSummary=result2.summary,fromExtension=!0),result2?.customInstructions!==void 0&&(customInstructions=result2.customInstructions),result2?.replaceInstructions!==void 0&&(replaceInstructions=result2.replaceInstructions),result2?.label!==void 0&&(label=result2.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let model=this.model,{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model),branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result2=await generateBranchSummary2(entriesToSummarize,{model:requestModel,apiKey,headers,env:env2,signal:this._branchSummaryAbortController.signal,customInstructions,replaceInstructions,reserveTokens:branchSummarySettings.reserveTokens,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),callbacks:this._summarizationRetryCallbacks({source:"branchSummary"})});if(result2.aborted)return{cancelled:!0,aborted:!0};if(result2.error)throw new Error(result2.error);summaryText=result2.summary,summaryUsage=result2.usage,summaryDetails={readFiles:result2.readFiles||[],modifiedFiles:result2.modifiedFiles||[]}}else extensionSummary&&(summaryText=extensionSummary.summary,summaryDetails=extensionSummary.details,summaryUsage=extensionSummary.usage);let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId,await this.background.cancelOutsideBranch(new Set(newLeafId===null?[]:this.sessionManager.getBranch(newLeafId).map(entry=>entry.id)));let summaryEntry;if(summaryText){let summaryId=this.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,fromExtension,summaryUsage);summaryEntry=this.sessionManager.getEntry(summaryId),label&&this.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?this.sessionManager.resetLeaf():this.sessionManager.branch(newLeafId);return label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label),this._backgroundHost.restoreHistory(),this._refreshFinalizedContext(),this._restoreToolsFromTranscript(),await this._extensionRunner.emit({type:"session_tree",newLeafId:this.sessionManager.getLeafId(),oldLeafId,summaryEntry,fromExtension:summaryText?fromExtension:void 0}),{editorText,cancelled:!1,summaryEntry}}finally{this._branchSummaryAbortController=void 0,this._resolveIdleWaitIfIdle(),resumeBackground()}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result2=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text2=contentText(entry.message.content,"");text2&&result2.push({entryId:entry.id,text:text2})}return result2}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals(),entries=this.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries){if(entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++;else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c=>c.type==="toolCall").length)}}return{sessionFile:this.sessionFile,sessionId:this.sessionId,userMessages,assistantMessages,toolCalls,toolResults,totalMessages,tokens:{input:usageTotals.input,output:usageTotals.output,cacheRead:usageTotals.cacheRead,cacheWrite:usageTotals.cacheWrite,total:usageTotals.input+usageTotals.output+usageTotals.cacheRead+usageTotals.cacheWrite},cost:usageTotals.cost,contextUsage:this.getContextUsage()}}getContextUsage(){let model=this.model;if(!model)return;let contextWindow=model.contextWindow??0;if(contextWindow<=0)return;let projection=this.sessionManager.buildSessionProjection(),branch=this.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branch);if(latestCompaction){let projectedAssistants=new Set(projection.entries.flatMap(entry=>entry.messages.some(message=>message.role==="assistant"&&message.stopReason!=="aborted"&&message.stopReason!=="error"&&calculateContextTokens2(message.usage)>0)?[entry.sourceEntry.id]:[])),compactionIndex=branch.findIndex(entry=>entry.id===latestCompaction.id);if(!branch.slice(compactionIndex+1).some(entry=>projectedAssistants.has(entry.id)))return{tokens:null,contextWindow,percent:null}}let estimate=estimateProjectedContextTokens(projection,branch),percent=estimate.tokens/contextWindow*100;return{tokens:estimate.tokens,contextWindow,percent}}async exportToHtml(outputPath,options={}){let themeName=[options.themeName,this.settingsManager.getTheme()].find(candidate=>candidate!==void 0&&getThemeByName(candidate)!==void 0),toolRenderer=createToolHtmlRenderer({getToolDefinition:name=>this.getToolDefinition(name),theme,cwd:this.sessionManager.getCwd()});return await exportSessionToHtml(this.sessionManager,this.state,{outputPath,themeName,toolRenderer})}exportToJsonl(outputPath){return exportSessionToJsonl(this.sessionManager,outputPath)}async summarizeForBugReport(options){let model=this.model;if(!model)throw new Error("No model selected");let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model);return generateBugReportSummary({messages:this.messages,hint:options.hint,model:requestModel,apiKey,headers,env:env2,signal:options.signal,thinkingLevel:this.thinkingLevel,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),sessionId:this.sessionId})}getLastAssistantText(){let lastAssistant=this.messages.slice().reverse().find(m2=>{if(m2.role!=="assistant")return!1;let msg=m2;return!(msg.stopReason==="aborted"&&msg.content.length===0)});if(!lastAssistant)return;let text2="";for(let content of lastAssistant.content)content.type==="text"&&(text2+=content.text);return text2.trim()||void 0}createReplacedSessionContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()));return context.sendMessage=(message,options)=>this.sendCustomMessage(message,options),context.sendUserMessage=(content,options)=>this.sendUserMessage(content,options),context}hasExtensionHandlers(eventType){return this._extensionRunner.hasHandlers(eventType)}get extensionRunner(){return this._extensionRunner}};import{join as join31}from"node:path";var MAX_WARMING_AGE_MS=60*6e4,MAX_IDLE_WARMING_AGE_MS=30*6e4,CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS=.05,IDLE_CONTINUATION_PROBABILITY=.15;function getCacheWarmingDelayMs(ttlMs){if(!(ttlMs<=1e4))return Math.max(1,Math.floor(Math.min(ttlMs*.9,ttlMs-1e4)))}function getPromptCacheTtlMs(model,options){let retention=options?.cacheRetention??(getProviderEnvValue("PI_CACHE_RETENTION",options?.env)==="long"?"long":"short");if(retention==="none")return;let seconds=model.promptCache?.[retention];return seconds===void 0?void 0:seconds*1e3}function isReplayable(model,options){return!options?.reasoning||model.api!=="anthropic-messages"?!0:model.compat?.forceAdaptiveThinking===!0}function lastPromptTokens(entries){for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type==="message"&&entry.message.role==="assistant"){let usage=entry.message.usage;return usage.input+usage.cacheRead+usage.cacheWrite}}return 0}function price(model,tokens2){let usage={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},...tokens2};return calculateCost(model,usage).total}var CacheWarmer=class{constructor(models,sessionManager,getMode,decide=async event=>event.action){this.models=models,this.sessionManager=sessionManager,this.getMode=getMode,this.decide=decide,this.inactive={state:"inactive",reason:"waiting for first request"}}get status(){if(this.getMode()==="off")return{state:"inactive",reason:"cache warming disabled"};let run=this.run;if(!run)return this.inactive;if(!run.isCurrent())return{state:"inactive",reason:"conversation context changed"};let decision=this.evaluate(run),refreshing=run.timer===void 0;return!decision.economicsAvailable&&!refreshing?{state:"inactive",reason:"cache economics unavailable"}:{state:refreshing?"refreshing":"scheduled",nextWarmAt:run.nextWarmAt,decision,extensionOverride:run.extensionOverride}}start(request,isCurrent){if(this.clearRun(),this.getMode()==="off"){this.stop("cache warming disabled");return}if(!isReplayable(request.model,request.options)){this.stop("request cannot be replayed safely");return}let ttlMs=getPromptCacheTtlMs(request.model,request.options);if(ttlMs===void 0){this.stop(request.options.cacheRetention==="none"?"request disabled prompt caching":"cache lifetime unavailable");return}let delayMs=getCacheWarmingDelayMs(ttlMs);if(delayMs===void 0){this.stop("cache lifetime unavailable");return}this.run={...request,isCurrent,ttlMs,delayMs,refreshDeadlineAt:0,startedAt:Date.now(),controller:new AbortController,phase:"streaming",nextWarmAt:0,extensionOverride:!1},this.schedule(this.run)}onAgentSettled(){let run=this.run;if(!run)return;if(this.getMode()==="streaming"){this.stop("agent run settled");return}run.phase="idle";let deadline=run.startedAt+MAX_IDLE_WARMING_AGE_MS;(run.nextWarmAt>deadline||Date.now()>=deadline)&&this.stop("30-minute idle safety limit reached")}onModeChanged(){let run=this.run;if(!run)return;let reason=this.getModeStopReason(run);reason&&this.stop(reason)}cancel(){this.stop("inactive")}clearRun(){let run=this.run;run&&(this.run=void 0,run.timer&&clearTimeout(run.timer),run.controller.abort())}stop(reason,stopped){this.clearRun(),this.inactive={state:"inactive",reason,...stopped}}schedule(run){run.extensionOverride=!1,run.nextWarmAt=Date.now()+run.delayMs,run.refreshDeadlineAt=run.nextWarmAt+Math.floor((run.ttlMs-run.delayMs)/2);let deadline=run.startedAt+(run.phase==="idle"?MAX_IDLE_WARMING_AGE_MS:MAX_WARMING_AGE_MS);if(run.nextWarmAt>deadline||Date.now()>=deadline){this.stop(run.phase==="idle"?"30-minute idle safety limit reached":"one-hour safety limit reached");return}run.timer=setTimeout(()=>{this.refresh(run)},Math.max(0,run.nextWarmAt-Date.now())),run.timer.unref?.()}async refresh(run){if(run.timer=void 0,!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let decision=this.evaluate(run),{warmCost,missCost,continuationProbability}=decision,action=decision.action;try{action=await this.decide({type:"cache_warming_decision",warmCost,missCost,continuationProbability,action})}catch{}if(!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let extensionOverride=action!==decision.action;if(action==="stop"){let reason=extensionOverride?"stopped by extension":decision.economicsAvailable?"expected savings below threshold":"cache economics unavailable";this.stop(reason,{decision,extensionOverride});return}run.extensionOverride=extensionOverride;try{let message=await this.models.streamSimple(run.model,run.context,{...run.options,maxTokens:1,maxRetries:0,signal:run.controller.signal}).result();if(!this.validateRun(run))return;if(message.stopReason!=="error"&&message.stopReason!=="aborted"){let entry=this.sessionManager.appendUsage("cache_warm",message.provider,message.responseModel??message.model,message.usage,extensionOverride?"extension override":void 0);this.onWarmed?.(entry)}}catch{}this.run===run&&this.schedule(run)}refreshDeadlineMissed(run){return Date.now()<=run.refreshDeadlineAt?!1:(this.stop("cache refresh deadline missed"),!0)}validateRun(run){if(this.run!==run)return!1;let reason=this.getModeStopReason(run)??(run.isCurrent()?void 0:"conversation context changed");return reason?(this.stop(reason),!1):!0}getModeStopReason(run){let mode=this.getMode();if(mode==="off")return"cache warming disabled";if(mode==="streaming"&&run.phase==="idle")return"agent run settled"}evaluate(run){let model=run.model,promptTokens=lastPromptTokens(this.sessionManager.getBranch()),cacheHitCost=price(model,{cacheRead:promptTokens}),cacheMissCost=price(model,model.cost.cacheWrite>0?{cacheWrite:promptTokens}:{input:promptTokens}),warmCost=price(model,{cacheRead:promptTokens,output:1}),missCost=Math.max(0,cacheMissCost-cacheHitCost),continuationProbability=run.phase==="idle"?IDLE_CONTINUATION_PROBABILITY:1,economicsAvailable=promptTokens>0&&(cacheHitCost>0||cacheMissCost>0),expectedSavings=continuationProbability*missCost-warmCost;return{phase:run.phase,warmCost,missCost,continuationProbability,expectedSavings,economicsAvailable,action:expectedSavings>=CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS?"warm":"stop"}}};function formatDollars(value2){return value2<0?`-$${Math.abs(value2).toFixed(3)}`:`$${value2.toFixed(3)}`}function formatCacheWarmingEconomics(decision){if(!decision.economicsAvailable)return"cache economics unavailable";let probability=Math.round(decision.continuationProbability*100),probabilityText=decision.phase==="streaming"?`${probability}% continuation probability while agent is running`:`${probability}% continuation probability`,comparison=decision.action==="warm"?">=":"<";return`${probabilityText}, expected savings ${formatDollars(decision.expectedSavings)} ${comparison} $${CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS.toFixed(3)}`}function formatCacheWarmingDecisionTime(nextWarmAt,now){if(nextWarmAt===void 0||nextWarmAt<=now)return"Decision now";let remainingSeconds=Math.ceil((nextWarmAt-now)/1e3),hours=Math.floor(remainingSeconds/3600);remainingSeconds%=3600;let minutes=Math.floor(remainingSeconds/60),seconds=remainingSeconds%60,parts=[];return hours>0&&parts.push(`${hours}h`),minutes>0&&parts.push(`${minutes}m`),(seconds>0||parts.length===0)&&parts.push(`${seconds}s`),`Decision in ${parts.join(" ")}`}function formatCacheWarmingStatus(status,now=Date.now()){let decision=status.decision;if(!decision||status.state==="inactive"&&!decision.economicsAvailable&&!status.extensionOverride)return`Inactive (${status.reason??"unknown reason"})`;let details=status.extensionOverride?`extension override, ${formatCacheWarmingEconomics(decision)}`:`${formatCacheWarmingEconomics(decision)} -> ${decision.action}`;return status.state==="inactive"?`Stopped (${details})`:status.state==="refreshing"?`Warming cache (${details})`:`${formatCacheWarmingDecisionTime(status.nextWarmAt,now)} (${details})`}function formatCacheWarmingUsage(entry){let note=entry.note?` (${entry.note})`:"",cost=entry.usage.cost.total.toFixed(6).replace(/(\.\d{3}\d*?)0+$/,"$1");return`Cache warmed${note}: $${cost}`}import{isDeepStrictEqual}from"node:util";var ContextSnapshotCapture=class{constructor(settings2,runnerRef,buildRequestOptions){this.pending=new WeakMap,this.settings=settings2,this.runnerRef=runnerRef,this.buildRequestOptions=buildRequestOptions}install(agent){this.agent=agent;let transform=agent.transformContext;agent.transformContext=async(messages,signal)=>{let runner=this.runnerRef.current,source={messages:structuredClone(messages),runner},transformed=transform?await transform(messages,signal):messages;return this.pending.set(transformed,source),transformed};let convert=agent.convertToLlm,record=(messages,converted)=>{let source=this.pending.get(messages);return source&&(this.pending.delete(messages),this.prepared={source,messages:structuredClone(converted),blockImages:this.settings.getBlockImages()}),converted};agent.convertToLlm=messages=>{let converted=convert(messages);return Array.isArray(converted)?record(messages,converted):converted.then(all=>record(messages,all))}}resolveStreamOptions(model,options){return this.buildRequestOptions(model,options)}async prepareMessages(messages){let agent=this.agent;if(!agent)throw new Error("Context snapshot capture is not installed");let runner=this.runnerRef.current,blockImages=this.settings.getBlockImages(),prepared=this.prepared;if(prepared&&prepared.source.runner===runner&&prepared.blockImages===blockImages&&isDeepStrictEqual(messages.slice(0,prepared.source.messages.length),prepared.source.messages))return[...structuredClone(prepared.messages),...await agent.convertToLlm(messages.slice(prepared.source.messages.length))];let transformed=runner?await runner.emitContext(messages):messages;return structuredClone(await agent.convertToLlm(transformed))}};function isTruthyEnvFlag(value2){return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}function isInstallTelemetryEnabled(settingsManager,telemetryEnv=process.env.PI_TELEMETRY){return telemetryEnv!==void 0?isTruthyEnvFlag(telemetryEnv):settingsManager.getEnableInstallTelemetry()}var OPENROUTER_HOST="openrouter.ai",NVIDIA_NIM_HOST="integrate.api.nvidia.com",CLOUDFLARE_API_HOST="api.cloudflare.com",CLOUDFLARE_AI_GATEWAY_HOST="gateway.ai.cloudflare.com",OPENCODE_HOST="opencode.ai";function matchesHost(baseUrl,expectedHost){try{return new URL(baseUrl).hostname===expectedHost}catch{return!1}}function isOpenRouterModel(model){return model.provider==="openrouter"||model.baseUrl.includes(OPENROUTER_HOST)}function isNvidiaNimModel(model){return model.provider==="nvidia"||matchesHost(model.baseUrl,NVIDIA_NIM_HOST)}function isCloudflareModel(model){return model.provider==="cloudflare-workers-ai"||model.provider==="cloudflare-ai-gateway"||matchesHost(model.baseUrl,CLOUDFLARE_API_HOST)||matchesHost(model.baseUrl,CLOUDFLARE_AI_GATEWAY_HOST)}function getDefaultAttributionHeaders(model,settingsManager){if(isInstallTelemetryEnabled(settingsManager)){if(isOpenRouterModel(model))return{"HTTP-Referer":"https://pi.dev","X-OpenRouter-Title":"pi","X-OpenRouter-Categories":"cli-agent"};if(isNvidiaNimModel(model))return{"X-BILLING-INVOKE-ORIGIN":"Pi"};if(isCloudflareModel(model))return{"User-Agent":"pi-coding-agent"}}}function getSessionHeaders(model,sessionId){if(sessionId&&!(model.provider!=="opencode"&&model.provider!=="opencode-go"&&!matchesHost(model.baseUrl,OPENCODE_HOST)))return{"x-opencode-session":sessionId,"x-opencode-client":"pi"}}function mergeProviderAttributionHeaders(model,settingsManager,sessionId,...headerSources){let merged={...getSessionHeaders(model,sessionId),...getDefaultAttributionHeaders(model,settingsManager)};for(let headers of headerSources)headers&&Object.assign(merged,headers);return Object.keys(merged).length>0?merged:void 0}import{existsSync as existsSync17,readdirSync as readdirSync9,readFileSync as readFileSync13,statSync as statSync11}from"node:fs";import{basename as basename10,dirname as dirname19,join as join28,resolve as resolve9,sep as sep9}from"node:path";import{statSync as statSync9}from"node:fs";import{homedir as homedir8,userInfo}from"node:os";import{isAbsolute as isAbsolute4,join as join26,relative as relative5,sep as sep8}from"node:path";function samePath(left,right){return left!==void 0&&relative5(canonicalizePath(left),canonicalizePath(right))===""}function isPathInside(parent,child){let relativePath=relative5(canonicalizePath(parent),canonicalizePath(child));return relativePath!==""&&relativePath!==".."&&!relativePath.startsWith(`..${sep8}`)&&!isAbsolute4(relativePath)}function pathKey(value2){let normalized=canonicalizePath(resolvePath(value2));return process.platform==="win32"?normalized.replace(/^([A-Z]):/,(_2,drive)=>`${drive.toLowerCase()}:`):normalized}function fileIdentity(value2){try{let stats=statSync9(value2,{bigint:!0});return stats.ino===0n?void 0:`${stats.dev}:${stats.ino}`}catch{return}}function referToSameLocation(left,right){let leftKey=pathKey(left),rightKey=pathKey(right);if(leftKey===rightKey)return!0;if(process.platform!=="win32")return!1;let leftIdentity=fileIdentity(leftKey);return leftIdentity!==void 0&&leftIdentity===fileIdentity(rightKey)}function findPathKeys(record,path14){return process.platform!=="win32"?Object.hasOwn(record,path14)?[path14]:[]:Object.keys(record).filter(key=>referToSameLocation(key,path14))}function userAgentsSkillsDirMatcher(){let homes=[process.env.HOME||homedir8()];try{homes.push(userInfo().homedir)}catch{}let skillDirs=homes.map(home=>join26(pathKey(home),".agents","skills"));return dir=>skillDirs.some(skillDir=>referToSameLocation(skillDir,dir))}import{execFile,spawnSync as spawnSync5}from"child_process";import{existsSync as existsSync16,readFileSync as readFileSync12,statSync as statSync10,unwatchFile,watchFile}from"fs";import{dirname as dirname18,join as join27,resolve as resolve8}from"path";function findGitPaths(cwd){let dir=cwd;for(;;){let gitPath=join27(dir,".git");if(existsSync16(gitPath))try{let stat3=statSync10(gitPath);if(stat3.isFile()){let content=readFileSync12(gitPath,"utf8").trim();if(content.startsWith("gitdir: ")){let gitDir=resolve8(dir,content.slice(8).trim()),headPath=join27(gitDir,"HEAD");if(!existsSync16(headPath))return null;let commonDirPath=join27(gitDir,"commondir"),commonGitDir=existsSync16(commonDirPath)?resolve8(gitDir,readFileSync12(commonDirPath,"utf8").trim()):gitDir;return{repoDir:dir,commonGitDir,headPath}}}else if(stat3.isDirectory()){let headPath=join27(gitPath,"HEAD");return existsSync16(headPath)?{repoDir:dir,commonGitDir:gitPath,headPath}:null}}catch{return null}let parent=dirname18(dir);if(parent===dir)return null;dir=parent}}function resolveBranchWithGitSync(repoDir){let result2=spawnSync5("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8",stdio:["ignore","pipe","ignore"]});return(result2.status===0?result2.stdout.trim():"")||null}function resolveBranchWithGitAsync(repoDir){return new Promise(resolvePromise=>{execFile("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8"},(error,stdout)=>{if(error){resolvePromise(null);return}let branch=stdout.trim();resolvePromise(branch||null)})})}function isWslEnvironment(){return process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP)}function isWindowsMountedRepoPath(repoDir){return/^\/mnt\/[a-z](?:\/|$)/i.test(repoDir)}function shouldPollGitHead(repoDir){return isWslEnvironment()&&isWindowsMountedRepoPath(repoDir)}var FooterDataProvider=class _FooterDataProvider{static{this.WATCH_DEBOUNCE_MS=500}constructor(cwd){this.extensionStatuses=new Map,this.cachedBranch=void 0,this.gitPaths=void 0,this.headWatcher=null,this.headWatchFilePath=null,this.headWatchFileListener=null,this.reftableWatcher=null,this.reftableTablesListWatcher=null,this.reftableTablesListPath=null,this.branchChangeCallbacks=new Set,this.availableProviderCount=0,this.refreshTimer=null,this.gitWatcherRetryTimer=null,this.refreshInFlight=!1,this.refreshPending=!1,this.disposed=!1,this.cwd=cwd,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher()}getGitBranch(){return this.cachedBranch===void 0&&(this.cachedBranch=this.resolveGitBranchSync()),this.cachedBranch}getExtensionStatuses(){return this.extensionStatuses}onBranchChange(callback){return this.branchChangeCallbacks.add(callback),()=>this.branchChangeCallbacks.delete(callback)}setExtensionStatus(key,text2){text2===void 0?this.extensionStatuses.delete(key):this.extensionStatuses.set(key,text2)}clearExtensionStatuses(){this.extensionStatuses.clear()}getAvailableProviderCount(){return this.availableProviderCount}setAvailableProviderCount(count){this.availableProviderCount=count}setCwd(cwd){this.cwd!==cwd&&(this.cwd=cwd,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.cachedBranch=void 0,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher(),this.notifyBranchChange())}dispose(){this.disposed=!0,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.branchChangeCallbacks.clear()}notifyBranchChange(){for(let cb of this.branchChangeCallbacks)cb()}scheduleRefresh(){if(!(this.disposed||this.refreshTimer)){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.refreshGitBranchAsync()},_FooterDataProvider.WATCH_DEBOUNCE_MS)}}async refreshGitBranchAsync(){if(!this.disposed){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshInFlight=!0;try{let nextBranch=await this.resolveGitBranchAsync();if(this.disposed)return;if(this.cachedBranch!==void 0&&this.cachedBranch!==nextBranch){this.cachedBranch=nextBranch,this.notifyBranchChange();return}this.cachedBranch=nextBranch}finally{this.refreshInFlight=!1,this.refreshPending&&!this.disposed&&(this.refreshPending=!1,this.scheduleRefresh())}}}resolveGitBranchSync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?resolveBranchWithGitSync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}async resolveGitBranchAsync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?await resolveBranchWithGitAsync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}clearGitWatchers(){closeWatcher(this.headWatcher),this.headWatcher=null,this.headWatchFilePath&&this.headWatchFileListener&&(unwatchFile(this.headWatchFilePath,this.headWatchFileListener),this.headWatchFilePath=null,this.headWatchFileListener=null),closeWatcher(this.reftableWatcher),this.reftableWatcher=null,closeWatcher(this.reftableTablesListWatcher),this.reftableTablesListWatcher=null,this.reftableTablesListPath&&(unwatchFile(this.reftableTablesListPath),this.reftableTablesListPath=null),this.gitWatcherRetryTimer&&(clearTimeout(this.gitWatcherRetryTimer),this.gitWatcherRetryTimer=null)}scheduleGitWatcherRetry(){this.disposed||this.gitWatcherRetryTimer||(this.gitWatcherRetryTimer=setTimeout(()=>{this.gitWatcherRetryTimer=null,this.setupGitWatcher()},FS_WATCH_RETRY_DELAY_MS))}handleGitWatcherError(){this.clearGitWatchers(),this.scheduleGitWatcherRetry()}setupGitWatcher(){if(this.clearGitWatchers(),!this.gitPaths)return;let pollGitHead=shouldPollGitHead(this.gitPaths.repoDir);if(this.headWatcher=watchWithErrorHandler(dirname18(this.gitPaths.headPath),(_eventType,filename)=>{(!filename||filename==="HEAD")&&this.scheduleRefresh()},()=>this.handleGitWatcherError()),pollGitHead&&(this.headWatchFilePath=this.gitPaths.headPath,this.headWatchFileListener=(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()},watchFile(this.headWatchFilePath,{interval:1e3},this.headWatchFileListener)),!this.headWatcher&&!pollGitHead)return;let reftableDir=join27(this.gitPaths.commonGitDir,"reftable");if(existsSync16(reftableDir)){if(this.reftableWatcher=watchWithErrorHandler(reftableDir,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableWatcher)return;let tablesListPath=join27(reftableDir,"tables.list");if(existsSync16(tablesListPath)){if(this.reftableTablesListPath=tablesListPath,this.reftableTablesListWatcher=watchWithErrorHandler(tablesListPath,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableTablesListWatcher)return;watchFile(tablesListPath,{interval:250},(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()})}}}};function resolvePromptInput(input2,description){if(input2){if(existsSync17(input2))try{return stripBom(readFileSync13(input2,"utf-8"))}catch(error){return console.error(source_default.yellow(`Warning: Could not read ${description} file ${input2}: ${error}`)),input2}return input2}}function loadContextFileFromDir(dir){let candidates=["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"];for(let filename of candidates){let filePath=join28(dir,filename);if(existsSync17(filePath))try{if(!statSync11(filePath).isFile())continue;return{path:filePath,content:stripBom(readFileSync13(filePath,"utf-8"))}}catch(error){console.error(source_default.yellow(`Warning: Could not read ${filePath}: ${error}`))}}return null}function findShadowedContextFile(cwd){let gitPaths=findGitPaths(cwd);if(!gitPaths)return;let commonGitDir=canonicalizePath(gitPaths.commonGitDir),worktreeRoot=canonicalizePath(gitPaths.repoDir),mainRepoRoot=dirname19(commonGitDir);if(!isPathInside(mainRepoRoot,worktreeRoot)||!samePath(join28(mainRepoRoot,".git"),commonGitDir))return;let worktreeContextFile=loadContextFileFromDir(worktreeRoot);return worktreeContextFile?join28(mainRepoRoot,basename10(worktreeContextFile.path)):void 0}function loadProjectContextFiles(options){let resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(options.agentDir),contextFiles=[],seenPaths=new Set,globalContext=loadContextFileFromDir(resolvedAgentDir);globalContext&&(contextFiles.push(globalContext),seenPaths.add(globalContext.path));let ancestorContextFiles=[],shadowedContextFile=findShadowedContextFile(resolvedCwd),currentDir=resolvedCwd;for(;;){let contextFile=loadContextFileFromDir(currentDir),isShadowed=shadowedContextFile!==void 0&&samePath(contextFile?.path,shadowedContextFile);contextFile&&!isShadowed&&!seenPaths.has(contextFile.path)&&(ancestorContextFiles.unshift(contextFile),seenPaths.add(contextFile.path));let parentDir=dirname19(currentDir);if(parentDir===currentDir)break;currentDir=parentDir}return contextFiles.push(...ancestorContextFiles),contextFiles}var DefaultResourceLoader=class{constructor(options){this.cwd=resolvePath(options.cwd),this.agentDir=resolvePath(options.agentDir),this.settingsManager=options.settingsManager??SettingsManager.create(this.cwd,this.agentDir),this.eventBus=options.eventBus??createEventBus(),this.packageManager=new DefaultPackageManager({cwd:this.cwd,agentDir:this.agentDir,settingsManager:this.settingsManager}),this.additionalExtensionPaths=options.additionalExtensionPaths??[],this.additionalSkillPaths=options.additionalSkillPaths??[],this.additionalPromptTemplatePaths=options.additionalPromptTemplatePaths??[],this.additionalThemePaths=options.additionalThemePaths??[],this.extensionFactories=options.extensionFactories??[],this.noExtensions=options.noExtensions??!1,this.noSkills=options.noSkills??!1,this.noPromptTemplates=options.noPromptTemplates??!1,this.noThemes=options.noThemes??!1,this.noContextFiles=options.noContextFiles??!1,this.systemPromptSource=options.systemPrompt,this.appendSystemPromptSource=options.appendSystemPrompt,this.extensionsOverride=options.extensionsOverride,this.skillsOverride=options.skillsOverride,this.promptsOverride=options.promptsOverride,this.themesOverride=options.themesOverride,this.agentsFilesOverride=options.agentsFilesOverride,this.systemPromptOverride=options.systemPromptOverride,this.appendSystemPromptOverride=options.appendSystemPromptOverride,this.extensionsResult={extensions:[],errors:[],runtime:createExtensionRuntime()},this.skills=[],this.skillDiagnostics=[],this.prompts=[],this.promptDiagnostics=[],this.themes=[],this.themeDiagnostics=[],this.agentsFiles=[],this.appendSystemPrompt=[],this.appendSystemPromptSourcePaths=[],this.lastSkillPaths=[],this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map,this.resourceMetadataByPath=new Map,this.lastPromptPaths=[],this.lastThemePaths=[],this.loaded=!1}getExtensions(){return this.extensionsResult}getSkills(){return{skills:this.skills,diagnostics:this.skillDiagnostics}}getPrompts(){return{prompts:this.prompts,diagnostics:this.promptDiagnostics}}getThemes(){return{themes:this.themes,diagnostics:this.themeDiagnostics}}getAgentsFiles(){return{agentsFiles:this.agentsFiles}}getSystemPrompt(){return this.systemPrompt}getSystemPromptSource(){return this.systemPromptSourcePath?{path:this.systemPromptSourcePath}:void 0}getAppendSystemPrompt(){return this.appendSystemPrompt}getAppendSystemPromptSources(){return this.appendSystemPromptSourcePaths.map(path14=>({path:path14}))}extendResources(paths){let skillPaths=this.normalizeExtensionPaths(paths.skillPaths??[]),promptPaths=this.normalizeExtensionPaths(paths.promptPaths??[]),themePaths=this.normalizeExtensionPaths(paths.themePaths??[]);for(let entry of skillPaths)this.extensionSkillSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of promptPaths)this.extensionPromptSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of themePaths)this.extensionThemeSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));skillPaths.length>0&&(this.lastSkillPaths=this.mergePaths(this.lastSkillPaths,skillPaths.map(entry=>entry.path)),this.updateSkillsFromPaths(this.lastSkillPaths,this.resourceMetadataByPath)),promptPaths.length>0&&(this.lastPromptPaths=this.mergePaths(this.lastPromptPaths,promptPaths.map(entry=>entry.path)),this.updatePromptsFromPaths(this.lastPromptPaths,this.resourceMetadataByPath)),themePaths.length>0&&(this.lastThemePaths=this.mergePaths(this.lastThemePaths,themePaths.map(entry=>entry.path)),this.updateThemesFromPaths(this.lastThemePaths,this.resourceMetadataByPath))}async loadProjectTrustExtensions(){return this.settingsManager.setProjectTrusted(!1),await this.settingsManager.reload(),this.loadCurrentExtensionSet({includeInlineFactories:!0})}async reload(options){resetTimings("extensions"),this.loaded&&clearExtensionCache();let preTrustExtensions;if(options?.resolveProjectTrust){preTrustExtensions=await this.loadProjectTrustExtensions();let projectTrusted=await options.resolveProjectTrust({extensionsResult:preTrustExtensions});this.settingsManager.setProjectTrusted(projectTrusted)}await this.settingsManager.reload();let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0});this.resourceMetadataByPath=new Map;let metadataByPath=this.resourceMetadataByPath;this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map;let getEnabledResources=resources=>{for(let r of resources)metadataByPath.has(r.path)||metadataByPath.set(r.path,r.metadata);return resources.filter(r=>r.enabled)},getEnabledPaths=resources=>getEnabledResources(resources).map(r=>r.path),enabledExtensions=getEnabledPaths(resolvedPaths.extensions),enabledSkillResources=getEnabledResources(resolvedPaths.skills),enabledPrompts=getEnabledPaths(resolvedPaths.prompts),enabledThemes=getEnabledPaths(resolvedPaths.themes),enabledSkills=enabledSkillResources.map(resource=>this.mapSkillPath(resource,metadataByPath));for(let r of cliExtensionPaths.extensions)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});for(let r of cliExtensionPaths.skills)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});let cliEnabledExtensions=getEnabledPaths(cliExtensionPaths.extensions),cliEnabledSkills=getEnabledPaths(cliExtensionPaths.skills),cliEnabledPrompts=getEnabledPaths(cliExtensionPaths.prompts),cliEnabledThemes=getEnabledPaths(cliExtensionPaths.themes),extensionPaths=this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions),extensionsResult=await this.loadFinalExtensionSet(extensionPaths,preTrustExtensions);for(let p of this.additionalExtensionPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);existsSync17(resolved)||extensionsResult.errors.push({path:resolved,error:`Extension path does not exist: ${resolved}`})}this.extensionsResult=this.extensionsOverride?this.extensionsOverride(extensionsResult):extensionsResult,this.applyExtensionSourceInfo(this.extensionsResult.extensions,metadataByPath);let skillPaths=this.noSkills?this.mergePaths(cliEnabledSkills,this.additionalSkillPaths):this.mergePaths([...cliEnabledSkills,...enabledSkills],this.additionalSkillPaths);this.lastSkillPaths=skillPaths,this.updateSkillsFromPaths(skillPaths,metadataByPath);for(let p of this.additionalSkillPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.skillDiagnostics.some(d=>d.path===resolved)&&this.skillDiagnostics.push({type:"error",message:"Skill path does not exist",path:resolved})}let promptPaths=this.noPromptTemplates?this.mergePaths(cliEnabledPrompts,this.additionalPromptTemplatePaths):this.mergePaths([...cliEnabledPrompts,...enabledPrompts],this.additionalPromptTemplatePaths);this.lastPromptPaths=promptPaths,this.updatePromptsFromPaths(promptPaths,metadataByPath);for(let p of this.additionalPromptTemplatePaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.promptDiagnostics.some(d=>d.path===resolved)&&this.promptDiagnostics.push({type:"error",message:"Prompt template path does not exist",path:resolved})}let themePaths=this.noThemes?this.mergePaths(cliEnabledThemes,this.additionalThemePaths):this.mergePaths([...cliEnabledThemes,...enabledThemes],this.additionalThemePaths);this.lastThemePaths=themePaths,this.updateThemesFromPaths(themePaths,metadataByPath);for(let p of this.additionalThemePaths){let resolved=this.resolveResourcePath(p);!existsSync17(resolved)&&!this.themeDiagnostics.some(d=>d.path===resolved)&&this.themeDiagnostics.push({type:"error",message:"Theme path does not exist",path:resolved})}let agentsFiles={agentsFiles:this.noContextFiles?[]:loadProjectContextFiles({cwd:this.cwd,agentDir:this.agentDir})},resolvedAgentsFiles=this.agentsFilesOverride?this.agentsFilesOverride(agentsFiles):agentsFiles;this.agentsFiles=resolvedAgentsFiles.agentsFiles;let systemPromptSource=this.systemPromptSource??this.discoverSystemPromptFile(),baseSystemPrompt=resolvePromptInput(systemPromptSource,"system prompt");this.systemPrompt=this.systemPromptOverride?this.systemPromptOverride(baseSystemPrompt):baseSystemPrompt,this.systemPromptSourcePath=systemPromptSource&&existsSync17(systemPromptSource)?resolvePath(systemPromptSource):void 0;let appendSources=this.appendSystemPromptSource;if(!appendSources){let discoveredAppendSystemPromptFile=this.discoverAppendSystemPromptFile();appendSources=discoveredAppendSystemPromptFile?[discoveredAppendSystemPromptFile]:[]}let baseAppend=appendSources.map(s=>resolvePromptInput(s,"append system prompt")).filter(s=>s!==void 0);this.appendSystemPrompt=this.appendSystemPromptOverride?this.appendSystemPromptOverride(baseAppend):baseAppend,this.appendSystemPromptSourcePaths=appendSources.filter(source=>existsSync17(source)).map(source=>resolvePath(source)),this.loaded=!0}async loadCurrentExtensionSet(options){let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0}),enabledExtensions=resolvedPaths.extensions.filter(r=>r.enabled).map(r=>r.path),cliEnabledExtensions=cliExtensionPaths.extensions.filter(r=>r.enabled).map(r=>r.path),extensionPaths=this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions),extensionsResult=await loadExtensionsCached(extensionPaths,this.cwd,this.eventBus);if(!options.includeInlineFactories)return extensionsResult;let inlineExtensions=await this.loadExtensionFactories(extensionsResult.runtime);return extensionsResult.extensions.push(...inlineExtensions.extensions),extensionsResult.errors.push(...inlineExtensions.errors),extensionsResult}resolveExtensionLoadPath(path14){return resolvePath(path14,this.cwd,{normalizeUnicodeSpaces:!0})}async loadFinalExtensionSet(extensionPaths,preTrustExtensions){if(!preTrustExtensions){let extensionsResult2=await loadExtensionsCached(extensionPaths,this.cwd,this.eventBus),inlineExtensions2=await this.loadExtensionFactories(extensionsResult2.runtime);return extensionsResult2.extensions.push(...inlineExtensions2.extensions),extensionsResult2.errors.push(...inlineExtensions2.errors),this.addExtensionConflictDiagnostics(extensionsResult2),extensionsResult2}let preloadedByPath=new Map(preTrustExtensions.extensions.filter(extension=>!extension.path.startsWith("<inline:")).map(extension=>[extension.resolvedPath,extension])),failedPreloadPaths=new Set(preTrustExtensions.errors.map(error=>this.resolveExtensionLoadPath(error.path))),remainingPaths=extensionPaths.filter(path14=>{let resolvedPath=this.resolveExtensionLoadPath(path14);return!preloadedByPath.has(resolvedPath)&&!failedPreloadPaths.has(resolvedPath)}),remainingExtensions=await loadExtensionsCached(remainingPaths,this.cwd,this.eventBus,preTrustExtensions.runtime),loadedByPath=new Map(preloadedByPath);for(let extension of remainingExtensions.extensions)loadedByPath.set(extension.resolvedPath,extension);let inlineExtensions=preTrustExtensions.extensions.filter(extension=>extension.path.startsWith("<inline:")),orderedExtensions=extensionPaths.map(path14=>loadedByPath.get(this.resolveExtensionLoadPath(path14))).filter(extension=>extension!==void 0);orderedExtensions.push(...inlineExtensions);let extensionsResult={extensions:orderedExtensions,errors:[...preTrustExtensions.errors,...remainingExtensions.errors],runtime:preTrustExtensions.runtime};return this.addExtensionConflictDiagnostics(extensionsResult),extensionsResult}addExtensionConflictDiagnostics(extensionsResult){let conflicts=this.detectExtensionConflicts(extensionsResult.extensions);for(let conflict of conflicts)extensionsResult.errors.push({path:conflict.path,error:conflict.message})}mapSkillPath(resource,metadataByPath){if(resource.metadata.source!=="auto"&&resource.metadata.origin!=="package")return resource.path;try{if(!statSync11(resource.path).isDirectory())return resource.path}catch{return resource.path}let skillFile=join28(resource.path,"SKILL.md");return existsSync17(skillFile)?(metadataByPath.has(skillFile)||metadataByPath.set(skillFile,resource.metadata),skillFile):resource.path}normalizeExtensionPaths(entries){return entries.map(entry=>{let metadata=entry.metadata.baseDir?{...entry.metadata,baseDir:this.resolveResourcePath(entry.metadata.baseDir)}:entry.metadata;return{path:this.resolveResourcePath(entry.path),metadata}})}updateSkillsFromPaths(skillPaths,metadataByPath){let skillsResult;this.noSkills&&skillPaths.length===0?skillsResult={skills:[],diagnostics:[]}:skillsResult=loadSkills({cwd:this.cwd,agentDir:this.agentDir,skillPaths,includeDefaults:!1});let resolvedSkills=this.skillsOverride?this.skillsOverride(skillsResult):skillsResult;this.skills=resolvedSkills.skills.map(skill=>({...skill,sourceInfo:this.findSourceInfoForPath(skill.filePath,this.extensionSkillSourceInfos,metadataByPath)??skill.sourceInfo??this.getDefaultSourceInfoForPath(skill.filePath)})),this.skillDiagnostics=resolvedSkills.diagnostics}updatePromptsFromPaths(promptPaths,metadataByPath){let promptsResult;if(this.noPromptTemplates&&promptPaths.length===0)promptsResult={prompts:[],diagnostics:[]};else{let loaded=loadPromptTemplates2({cwd:this.cwd,agentDir:this.agentDir,promptPaths,includeDefaults:!1}),deduped=this.dedupePrompts(loaded.templates);promptsResult={prompts:deduped.prompts,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedPrompts=this.promptsOverride?this.promptsOverride(promptsResult):promptsResult;this.prompts=resolvedPrompts.prompts.map(prompt=>({...prompt,sourceInfo:this.findSourceInfoForPath(prompt.filePath,this.extensionPromptSourceInfos,metadataByPath)??prompt.sourceInfo??this.getDefaultSourceInfoForPath(prompt.filePath)})),this.promptDiagnostics=resolvedPrompts.diagnostics}updateThemesFromPaths(themePaths,metadataByPath){let themesResult;if(this.noThemes&&themePaths.length===0)themesResult={themes:[],diagnostics:[]};else{let loaded=this.loadThemes(themePaths,!1),deduped=this.dedupeThemes(loaded.themes);themesResult={themes:deduped.themes,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedThemes=this.themesOverride?this.themesOverride(themesResult):themesResult;this.themes=resolvedThemes.themes.map(theme2=>{let sourcePath=theme2.sourcePath;return theme2.sourceInfo=sourcePath?this.findSourceInfoForPath(sourcePath,this.extensionThemeSourceInfos,metadataByPath)??theme2.sourceInfo??this.getDefaultSourceInfoForPath(sourcePath):theme2.sourceInfo,theme2}),this.themeDiagnostics=resolvedThemes.diagnostics}applyExtensionSourceInfo(extensions,metadataByPath){for(let extension of extensions){extension.sourceInfo=this.findSourceInfoForPath(extension.path,void 0,metadataByPath)??this.getDefaultSourceInfoForPath(extension.path);for(let command of extension.commands.values())command.sourceInfo=extension.sourceInfo;for(let tool of extension.tools.values())tool.sourceInfo=extension.sourceInfo}}findSourceInfoForPath(resourcePath,extraSourceInfos,metadataByPath){if(!resourcePath)return;if(resourcePath.startsWith("<"))return this.getDefaultSourceInfoForPath(resourcePath);let normalizedResourcePath=resolve9(resourcePath);if(extraSourceInfos)for(let[sourcePath,sourceInfo]of extraSourceInfos.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return{...sourceInfo,path:resourcePath}}if(metadataByPath){let exact=metadataByPath.get(normalizedResourcePath)??metadataByPath.get(resourcePath);if(exact)return createSourceInfo(resourcePath,exact);for(let[sourcePath,metadata]of metadataByPath.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return createSourceInfo(resourcePath,metadata)}}}getDefaultSourceInfoForPath(filePath){if(filePath.startsWith("<")&&filePath.endsWith(">"))return{path:filePath,source:filePath.slice(1,-1).split(":")[0]||"temporary",scope:"temporary",origin:"top-level"};let normalizedPath=resolve9(filePath),agentRoots=[join28(this.agentDir,"skills"),join28(this.agentDir,"prompts"),join28(this.agentDir,"themes"),join28(this.agentDir,"extensions")],projectRoots=[join28(this.cwd,CONFIG_DIR_NAME,"skills"),join28(this.cwd,CONFIG_DIR_NAME,"prompts"),join28(this.cwd,CONFIG_DIR_NAME,"themes"),join28(this.cwd,CONFIG_DIR_NAME,"extensions")];for(let root of agentRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"user",origin:"top-level",baseDir:root};for(let root of projectRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"project",origin:"top-level",baseDir:root};return{path:filePath,source:"local",scope:"temporary",origin:"top-level",baseDir:statSync11(normalizedPath).isDirectory()?normalizedPath:resolve9(normalizedPath,"..")}}mergePaths(primary,additional){let merged=[],seen=new Set;for(let p of[...primary,...additional]){let resolved=this.resolveResourcePath(p),canonicalPath=canonicalizePath(resolved);seen.has(canonicalPath)||(seen.add(canonicalPath),merged.push(resolved))}return merged}resolveResourcePath(p){return resolvePath(p,this.cwd,{trim:!0})}loadThemes(paths,includeDefaults=!0){let themes=[],diagnostics=[];if(includeDefaults){let defaultDirs=[join28(this.agentDir,"themes"),join28(this.cwd,CONFIG_DIR_NAME,"themes")];for(let dir of defaultDirs)this.loadThemesFromDir(dir,themes,diagnostics)}for(let p of paths){let resolved=this.resolveResourcePath(p);if(!existsSync17(resolved)){diagnostics.push({type:"warning",message:"theme path does not exist",path:resolved});continue}try{let stats=statSync11(resolved);stats.isDirectory()?this.loadThemesFromDir(resolved,themes,diagnostics):stats.isFile()&&resolved.endsWith(".json")?this.loadThemeFromFile(resolved,themes,diagnostics):diagnostics.push({type:"warning",message:"theme path is not a json file",path:resolved})}catch(error){let message=error instanceof Error?error.message:"failed to read theme path";diagnostics.push({type:"warning",message,path:resolved})}}return{themes,diagnostics}}loadThemesFromDir(dir,themes,diagnostics){if(existsSync17(dir))try{let entries=readdirSync9(dir,{withFileTypes:!0});for(let entry of entries){let isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync11(join28(dir,entry.name)).isFile()}catch{continue}isFile&&entry.name.endsWith(".json")&&this.loadThemeFromFile(join28(dir,entry.name),themes,diagnostics)}}catch(error){let message=error instanceof Error?error.message:"failed to read theme directory";diagnostics.push({type:"warning",message,path:dir})}}loadThemeFromFile(filePath,themes,diagnostics){try{themes.push(loadThemeFromPath(filePath))}catch(error){let message=error instanceof Error?error.message:"failed to load theme";diagnostics.push({type:"warning",message,path:filePath})}}async loadExtensionFactories(runtime){let extensions=[],errors=[];for(let[index3,input2]of this.extensionFactories.entries()){let isNamed=typeof input2!="function",factory=isNamed?input2.factory:input2,extensionPath=`<inline:${isNamed?input2.name:index3+1}>`;try{let extension=await loadExtensionFromFactory(factory,this.cwd,this.eventBus,runtime,extensionPath);extension.hidden=isNamed&&input2.hidden,extensions.push(extension)}catch(error){let message=error instanceof Error?error.message:"failed to load extension";errors.push({path:extensionPath,error:message})}}return{extensions,errors}}dedupePrompts(prompts){let seen=new Map,diagnostics=[];for(let prompt of prompts){let existing=seen.get(prompt.name);existing?diagnostics.push({type:"collision",message:`name "/${prompt.name}" collision`,path:prompt.filePath,collision:{resourceType:"prompt",name:prompt.name,winnerPath:existing.filePath,loserPath:prompt.filePath}}):seen.set(prompt.name,prompt)}return{prompts:Array.from(seen.values()),diagnostics}}dedupeThemes(themes){let seen=new Map,diagnostics=[];for(let t of themes){let name=t.name??"unnamed",existing=seen.get(name);existing?diagnostics.push({type:"collision",message:`name "${name}" collision`,path:t.sourcePath,collision:{resourceType:"theme",name,winnerPath:existing.sourcePath??"<builtin>",loserPath:t.sourcePath??"<builtin>"}}):seen.set(name,t)}return{themes:Array.from(seen.values()),diagnostics}}discoverSystemPromptFile(){let projectPath=join28(this.cwd,CONFIG_DIR_NAME,"SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync17(projectPath))return projectPath;let globalPath=join28(this.agentDir,"SYSTEM.md");if(existsSync17(globalPath))return globalPath}discoverAppendSystemPromptFile(){let projectPath=join28(this.cwd,CONFIG_DIR_NAME,"APPEND_SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync17(projectPath))return projectPath;let globalPath=join28(this.agentDir,"APPEND_SYSTEM.md");if(existsSync17(globalPath))return globalPath}isUnderPath(target,root){let normalizedRoot=resolve9(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep9)?normalizedRoot:`${normalizedRoot}${sep9}`;return target.startsWith(prefix)}detectExtensionConflicts(extensions){let conflicts=[],toolOwners=new Map,flagOwners=new Map;for(let ext2 of extensions){for(let toolName of ext2.tools.keys()){let existingOwner=toolOwners.get(toolName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Tool "${toolName}" conflicts with ${existingOwner}`}):toolOwners.set(toolName,ext2.path)}for(let flagName of ext2.flags.keys()){let existingOwner=flagOwners.get(flagName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Flag "--${flagName}" conflicts with ${existingOwner}`}):flagOwners.set(flagName,ext2.path)}}return conflicts}};import{constants as constants7,copyFileSync,existsSync as existsSync19,mkdirSync as mkdirSync9}from"node:fs";import{basename as basename11,join as join30,parse as parse4,resolve as resolve10}from"node:path";import{existsSync as existsSync18}from"node:fs";function getMissingSessionCwdIssue(sessionManager,fallbackCwd){let sessionFile=sessionManager.getSessionFile();if(!sessionFile)return;let sessionCwd=sessionManager.getCwd();if(!(!sessionCwd||existsSync18(sessionCwd)))return{sessionFile,sessionCwd,fallbackCwd}}function formatMissingSessionCwdError(issue){let sessionFile=issue.sessionFile?`
|
|
1300
1300
|
Session file: ${issue.sessionFile}`:"";return`Stored session working directory does not exist: ${issue.sessionCwd}${sessionFile}
|
|
1301
1301
|
Current working directory: ${issue.fallbackCwd}`}function formatMissingSessionCwdPrompt(issue){return`cwd from session file does not exist
|
|
1302
1302
|
${issue.sessionCwd}
|
|
1303
1303
|
|
|
1304
1304
|
continue in current cwd
|
|
1305
|
-
${issue.fallbackCwd}`}var MissingSessionCwdError=class extends Error{constructor(issue){super(formatMissingSessionCwdError(issue)),this.name="MissingSessionCwdError",this.issue=issue}};function assertSessionCwdExists(sessionManager,fallbackCwd){let issue=getMissingSessionCwdIssue(sessionManager,fallbackCwd);if(issue)throw new MissingSessionCwdError(issue)}import{join as join29}from"node:path";function applyExtensionFlagValues(resourceLoader,extensionFlagValues){if(!extensionFlagValues)return[];let diagnostics=[],extensionsResult=resourceLoader.getExtensions(),registeredFlags=new Map;for(let extension of extensionsResult.extensions)for(let[name,flag]of extension.flags)registeredFlags.set(name,{type:flag.type});let unknownFlags=[];for(let[name,value2]of extensionFlagValues){let flag=registeredFlags.get(name);if(!flag){unknownFlags.push(name);continue}if(flag.type==="boolean"){extensionsResult.runtime.flagValues.set(name,!0);continue}if(typeof value2=="string"){extensionsResult.runtime.flagValues.set(name,value2);continue}diagnostics.push({type:"error",message:`Extension flag "--${name}" requires a value`})}return unknownFlags.length>0&&diagnostics.push({type:"error",message:`Unknown option${unknownFlags.length===1?"":"s"}: ${unknownFlags.map(name=>`--${name}`).join(", ")}`}),diagnostics}async function createAgentSessionServices(options){let cwd=resolvePath(options.cwd),agentDir=options.agentDir?resolvePath(options.agentDir):getAgentDir(),modelRuntime=options.modelRuntime??await ModelRuntime.create({authPath:join29(agentDir,"auth.json"),modelsPath:join29(agentDir,"models.json"),signal:options.modelRuntimeSignal}),settingsManager=options.settingsManager??SettingsManager.create(cwd,agentDir),resourceLoader=new DefaultResourceLoader({...options.resourceLoaderOptions??{},cwd,agentDir,settingsManager});await resourceLoader.reload(options.resourceLoaderReloadOptions);let diagnostics=[],extensionsResult=resourceLoader.getExtensions();for(let{name,config,extensionPath}of extensionsResult.runtime.pendingProviderRegistrations)try{modelRuntime.registerProvider(name,config)}catch(error){let message=error instanceof Error?error.message:String(error);diagnostics.push({type:"error",message:`Extension "${extensionPath}" error: ${message}`})}extensionsResult.runtime.pendingProviderRegistrations=[];for(let{provider,extensionPath}of extensionsResult.runtime.pendingNativeProviderRegistrations)try{modelRuntime.registerNativeProvider(provider)}catch(error){let message=error instanceof Error?error.message:String(error);diagnostics.push({type:"error",message:`Extension "${extensionPath}" error: ${message}`})}return extensionsResult.runtime.pendingNativeProviderRegistrations=[],await modelRuntime.refresh({allowNetwork:!1}),diagnostics.push(...applyExtensionFlagValues(resourceLoader,options.extensionFlagValues)),{cwd,agentDir,modelRuntime,settingsManager,resourceLoader,diagnostics}}async function createAgentSessionFromServices(options){return createAgentSession({cwd:options.services.cwd,agentDir:options.services.agentDir,modelRuntime:options.services.modelRuntime,settingsManager:options.services.settingsManager,resourceLoader:options.services.resourceLoader,sessionManager:options.sessionManager,model:options.model,thinkingLevel:options.thinkingLevel,scopedModels:options.scopedModels,tools:options.tools,excludeTools:options.excludeTools,noTools:options.noTools,customTools:options.customTools,sessionStartEvent:options.sessionStartEvent,executionRole:options.executionRole})}var SessionImportFileNotFoundError=class extends Error{constructor(filePath){super(`File not found: ${filePath}`),this.name="SessionImportFileNotFoundError",this.filePath=filePath}};function extractUserMessageText(content){return typeof content=="string"?content:content.filter(part=>part.type==="text"&&typeof part.text=="string").map(part=>part.text).join("")}var AgentSessionRuntime=class{constructor(_session,_services,createRuntime,_diagnostics=[],_modelFallbackMessage){this._session=_session,this._services=_services,this.createRuntime=createRuntime,this._diagnostics=_diagnostics,this._modelFallbackMessage=_modelFallbackMessage}get services(){return this._services}get session(){return this._session}get cwd(){return this._services.cwd}get diagnostics(){return this._diagnostics}get modelFallbackMessage(){return this._modelFallbackMessage}setRebindSession(rebindSession){this.rebindSession=rebindSession}setBeforeSessionInvalidate(beforeSessionInvalidate){this.beforeSessionInvalidate=beforeSessionInvalidate}async emitBeforeSwitch(reason,targetSessionFile){let runner=this.session.extensionRunner;return runner.hasHandlers("session_before_switch")?{cancelled:(await runner.emit({type:"session_before_switch",reason,targetSessionFile}))?.cancel===!0}:{cancelled:!1}}async emitBeforeFork(entryId,options){let runner=this.session.extensionRunner;return runner.hasHandlers("session_before_fork")?{cancelled:(await runner.emit({type:"session_before_fork",entryId,...options}))?.cancel===!0}:{cancelled:!1}}async teardownCurrent(reason,targetSessionFile){this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),await emitSessionShutdownEvent(this.session.extensionRunner,{type:"session_shutdown",reason,targetSessionFile}),this.beforeSessionInvalidate?.(),this.session.dispose()}apply(result2){this._session=result2.session,this._services=result2.services,this._diagnostics=result2.diagnostics,this._modelFallbackMessage=result2.modelFallbackMessage}async finishSessionReplacement(withSession){this.rebindSession&&await this.rebindSession(this.session),withSession&&await withSession(this.session.createReplacedSessionContext())}async withBackgroundPaused(operation){let resumeBackground=this.session.pauseBackgroundNotifications();try{return await operation()}finally{resumeBackground()}}async switchSession(sessionPath,options){return this.withBackgroundPaused(()=>this.switchSessionBody(sessionPath,options))}async switchSessionBody(sessionPath,options){let beforeResult=await this.emitBeforeSwitch("resume",sessionPath);if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile,sessionManager=SessionManager.open(sessionPath,void 0,options?.cwdOverride);return assertSessionCwdExists(sessionManager,this.cwd),await this.teardownCurrent("resume",sessionManager.getSessionFile()),sessionManager=SessionManager.open(sessionPath,void 0,options?.cwdOverride),this.apply(await this.createRuntime({cwd:sessionManager.getCwd(),agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"resume",previousSessionFile},projectTrustContext:options?.projectTrustContextFactory?.(sessionManager.getCwd())})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1}}async newSession(options){return this.withBackgroundPaused(()=>this.newSessionBody(options))}async newSessionBody(options){let beforeResult=await this.emitBeforeSwitch("new");if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile,sessionDir=this.session.sessionManager.getSessionDir(),sessionManager=this.session.sessionManager.isPersisted()?SessionManager.create(this.cwd,sessionDir):SessionManager.inMemory(this.cwd);return options?.parentSession&&sessionManager.newSession({parentSession:options.parentSession}),await this.teardownCurrent("new",sessionManager.getSessionFile()),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"new",previousSessionFile}})),options?.setup&&(await options.setup(this.session.sessionManager),this.session.refreshContext()),await this.finishSessionReplacement(options?.withSession),{cancelled:!1}}async fork(entryId,options){return this.withBackgroundPaused(()=>this.forkBody(entryId,options))}async forkBody(entryId,options){let position=options?.position??"before";if((await this.emitBeforeFork(entryId,{position})).cancelled)return{cancelled:!0};let targetLeafId,selectedText,selectedEntry=this.session.sessionManager.getEntry(entryId);if(!selectedEntry)throw new Error("Invalid entry ID for forking");if(position==="at")targetLeafId=selectedEntry.id;else{if(selectedEntry.type!=="message"||selectedEntry.message.role!=="user")throw new Error("Invalid entry ID for forking");targetLeafId=selectedEntry.parentId,selectedText=extractUserMessageText(selectedEntry.message.content)}let previousSessionFile=this.session.sessionFile;if(this.session.sessionManager.isPersisted()){let currentSessionFile=this.session.sessionFile;if(!currentSessionFile)throw new Error("Persisted session is missing a session file");let sessionDir=this.session.sessionManager.getSessionDir();if(!targetLeafId){let sessionManager3=SessionManager.create(this.cwd,sessionDir);return sessionManager3.newSession({parentSession:currentSessionFile}),await this.teardownCurrent("fork",sessionManager3.getSessionFile()),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager:sessionManager3,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}if(!existsSync19(currentSessionFile))throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");let forkingCurrentLeaf2=targetLeafId===this.session.sessionManager.getLeafId();this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),forkingCurrentLeaf2&&(targetLeafId=this.session.sessionManager.getLeafId());let sessionManager2=SessionManager.open(currentSessionFile,sessionDir);if(!sessionManager2.createBranchedSession(targetLeafId))throw new Error("Failed to create forked session");return await this.teardownCurrent("fork",sessionManager2.getSessionFile()),this.apply(await this.createRuntime({cwd:sessionManager2.getCwd(),agentDir:this.services.agentDir,sessionManager:sessionManager2,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}let sessionManager=this.session.sessionManager,forkingCurrentLeaf=targetLeafId!==null&&targetLeafId===sessionManager.getLeafId();return await this.teardownCurrent("fork",sessionManager.getSessionFile()),forkingCurrentLeaf&&(targetLeafId=sessionManager.getLeafId()),targetLeafId?sessionManager.createBranchedSession(targetLeafId):sessionManager.newSession({parentSession:previousSessionFile}),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}async importFromJsonl(inputPath,cwdOverride){return this.withBackgroundPaused(()=>this.importFromJsonlBody(inputPath,cwdOverride))}async importFromJsonlBody(inputPath,cwdOverride){let resolvedPath=resolvePath(inputPath);if(!existsSync19(resolvedPath))throw new SessionImportFileNotFoundError(resolvedPath);let sessionDir=this.session.sessionManager.getSessionDir();existsSync19(sessionDir)||mkdirSync9(sessionDir,{recursive:!0});let destinationPath=join30(sessionDir,basename11(resolvedPath)),sourceAlreadyStored=resolve10(destinationPath)===resolvedPath;if(!sourceAlreadyStored){let{name,ext:ext2}=parse4(destinationPath),suffix=1;for(;existsSync19(destinationPath);)destinationPath=join30(sessionDir,`${name}-${suffix++}${ext2}`)}let beforeResult=await this.emitBeforeSwitch("resume",destinationPath);if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile;sourceAlreadyStored||copyFileSync(resolvedPath,destinationPath,constants7.COPYFILE_EXCL);let sessionManager=SessionManager.open(destinationPath,sessionDir,cwdOverride);return assertSessionCwdExists(sessionManager,this.cwd),await this.teardownCurrent("resume",sessionManager.getSessionFile()),sessionManager=SessionManager.open(destinationPath,sessionDir,cwdOverride),this.apply(await this.createRuntime({cwd:sessionManager.getCwd(),agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"resume",previousSessionFile}})),await this.finishSessionReplacement(),{cancelled:!1}}async dispose(){this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),await emitSessionShutdownEvent(this.session.extensionRunner,{type:"session_shutdown",reason:"quit"}),this.beforeSessionInvalidate?.(),this.session.dispose()}};async function createAgentSessionRuntime(createRuntime,options){assertSessionCwdExists(options.sessionManager,options.cwd);let result2=await createRuntime(options);return new AgentSessionRuntime(result2.session,result2.services,createRuntime,result2.diagnostics,result2.modelFallbackMessage)}setDefaultStreamFn(streamSimple);function getDefaultAgentDir(){return getAgentDir()}async function createAgentSession(options={}){let cwd=resolvePath(options.cwd??options.sessionManager?.getCwd()??process.cwd()),agentDir=options.agentDir?resolvePath(options.agentDir):getDefaultAgentDir(),resourceLoader=options.resourceLoader,authPath=options.agentDir?join31(agentDir,"auth.json"):void 0,modelsPath=options.agentDir?join31(agentDir,"models.json"):void 0,modelRuntime=options.modelRuntime??await ModelRuntime.create({authPath,modelsPath}),settingsManager=options.settingsManager??SettingsManager.create(cwd,agentDir),sessionManager=options.sessionManager??SessionManager.create(cwd,getDefaultSessionDir(cwd,agentDir));resourceLoader||(resourceLoader=new DefaultResourceLoader({cwd,agentDir,settingsManager}),await resourceLoader.reload(),time("resourceLoader.reload"));let existingSession=sessionManager.buildSessionContext(),hasExistingSession=existingSession.messages.length>0,hasThinkingEntry=sessionManager.getBranch().some(entry=>entry.type==="thinking_level_change"),model=options.model,modelFallbackMessage;if(!model&&hasExistingSession&&existingSession.model){let restoredModel=modelRuntime.getModel(existingSession.model.provider,existingSession.model.modelId);restoredModel&&modelRuntime.hasConfiguredAuth(restoredModel.provider)&&(model=restoredModel),model||(modelFallbackMessage=`Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`)}model||(model=(await findInitialModel({scopedModels:[],isContinuing:hasExistingSession,defaultProvider:settingsManager.getDefaultProvider(),defaultModelId:settingsManager.getDefaultModel(),defaultThinkingLevel:settingsManager.getDefaultThinkingLevel(),modelThinkingLevels:settingsManager.getAllModelThinkingLevels(),modelRuntime})).model,model?modelFallbackMessage&&(modelFallbackMessage+=`. Using ${model.provider}/${model.id}`):modelFallbackMessage=formatNoModelsAvailableMessage());let thinkingLevel=options.thinkingLevel;if(thinkingLevel===void 0&&hasExistingSession&&(thinkingLevel=hasThinkingEntry?existingSession.thinkingLevel:settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL),thinkingLevel===void 0&&model){let perModel=settingsManager.getModelThinkingLevel(model.provider,model.id);perModel&&(thinkingLevel=perModel)}thinkingLevel===void 0&&(thinkingLevel=settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL),model?thinkingLevel=clampThinkingLevel(model,thinkingLevel):thinkingLevel="off";let defaultActiveToolNames=["read","bash","edit","write"],configuredDefaultToolNames=settingsManager.getDefaultTools(),allowedToolNames=options.tools??(options.noTools==="all"?[]:void 0),excludedToolNames=options.excludeTools,excludedToolNameSet=excludedToolNames?new Set(excludedToolNames):void 0,initialActiveToolNames=(options.tools??(options.noTools?[]:configuredDefaultToolNames??defaultActiveToolNames)).filter(name=>!excludedToolNameSet?.has(name)),extensionRunnerRef={},contextCapture=new ContextSnapshotCapture(settingsManager,extensionRunnerRef),cacheWarmer=new CacheWarmer(modelRuntime,sessionManager,()=>settingsManager.getCacheWarmingMode(),async event=>extensionRunnerRef.current?.emitCacheWarmingDecision(event)??event.action),cacheContextIsCurrent=requestModel=>{let messages=agent.state.messages;return()=>{let currentModel=agent.state.model,currentMessages=agent.state.messages;return currentModel.provider===requestModel.provider&¤tModel.id===requestModel.id&&messages.length<=currentMessages.length&&messages.every((message,index3)=>currentMessages[index3]===message)}},transformProviderPayload=async payload=>{let runner=extensionRunnerRef.current;return runner?.hasHandlers("before_provider_request")?runner.emitBeforeProviderRequest(payload):payload},handleProviderResponse=async response=>{let runner=extensionRunnerRef.current;runner?.hasHandlers("after_provider_response")&&await runner.emit({type:"after_provider_response",status:response.status,headers:response.headers})},agent=new Agent({initialState:{systemPrompt:"",model,thinkingLevel,tools:[],messages:existingSession.messages},convertToLlm:contextCapture.convertToLlm,streamFn:async(model2,context,options2)=>{let requestOptions=resolveModelStreamOptions(model2,settingsManager,extensionRunnerRef.current,options2);return options2?.sessionId===sessionManager.getSessionId()&&cacheWarmer.start({model:model2,context,options:requestOptions},cacheContextIsCurrent(model2)),modelRuntime.streamSimple(model2,context,requestOptions)},onPayload:transformProviderPayload,onResponse:handleProviderResponse,sessionId:sessionManager.getSessionId(),transformContext:async messages=>{let runner=extensionRunnerRef.current;return runner?runner.emitContext(messages):messages},steeringMode:settingsManager.getSteeringMode(),followUpMode:settingsManager.getFollowUpMode(),transport:settingsManager.getTransport(),thinkingBudgets:settingsManager.getThinkingBudgets(),maxRetryDelayMs:settingsManager.getProviderRetrySettings().maxRetryDelayMs});hasExistingSession?hasThinkingEntry||sessionManager.appendThinkingLevelChange(thinkingLevel):(model&&sessionManager.appendModelChange(model.provider,model.id),sessionManager.appendThinkingLevelChange(thinkingLevel));let session=new AgentSession({agent,sessionManager,settingsManager,cwd,scopedModels:options.scopedModels,resourceLoader,customTools:options.customTools,modelRuntime,cacheWarmer,initialActiveToolNames,allowedToolNames,excludedToolNames,extensionRunnerRef,captureModelContext:contextCapture.capture,sessionStartEvent:options.sessionStartEvent,executionRole:options.executionRole});contextCapture.install(agent);let extensionsResult=resourceLoader.getExtensions();return{session,extensionsResult,modelFallbackMessage}}var import_proper_lockfile3=__toESM(require_proper_lockfile(),1);import{existsSync as existsSync20,mkdirSync as mkdirSync10,readFileSync as readFileSync14,writeFileSync as writeFileSync8}from"node:fs";import{dirname as dirname20,join as join32}from"node:path";var TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES=["settings.json","extensions","skills","prompts","themes","SYSTEM.md","APPEND_SYSTEM.md"];function normalizeCwd(cwd){return canonicalizePath(resolvePath(cwd))}function findNearestTrustEntry(data,cwd){let currentDir=normalizeCwd(cwd);for(;;){let value2=data[findPathKeys(data,currentDir)[0]??currentDir];if(value2===!0||value2===!1)return{path:currentDir,decision:value2};let parentDir=dirname20(currentDir);if(parentDir===currentDir)return null;currentDir=parentDir}}function getProjectTrustParentPath(cwd){let trustPath=normalizeCwd(cwd),parentDir=dirname20(trustPath);return parentDir===trustPath?void 0:parentDir}function getProjectTrustOptions(cwd,options){let trustPath=normalizeCwd(cwd),trustOptions=[{label:"Trust",trusted:!0,updates:[{path:trustPath,decision:!0}],savedPath:trustPath}],parentPath=getProjectTrustParentPath(cwd);return parentPath!==void 0&&trustOptions.push({label:`Trust parent folder (${parentPath})`,trusted:!0,updates:[{path:parentPath,decision:!0},{path:trustPath,decision:null}],savedPath:parentPath}),options?.includeSessionOnly&&trustOptions.push({label:"Trust (this session only)",trusted:!0,updates:[]}),trustOptions.push({label:"Do not trust",trusted:!1,updates:[{path:trustPath,decision:!1}],savedPath:trustPath}),options?.includeSessionOnly&&trustOptions.push({label:"Do not trust (this session only)",trusted:!1,updates:[]}),trustOptions}function readTrustFile(path14){if(!existsSync20(path14))return{};let parsed;try{parsed=JSON.parse(stripBom(readFileSync14(path14,"utf-8")))}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(`Failed to read trust store ${path14}: ${message}`)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new Error(`Invalid trust store ${path14}: expected an object`);let data={};for(let[key,value2]of Object.entries(parsed)){if(value2!==!0&&value2!==!1&&value2!==null)throw new Error(`Invalid trust store ${path14}: value for ${JSON.stringify(key)} must be true, false, or null`);data[key]=value2}return data}function writeTrustFile(path14,data){let sorted={};for(let key of Object.keys(data).sort()){let value2=data[key];(value2===!0||value2===!1||value2===null)&&(sorted[key]=value2)}mkdirSync10(dirname20(path14),{recursive:!0}),writeFileSync8(path14,`${JSON.stringify(sorted,null,2)}
|
|
1305
|
+
${issue.fallbackCwd}`}var MissingSessionCwdError=class extends Error{constructor(issue){super(formatMissingSessionCwdError(issue)),this.name="MissingSessionCwdError",this.issue=issue}};function assertSessionCwdExists(sessionManager,fallbackCwd){let issue=getMissingSessionCwdIssue(sessionManager,fallbackCwd);if(issue)throw new MissingSessionCwdError(issue)}import{join as join29}from"node:path";function applyExtensionFlagValues(resourceLoader,extensionFlagValues){if(!extensionFlagValues)return[];let diagnostics=[],extensionsResult=resourceLoader.getExtensions(),registeredFlags=new Map;for(let extension of extensionsResult.extensions)for(let[name,flag]of extension.flags)registeredFlags.set(name,{type:flag.type});let unknownFlags=[];for(let[name,value2]of extensionFlagValues){let flag=registeredFlags.get(name);if(!flag){unknownFlags.push(name);continue}if(flag.type==="boolean"){extensionsResult.runtime.flagValues.set(name,!0);continue}if(typeof value2=="string"){extensionsResult.runtime.flagValues.set(name,value2);continue}diagnostics.push({type:"error",message:`Extension flag "--${name}" requires a value`})}return unknownFlags.length>0&&diagnostics.push({type:"error",message:`Unknown option${unknownFlags.length===1?"":"s"}: ${unknownFlags.map(name=>`--${name}`).join(", ")}`}),diagnostics}async function createAgentSessionServices(options){let cwd=resolvePath(options.cwd),agentDir=options.agentDir?resolvePath(options.agentDir):getAgentDir(),modelRuntime=options.modelRuntime??await ModelRuntime.create({authPath:join29(agentDir,"auth.json"),modelsPath:join29(agentDir,"models.json"),signal:options.modelRuntimeSignal}),settingsManager=options.settingsManager??SettingsManager.create(cwd,agentDir),resourceLoader=new DefaultResourceLoader({...options.resourceLoaderOptions??{},cwd,agentDir,settingsManager});await resourceLoader.reload(options.resourceLoaderReloadOptions);let diagnostics=[],extensionsResult=resourceLoader.getExtensions();for(let{name,config,extensionPath}of extensionsResult.runtime.pendingProviderRegistrations)try{modelRuntime.registerProvider(name,config)}catch(error){let message=error instanceof Error?error.message:String(error);diagnostics.push({type:"error",message:`Extension "${extensionPath}" error: ${message}`})}extensionsResult.runtime.pendingProviderRegistrations=[];for(let{provider,extensionPath}of extensionsResult.runtime.pendingNativeProviderRegistrations)try{modelRuntime.registerNativeProvider(provider)}catch(error){let message=error instanceof Error?error.message:String(error);diagnostics.push({type:"error",message:`Extension "${extensionPath}" error: ${message}`})}return extensionsResult.runtime.pendingNativeProviderRegistrations=[],await modelRuntime.refresh({allowNetwork:!1}),diagnostics.push(...applyExtensionFlagValues(resourceLoader,options.extensionFlagValues)),{cwd,agentDir,modelRuntime,settingsManager,resourceLoader,diagnostics}}async function createAgentSessionFromServices(options){return createAgentSession({cwd:options.services.cwd,agentDir:options.services.agentDir,modelRuntime:options.services.modelRuntime,settingsManager:options.services.settingsManager,resourceLoader:options.services.resourceLoader,sessionManager:options.sessionManager,model:options.model,thinkingLevel:options.thinkingLevel,scopedModels:options.scopedModels,tools:options.tools,excludeTools:options.excludeTools,noTools:options.noTools,customTools:options.customTools,sessionStartEvent:options.sessionStartEvent,executionRole:options.executionRole})}var SessionImportFileNotFoundError=class extends Error{constructor(filePath){super(`File not found: ${filePath}`),this.name="SessionImportFileNotFoundError",this.filePath=filePath}};function extractUserMessageText(content){return typeof content=="string"?content:content.filter(part=>part.type==="text"&&typeof part.text=="string").map(part=>part.text).join("")}var AgentSessionRuntime=class{constructor(_session,_services,createRuntime,_diagnostics=[],_modelFallbackMessage){this._session=_session,this._services=_services,this.createRuntime=createRuntime,this._diagnostics=_diagnostics,this._modelFallbackMessage=_modelFallbackMessage}get services(){return this._services}get session(){return this._session}get cwd(){return this._services.cwd}get diagnostics(){return this._diagnostics}get modelFallbackMessage(){return this._modelFallbackMessage}setRebindSession(rebindSession){this.rebindSession=rebindSession}setBeforeSessionInvalidate(beforeSessionInvalidate){this.beforeSessionInvalidate=beforeSessionInvalidate}async emitBeforeSwitch(reason,targetSessionFile){let runner=this.session.extensionRunner;return runner.hasHandlers("session_before_switch")?{cancelled:(await runner.emit({type:"session_before_switch",reason,targetSessionFile}))?.cancel===!0}:{cancelled:!1}}async emitBeforeFork(entryId,options){let runner=this.session.extensionRunner;return runner.hasHandlers("session_before_fork")?{cancelled:(await runner.emit({type:"session_before_fork",entryId,...options}))?.cancel===!0}:{cancelled:!1}}async teardownCurrent(reason,targetSessionFile){this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),await emitSessionShutdownEvent(this.session.extensionRunner,{type:"session_shutdown",reason,targetSessionFile}),this.beforeSessionInvalidate?.(),this.session.dispose()}apply(result2){this._session=result2.session,this._services=result2.services,this._diagnostics=result2.diagnostics,this._modelFallbackMessage=result2.modelFallbackMessage}async finishSessionReplacement(withSession){this.rebindSession&&await this.rebindSession(this.session),withSession&&await withSession(this.session.createReplacedSessionContext())}async withBackgroundPaused(operation){let resumeBackground=this.session.pauseBackgroundNotifications();try{return await operation()}finally{resumeBackground()}}async switchSession(sessionPath,options){return this.withBackgroundPaused(()=>this.switchSessionBody(sessionPath,options))}async switchSessionBody(sessionPath,options){let beforeResult=await this.emitBeforeSwitch("resume",sessionPath);if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile,sessionManager=SessionManager.open(sessionPath,void 0,options?.cwdOverride);return assertSessionCwdExists(sessionManager,this.cwd),await this.teardownCurrent("resume",sessionManager.getSessionFile()),sessionManager=SessionManager.open(sessionPath,void 0,options?.cwdOverride),this.apply(await this.createRuntime({cwd:sessionManager.getCwd(),agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"resume",previousSessionFile},projectTrustContext:options?.projectTrustContextFactory?.(sessionManager.getCwd())})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1}}async newSession(options){return this.withBackgroundPaused(()=>this.newSessionBody(options))}async newSessionBody(options){let beforeResult=await this.emitBeforeSwitch("new");if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile,sessionDir=this.session.sessionManager.getSessionDir(),sessionManager=this.session.sessionManager.isPersisted()?SessionManager.create(this.cwd,sessionDir):SessionManager.inMemory(this.cwd);return options?.parentSession&&sessionManager.newSession({parentSession:options.parentSession}),await this.teardownCurrent("new",sessionManager.getSessionFile()),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"new",previousSessionFile}})),options?.setup&&(await options.setup(this.session.sessionManager),this.session.refreshContext()),await this.finishSessionReplacement(options?.withSession),{cancelled:!1}}async fork(entryId,options){return this.withBackgroundPaused(()=>this.forkBody(entryId,options))}async forkBody(entryId,options){let position=options?.position??"before";if((await this.emitBeforeFork(entryId,{position})).cancelled)return{cancelled:!0};let targetLeafId,selectedText,selectedEntry=this.session.sessionManager.getEntry(entryId);if(!selectedEntry)throw new Error("Invalid entry ID for forking");if(position==="at")targetLeafId=selectedEntry.id;else{if(selectedEntry.type!=="message"||selectedEntry.message.role!=="user")throw new Error("Invalid entry ID for forking");targetLeafId=selectedEntry.parentId,selectedText=extractUserMessageText(selectedEntry.message.content)}let previousSessionFile=this.session.sessionFile;if(this.session.sessionManager.isPersisted()){let currentSessionFile=this.session.sessionFile;if(!currentSessionFile)throw new Error("Persisted session is missing a session file");let sessionDir=this.session.sessionManager.getSessionDir();if(!targetLeafId){let sessionManager3=SessionManager.create(this.cwd,sessionDir);return sessionManager3.newSession({parentSession:currentSessionFile}),await this.teardownCurrent("fork",sessionManager3.getSessionFile()),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager:sessionManager3,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}if(!existsSync19(currentSessionFile))throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");let forkingCurrentLeaf2=targetLeafId===this.session.sessionManager.getLeafId();this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),forkingCurrentLeaf2&&(targetLeafId=this.session.sessionManager.getLeafId());let sessionManager2=SessionManager.open(currentSessionFile,sessionDir);if(!sessionManager2.createBranchedSession(targetLeafId))throw new Error("Failed to create forked session");return await this.teardownCurrent("fork",sessionManager2.getSessionFile()),this.apply(await this.createRuntime({cwd:sessionManager2.getCwd(),agentDir:this.services.agentDir,sessionManager:sessionManager2,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}let sessionManager=this.session.sessionManager,forkingCurrentLeaf=targetLeafId!==null&&targetLeafId===sessionManager.getLeafId();return await this.teardownCurrent("fork",sessionManager.getSessionFile()),forkingCurrentLeaf&&(targetLeafId=sessionManager.getLeafId()),targetLeafId?sessionManager.createBranchedSession(targetLeafId):sessionManager.newSession({parentSession:previousSessionFile}),this.apply(await this.createRuntime({cwd:this.cwd,agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"fork",previousSessionFile}})),await this.finishSessionReplacement(options?.withSession),{cancelled:!1,selectedText}}async importFromJsonl(inputPath,cwdOverride){return this.withBackgroundPaused(()=>this.importFromJsonlBody(inputPath,cwdOverride))}async importFromJsonlBody(inputPath,cwdOverride){let resolvedPath=resolvePath(inputPath);if(!existsSync19(resolvedPath))throw new SessionImportFileNotFoundError(resolvedPath);let sessionDir=this.session.sessionManager.getSessionDir();existsSync19(sessionDir)||mkdirSync9(sessionDir,{recursive:!0});let destinationPath=join30(sessionDir,basename11(resolvedPath)),sourceAlreadyStored=resolve10(destinationPath)===resolvedPath;if(!sourceAlreadyStored){let{name,ext:ext2}=parse4(destinationPath),suffix=1;for(;existsSync19(destinationPath);)destinationPath=join30(sessionDir,`${name}-${suffix++}${ext2}`)}let beforeResult=await this.emitBeforeSwitch("resume",destinationPath);if(beforeResult.cancelled)return beforeResult;let previousSessionFile=this.session.sessionFile;sourceAlreadyStored||copyFileSync(resolvedPath,destinationPath,constants7.COPYFILE_EXCL);let sessionManager=SessionManager.open(destinationPath,sessionDir,cwdOverride);return assertSessionCwdExists(sessionManager,this.cwd),await this.teardownCurrent("resume",sessionManager.getSessionFile()),sessionManager=SessionManager.open(destinationPath,sessionDir,cwdOverride),this.apply(await this.createRuntime({cwd:sessionManager.getCwd(),agentDir:this.services.agentDir,sessionManager,sessionStartEvent:{type:"session_start",reason:"resume",previousSessionFile}})),await this.finishSessionReplacement(),{cancelled:!1}}async dispose(){this.session.background.close(),await Promise.all([this.session.background.shutdown(),this.session.abort()]),await emitSessionShutdownEvent(this.session.extensionRunner,{type:"session_shutdown",reason:"quit"}),this.beforeSessionInvalidate?.(),this.session.dispose()}};async function createAgentSessionRuntime(createRuntime,options){assertSessionCwdExists(options.sessionManager,options.cwd);let result2=await createRuntime(options);return new AgentSessionRuntime(result2.session,result2.services,createRuntime,result2.diagnostics,result2.modelFallbackMessage)}setDefaultStreamFn(streamSimple);function getDefaultAgentDir(){return getAgentDir()}async function createAgentSession(options={}){let cwd=resolvePath(options.cwd??options.sessionManager?.getCwd()??process.cwd()),agentDir=options.agentDir?resolvePath(options.agentDir):getDefaultAgentDir(),resourceLoader=options.resourceLoader,authPath=options.agentDir?join31(agentDir,"auth.json"):void 0,modelsPath=options.agentDir?join31(agentDir,"models.json"):void 0,modelRuntime=options.modelRuntime??await ModelRuntime.create({authPath,modelsPath}),settingsManager=options.settingsManager??SettingsManager.create(cwd,agentDir),sessionManager=options.sessionManager??SessionManager.create(cwd,getDefaultSessionDir(cwd,agentDir));resourceLoader||(resourceLoader=new DefaultResourceLoader({cwd,agentDir,settingsManager}),await resourceLoader.reload(),time("resourceLoader.reload"));let existingSession=sessionManager.buildSessionContext(),hasExistingSession=existingSession.messages.length>0,hasThinkingEntry=sessionManager.getBranch().some(entry=>entry.type==="thinking_level_change"),model=options.model,modelFallbackMessage;if(!model&&hasExistingSession&&existingSession.model){let restoredModel=modelRuntime.getModel(existingSession.model.provider,existingSession.model.modelId);restoredModel&&modelRuntime.hasConfiguredAuth(restoredModel.provider)&&(model=restoredModel),model||(modelFallbackMessage=`Could not restore model ${existingSession.model.provider}/${existingSession.model.modelId}`)}model||(model=(await findInitialModel({scopedModels:[],isContinuing:hasExistingSession,defaultProvider:settingsManager.getDefaultProvider(),defaultModelId:settingsManager.getDefaultModel(),defaultThinkingLevel:settingsManager.getDefaultThinkingLevel(),modelThinkingLevels:settingsManager.getAllModelThinkingLevels(),modelRuntime})).model,model?modelFallbackMessage&&(modelFallbackMessage+=`. Using ${model.provider}/${model.id}`):modelFallbackMessage=formatNoModelsAvailableMessage());let thinkingLevel=options.thinkingLevel;if(thinkingLevel===void 0&&hasExistingSession&&(thinkingLevel=hasThinkingEntry?existingSession.thinkingLevel:settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL),thinkingLevel===void 0&&model){let perModel=settingsManager.getModelThinkingLevel(model.provider,model.id);perModel&&(thinkingLevel=perModel)}thinkingLevel===void 0&&(thinkingLevel=settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL),model?thinkingLevel=clampThinkingLevel(model,thinkingLevel):thinkingLevel="off";let defaultActiveToolNames=["read","bash","edit","write"],configuredDefaultToolNames=settingsManager.getDefaultTools(),allowedToolNames=options.tools??(options.noTools==="all"?[]:void 0),excludedToolNames=options.excludeTools,excludedToolNameSet=excludedToolNames?new Set(excludedToolNames):void 0,initialActiveToolNames=(options.tools??(options.noTools?[]:configuredDefaultToolNames??defaultActiveToolNames)).filter(name=>!excludedToolNameSet?.has(name)),convertToLlmWithBlockImages=messages=>{let converted=convertToLlm(messages);return settingsManager.getBlockImages()?converted.map(msg=>{if(msg.role==="user"||msg.role==="toolResult"){let content=msg.content;if(Array.isArray(content)&&content.some(c=>c.type==="image")){let filteredContent=content.map(c=>c.type==="image"?{type:"text",text:"Image reading is disabled."}:c).filter((c,i,arr)=>!(c.type==="text"&&c.text==="Image reading is disabled."&&i>0&&arr[i-1].type==="text"&&arr[i-1].text==="Image reading is disabled."));return{...msg,content:filteredContent}}}return msg}):converted},extensionRunnerRef={},cacheWarmer=new CacheWarmer(modelRuntime,sessionManager,()=>settingsManager.getCacheWarmingMode(),async event=>extensionRunnerRef.current?.emitCacheWarmingDecision(event)??event.action),buildRequestOptions=(requestModel,options2={})=>{let providerRetrySettings=settingsManager.getProviderRetrySettings(),httpIdleTimeoutMs=settingsManager.getHttpIdleTimeoutMs(),effectiveTimeoutMs=httpIdleTimeoutMs===0?2147483647:httpIdleTimeoutMs,headerRunner=extensionRunnerRef.current;return{...options2,timeoutMs:options2.timeoutMs??providerRetrySettings.timeoutMs??effectiveTimeoutMs,websocketConnectTimeoutMs:options2.websocketConnectTimeoutMs??settingsManager.getWebSocketConnectTimeoutMs(),maxRetries:options2.maxRetries??providerRetrySettings.maxRetries,maxRetryDelayMs:options2.maxRetryDelayMs??providerRetrySettings.maxRetryDelayMs,transformHeaders:async requestHeaders=>{let headers=mergeProviderAttributionHeaders(requestModel,settingsManager,options2.sessionId,requestHeaders);return headerRunner?.hasHandlers("before_provider_headers")?headerRunner.emitBeforeProviderHeaders(headers??{}):headers??{}}}},contextSource=new ContextSnapshotCapture(settingsManager,extensionRunnerRef,buildRequestOptions),cacheContextIsCurrent=requestModel=>{let messages=agent.state.messages;return()=>{let currentModel=agent.state.model,currentMessages=agent.state.messages;return currentModel.provider===requestModel.provider&¤tModel.id===requestModel.id&&messages.length<=currentMessages.length&&messages.every((message,index3)=>currentMessages[index3]===message)}},transformProviderPayload=async payload=>{let runner=extensionRunnerRef.current;return runner?.hasHandlers("before_provider_request")?runner.emitBeforeProviderRequest(payload):payload},handleProviderResponse=async response=>{let runner=extensionRunnerRef.current;runner?.hasHandlers("after_provider_response")&&await runner.emit({type:"after_provider_response",status:response.status,headers:response.headers})},agent=new Agent({initialState:{systemPrompt:"",model,thinkingLevel,tools:[],messages:existingSession.messages},convertToLlm:convertToLlmWithBlockImages,streamFn:async(model2,context,options2)=>{let requestOptions=buildRequestOptions(model2,options2);return options2?.sessionId===sessionManager.getSessionId()&&cacheWarmer.start({model:model2,context,options:requestOptions},cacheContextIsCurrent(model2)),modelRuntime.streamSimple(model2,context,requestOptions)},onPayload:transformProviderPayload,onResponse:handleProviderResponse,sessionId:sessionManager.getSessionId(),transformContext:async messages=>{let runner=extensionRunnerRef.current;return runner?runner.emitContext(messages):messages},steeringMode:settingsManager.getSteeringMode(),followUpMode:settingsManager.getFollowUpMode(),transport:settingsManager.getTransport(),thinkingBudgets:settingsManager.getThinkingBudgets(),maxRetryDelayMs:settingsManager.getProviderRetrySettings().maxRetryDelayMs});hasExistingSession?hasThinkingEntry||sessionManager.appendThinkingLevelChange(thinkingLevel):(model&&sessionManager.appendModelChange(model.provider,model.id),sessionManager.appendThinkingLevelChange(thinkingLevel));let session=new AgentSession({agent,sessionManager,settingsManager,cwd,scopedModels:options.scopedModels,resourceLoader,customTools:options.customTools,modelRuntime,cacheWarmer,initialActiveToolNames,allowedToolNames,excludedToolNames,extensionRunnerRef,contextSource,sessionStartEvent:options.sessionStartEvent,executionRole:options.executionRole});contextSource.install(agent);let extensionsResult=resourceLoader.getExtensions();return{session,extensionsResult,modelFallbackMessage}}var import_proper_lockfile3=__toESM(require_proper_lockfile(),1);import{existsSync as existsSync20,mkdirSync as mkdirSync10,readFileSync as readFileSync14,writeFileSync as writeFileSync8}from"node:fs";import{dirname as dirname20,join as join32}from"node:path";var TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES=["settings.json","extensions","skills","prompts","themes","SYSTEM.md","APPEND_SYSTEM.md"];function normalizeCwd(cwd){return canonicalizePath(resolvePath(cwd))}function findNearestTrustEntry(data,cwd){let currentDir=normalizeCwd(cwd);for(;;){let value2=data[findPathKeys(data,currentDir)[0]??currentDir];if(value2===!0||value2===!1)return{path:currentDir,decision:value2};let parentDir=dirname20(currentDir);if(parentDir===currentDir)return null;currentDir=parentDir}}function getProjectTrustParentPath(cwd){let trustPath=normalizeCwd(cwd),parentDir=dirname20(trustPath);return parentDir===trustPath?void 0:parentDir}function getProjectTrustOptions(cwd,options){let trustPath=normalizeCwd(cwd),trustOptions=[{label:"Trust",trusted:!0,updates:[{path:trustPath,decision:!0}],savedPath:trustPath}],parentPath=getProjectTrustParentPath(cwd);return parentPath!==void 0&&trustOptions.push({label:`Trust parent folder (${parentPath})`,trusted:!0,updates:[{path:parentPath,decision:!0},{path:trustPath,decision:null}],savedPath:parentPath}),options?.includeSessionOnly&&trustOptions.push({label:"Trust (this session only)",trusted:!0,updates:[]}),trustOptions.push({label:"Do not trust",trusted:!1,updates:[{path:trustPath,decision:!1}],savedPath:trustPath}),options?.includeSessionOnly&&trustOptions.push({label:"Do not trust (this session only)",trusted:!1,updates:[]}),trustOptions}function readTrustFile(path14){if(!existsSync20(path14))return{};let parsed;try{parsed=JSON.parse(stripBom(readFileSync14(path14,"utf-8")))}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(`Failed to read trust store ${path14}: ${message}`)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new Error(`Invalid trust store ${path14}: expected an object`);let data={};for(let[key,value2]of Object.entries(parsed)){if(value2!==!0&&value2!==!1&&value2!==null)throw new Error(`Invalid trust store ${path14}: value for ${JSON.stringify(key)} must be true, false, or null`);data[key]=value2}return data}function writeTrustFile(path14,data){let sorted={};for(let key of Object.keys(data).sort()){let value2=data[key];(value2===!0||value2===!1||value2===null)&&(sorted[key]=value2)}mkdirSync10(dirname20(path14),{recursive:!0}),writeFileSync8(path14,`${JSON.stringify(sorted,null,2)}
|
|
1306
1306
|
`,"utf-8")}function acquireTrustLockSync(path14){let trustDir=dirname20(path14);mkdirSync10(trustDir,{recursive:!0});let maxAttempts=10,delayMs=20,lastError;for(let attempt2=1;attempt2<=maxAttempts;attempt2++)try{return import_proper_lockfile3.default.lockSync(trustDir,{realpath:!1,lockfilePath:`${path14}.lock`})}catch(error){if((typeof error=="object"&&error!==null&&"code"in error?String(error.code):void 0)!=="ELOCKED"||attempt2===maxAttempts)throw error;lastError=error;let start=Date.now();for(;Date.now()-start<delayMs;);}throw lastError instanceof Error?lastError:new Error("Failed to acquire trust store lock")}function withTrustFileLock(path14,fn){let release2=acquireTrustLockSync(path14);try{return fn()}finally{release2()}}function hasTrustRequiringProjectResources(cwd){let isUserAgentsSkillsDir=userAgentsSkillsDirMatcher(),currentDir=canonicalizePath(resolvePath(cwd)),configDir=join32(currentDir,CONFIG_DIR_NAME);if(TRUST_REQUIRING_PROJECT_CONFIG_RESOURCES.some(entry=>existsSync20(join32(configDir,entry))))return!0;for(;;){let agentsSkillsDir=join32(currentDir,".agents","skills");if(!isUserAgentsSkillsDir(agentsSkillsDir)&&existsSync20(agentsSkillsDir))return!0;let parentDir=dirname20(currentDir);if(parentDir===currentDir)return!1;currentDir=parentDir}}var ProjectTrustStore=class{constructor(agentDir){this.trustPath=join32(resolvePath(agentDir),"trust.json")}get(cwd){return this.getEntry(cwd)?.decision??null}getEntry(cwd){return withTrustFileLock(this.trustPath,()=>{let data=readTrustFile(this.trustPath);return findNearestTrustEntry(data,cwd)})}set(cwd,decision){this.setMany([{path:cwd,decision}])}setMany(decisions){withTrustFileLock(this.trustPath,()=>{let data=readTrustFile(this.trustPath);for(let{path:path14,decision}of decisions){let key=normalizeCwd(path14);for(let alias of findPathKeys(data,key))alias!==key&&delete data[alias];decision===null?delete data[key]:data[key]=decision}writeTrustFile(this.trustPath,data)})}};import{randomUUID as randomUUID4}from"node:crypto";import{unlinkSync,writeFileSync as writeFileSync9}from"node:fs";import{platform as platform2,tmpdir as tmpdir4}from"node:os";import{join as join33}from"node:path";import{spawn as spawn7}from"node:child_process";function runClipboardCommand(command,args,options){return new Promise(resolve17=>{let child=spawn7(command,args,{stdio:["pipe",options?.input===void 0?"pipe":"ignore","ignore"],windowsHide:!0}),chunks=[],length=0,settled=!1,finish=result2=>{settled||(settled=!0,clearTimeout(timer),resolve17(result2))},abort=()=>{child.kill("SIGKILL"),child.stdout?.destroy(),child.stdin?.destroy(),finish(void 0)},timer=setTimeout(abort,options?.timeoutMs??3e3);child.on("error",()=>finish(void 0)),child.on("close",code=>{settled||finish(code===0?Buffer.concat(chunks,length):void 0)}),child.stdout?.on("data",chunk=>{settled||(length+=chunk.length,length>(options?.maxBufferBytes??50*1024*1024)?abort():chunks.push(chunk))}),child.stdin?.on("error",()=>{}),child.stdin?.end(options?.input)})}import{readFileSync as readFileSync15}from"node:fs";function isWSL(env2=process.env){if(env2.WSL_DISTRO_NAME||env2.WSLENV)return!0;try{let release2=readFileSync15("/proc/version","utf-8");return/microsoft|wsl/i.test(release2)}catch{return!1}}var MAX_OSC52_ENCODED_LENGTH=1e5;function isRemoteSession(env2){return!!(env2.SSH_CONNECTION||env2.SSH_CLIENT||env2.MOSH_CONNECTION)}function emitOsc52(text2){let encoded=Buffer.from(text2).toString("base64");return encoded.length>MAX_OSC52_ENCODED_LENGTH?!1:(process.stdout.write(`\x1B]52;c;${encoded}\x07`),!0)}async function copyViaWindowsClipboard(text2){let tmpFile=join33(tmpdir4(),`pi-wsl-clip-${randomUUID4()}.txt`);try{writeFileSync9(tmpFile,text2,{encoding:"utf8",mode:384});let winPath=(await runClipboardCommand("wslpath",["-w",tmpFile],{timeoutMs:1e3}))?.toString("utf8").trim();if(!winPath)return!1;let script=`Set-Clipboard -Value ([System.IO.File]::ReadAllText('${winPath.replaceAll("'","''")}', [System.Text.Encoding]::UTF8))`;return await runClipboardCommand("powershell.exe",["-NoProfile","-Command",script],{timeoutMs:5e3})!==void 0}catch{return!1}finally{try{unlinkSync(tmpFile)}catch{}}}async function readClipboardText(){if(platform2()==="linux"){let commands=[];process.env.TERMUX_VERSION&&commands.push(["termux-clipboard-get",[]]),process.env.WAYLAND_DISPLAY&&commands.push(["wl-paste",["--no-newline","--type","text"]]),process.env.DISPLAY&&commands.push(["xclip",["-selection","clipboard","-out"]],["xsel",["--clipboard","--output"]]);for(let[command,args]of commands){let bytes=await runClipboardCommand(command,args,{timeoutMs:5e3});if(bytes!==void 0)return bytes.toString("utf8")||null}}try{return await getNativeClipboard()?.getText()||null}catch{return null}}async function copyToClipboard(text2){let p=platform2(),env2=process.env,copied=!1;if(p!=="linux")try{let clipboard=getNativeClipboard();clipboard?.setText&&(await clipboard.setText(text2),copied=!0)}catch{}if(!copied){let commands=[];p==="darwin"?commands.push(["pbcopy",[]]):p==="win32"?commands.push(["clip",[]]):(env2.TERMUX_VERSION&&commands.push(["termux-clipboard-set",[]]),env2.WAYLAND_DISPLAY&&commands.push(["wl-copy",[]]),env2.DISPLAY&&commands.push(["xclip",["-selection","clipboard"]],["xsel",["--clipboard","--input"]]));for(let[command,args]of commands)if(await runClipboardCommand(command,args,{input:text2,timeoutMs:5e3})!==void 0){copied=!0;break}}let osc52Emitted=!1;!copied&&p==="linux"&&isWSL(env2)&&(env2.WT_SESSION&&(osc52Emitted=emitOsc52(text2)),copied=osc52Emitted||await copyViaWindowsClipboard(text2));let headless=p==="linux"&&!env2.DISPLAY&&!env2.WAYLAND_DISPLAY&&!env2.TERMUX_VERSION,oversized=!1;if(!osc52Emitted&&(isRemoteSession(env2)||!copied&&headless)&&(emitOsc52(text2)?copied=!0:oversized=!0),!copied){if(oversized)throw new Error("Clipboard unavailable: text exceeds the OSC 52 size limit");if(p==="linux"){if(env2.TERMUX_VERSION)throw new Error("Clipboard unavailable: install the Termux:API app and `termux-api` package");if(env2.WAYLAND_DISPLAY)throw new Error("Clipboard unavailable: install `wl-clipboard` (`wl-copy`) or check Wayland access");if(env2.DISPLAY)throw new Error("Clipboard unavailable: install `xclip` or `xsel`, or check X11 access")}throw new Error("Clipboard unavailable")}}var BorderedLoader=class extends Container{constructor(tui,theme2,message,options){super(),this.cancellable=options?.cancellable??!0;let borderColor=s=>theme2.fg("border",s);this.addChild(new DynamicBorder(borderColor)),this.cancellable?this.loader=new CancellableLoader(tui,s=>theme2.fg("accent",s),s=>theme2.fg("muted",s),message):(this.signalController=new AbortController,this.loader=new Loader(tui,s=>theme2.fg("accent",s),s=>theme2.fg("muted",s),message)),this.addChild(this.loader),this.cancellable&&(this.addChild(new Spacer(1)),this.addChild(new Text(keyHint("tui.select.cancel","cancel"),1,0))),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(borderColor))}get signal(){return this.cancellable?this.loader.signal:this.signalController?.signal??new AbortController().signal}set onAbort(fn){this.cancellable&&(this.loader.onAbort=fn)}handleInput(data){this.cancellable&&this.loader.handleInput(data)}dispose(){"dispose"in this.loader&&typeof this.loader.dispose=="function"?this.loader.dispose():"stop"in this.loader&&typeof this.loader.stop=="function"&&this.loader.stop()}};var import_cross_spawn2=__toESM(require_cross_spawn(),1);import{mkdtempSync,readFileSync as readFileSync16,rmSync as rmSync3,writeFileSync as writeFileSync10}from"node:fs";import{tmpdir as tmpdir5}from"node:os";import{join as join34}from"node:path";function parseEditorCommand(command){let args=[],current="",quote,started=!1;for(let char of command.trim()){if(quote){char===quote?quote=void 0:current+=char,started=!0;continue}if(char==='"'||char==="'"){quote=char,started=!0;continue}if(/\s/u.test(char)){started&&(args.push(current),current="",started=!1);continue}current+=char,started=!0}return started&&args.push(current),args}async function editInExternalEditor(options){let directory=mkdtempSync(join34(tmpdir5(),"pi-editor-")),filePath=join34(directory,"prompt.md");try{writeFileSync10(filePath,options.content,"utf-8");let[editor,...editorArgs]=parseEditorCommand(options.command);return editor?(process.stdout.write(`Launching external editor: ${options.command}
|
|
1307
1307
|
Pi will resume when the editor exits.
|
|
1308
1308
|
`),await new Promise(resolve17=>{let child=(0,import_cross_spawn2.default)(editor,[...editorArgs,filePath],{stdio:"inherit"});child.on("error",()=>resolve17(null)),child.on("close",code=>resolve17(code))})!==0?{status:"failed"}:{status:"complete",content:stripBom(readFileSync16(filePath,"utf-8")).replace(/\n$/,"")}):{status:"failed"}}finally{try{rmSync3(directory,{recursive:!0,force:!0})}catch{}}}var ExtensionEditorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.editor.focused=value2}constructor(tui,keybindings,title,prefill,onSubmit,onCancel,options,externalEditorCommand){super(),this._focused=!1,this.tui=tui,this.keybindings=keybindings,this.externalEditorCommand=externalEditorCommand||process.env.VISUAL||process.env.EDITOR||(process.platform==="win32"?"notepad":"nano"),this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel;let{description,...editorOptions}=options??{};this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",title),1,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",description),1,0))),this.addChild(new Spacer(1)),this.editor=new Editor(tui,getEditorTheme(),editorOptions),prefill&&this.editor.setText(prefill),this.editor.onSubmit=text2=>{this.onSubmitCallback(text2)},this.addChild(this.editor),this.addChild(new Spacer(1));let hint2=keyHint("tui.select.confirm","submit")+" "+keyHint("tui.input.newLine","newline")+" "+keyHint("tui.select.cancel","cancel")+` ${keyHint("app.editor.external","external editor")}`;this.addChild(new Text(hint2,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){if(getKeybindings().matches(keyData,"tui.select.cancel")){this.onCancelCallback();return}if(this.keybindings.matches(keyData,"app.editor.external")){this.handleOpenExternalEditor();return}this.editor.handleInput(keyData)}async handleOpenExternalEditor(){let content=this.editor.getText();this.tui.stop();try{let result2=await editInExternalEditor({command:this.externalEditorCommand,content});result2.status==="complete"&&this.editor.setText(result2.content)}finally{this.tui.start(),this.tui.requestRender(!0)}}};var WIDTH=31,HEIGHT=36,BITS=[255,255,255,127,255,240,255,127,255,237,255,127,255,219,255,127,255,183,255,127,255,119,254,127,63,248,254,127,223,255,254,127,223,63,252,127,159,195,251,127,111,252,244,127,247,15,247,127,247,255,247,127,247,255,227,127,247,7,232,127,239,248,103,112,15,255,187,111,241,0,208,91,253,63,236,83,193,255,239,87,159,253,238,95,159,252,174,95,31,120,172,95,63,0,80,108,127,0,220,119,255,192,63,120,255,1,248,127,255,3,156,120,255,7,140,124,255,15,206,120,255,255,207,127,255,255,207,120,255,255,223,120,255,255,223,125,255,255,63,126,255,255,255,127],BYTES_PER_ROW=Math.ceil(WIDTH/8),DISPLAY_HEIGHT=Math.ceil(HEIGHT/2),EFFECTS=["typewriter","scanline","rain","fade","crt","glitch","dissolve"];function getPixel(x2,y2){if(y2>=HEIGHT)return!1;let byteIndex=y2*BYTES_PER_ROW+Math.floor(x2/8),bitIndex=x2%8;return(BITS[byteIndex]>>bitIndex&1)===0}function getChar(x2,row){let upper=getPixel(x2,row*2),lower=getPixel(x2,row*2+1);return upper&&lower?"\u2588":upper?"\u2580":lower?"\u2584":" "}function buildFinalGrid(){let grid=[];for(let row=0;row<DISPLAY_HEIGHT;row++){let line=[];for(let x2=0;x2<WIDTH;x2++)line.push(getChar(x2,row));grid.push(line)}return grid}var ArminComponent=class{constructor(ui){this.interval=null,this.effectState={},this.cachedLines=[],this.cachedWidth=0,this.gridVersion=0,this.cachedVersion=-1,this.ui=ui,this.effect=EFFECTS[Math.floor(Math.random()*EFFECTS.length)],this.finalGrid=buildFinalGrid(),this.currentGrid=this.createEmptyGrid(),this.initEffect(),this.startAnimation()}invalidate(){this.cachedWidth=0}render(width){if(width===this.cachedWidth&&this.cachedVersion===this.gridVersion)return this.cachedLines;let padding=1,availableWidth=width-padding;this.cachedLines=this.currentGrid.map(row=>{let clipped=row.slice(0,availableWidth).join(""),padRight=Math.max(0,width-padding-clipped.length);return` ${theme.fg("accent",clipped)}${" ".repeat(padRight)}`});let message="ARMIN SAYS HI",msgPadRight=Math.max(0,width-padding-message.length);return this.cachedLines.push(` ${theme.fg("accent",message)}${" ".repeat(msgPadRight)}`),this.cachedWidth=width,this.cachedVersion=this.gridVersion,this.cachedLines}createEmptyGrid(){return Array.from({length:DISPLAY_HEIGHT},()=>Array(WIDTH).fill(" "))}initEffect(){switch(this.effect){case"typewriter":this.effectState={pos:0};break;case"scanline":this.effectState={row:0};break;case"rain":this.effectState={drops:Array.from({length:WIDTH},()=>({y:-Math.floor(Math.random()*DISPLAY_HEIGHT*2),settled:0}))};break;case"fade":{let positions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)positions.push([row,x2]);for(let i=positions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[positions[i],positions[j2]]=[positions[j2],positions[i]]}this.effectState={positions,idx:0};break}case"crt":this.effectState={expansion:0};break;case"glitch":this.effectState={phase:0,glitchFrames:8};break;case"dissolve":{this.currentGrid=Array.from({length:DISPLAY_HEIGHT},()=>Array.from({length:WIDTH},()=>{let chars=[" ","\u2591","\u2592","\u2593","\u2588","\u2580","\u2584"];return chars[Math.floor(Math.random()*chars.length)]}));let dissolvePositions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)dissolvePositions.push([row,x2]);for(let i=dissolvePositions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[dissolvePositions[i],dissolvePositions[j2]]=[dissolvePositions[j2],dissolvePositions[i]]}this.effectState={positions:dissolvePositions,idx:0};break}}}startAnimation(){let fps=this.effect==="glitch"?60:30;this.interval=setInterval(()=>{let done=this.tickEffect();this.updateDisplay(),this.ui.requestRender(),done&&this.stopAnimation()},1e3/fps)}stopAnimation(){this.interval&&(clearInterval(this.interval),this.interval=null)}tickEffect(){switch(this.effect){case"typewriter":return this.tickTypewriter();case"scanline":return this.tickScanline();case"rain":return this.tickRain();case"fade":return this.tickFade();case"crt":return this.tickCrt();case"glitch":return this.tickGlitch();case"dissolve":return this.tickDissolve();default:return!0}}tickTypewriter(){let state2=this.effectState,pixelsPerFrame=3;for(let i=0;i<pixelsPerFrame;i++){let row=Math.floor(state2.pos/WIDTH),x2=state2.pos%WIDTH;if(row>=DISPLAY_HEIGHT)return!0;this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.pos++}return!1}tickScanline(){let state2=this.effectState;if(state2.row>=DISPLAY_HEIGHT)return!0;for(let x2=0;x2<WIDTH;x2++)this.currentGrid[state2.row][x2]=this.finalGrid[state2.row][x2];return state2.row++,!1}tickRain(){let state2=this.effectState,allSettled=!0;this.currentGrid=this.createEmptyGrid();for(let x2=0;x2<WIDTH;x2++){let drop=state2.drops[x2];for(let row=DISPLAY_HEIGHT-1;row>=DISPLAY_HEIGHT-drop.settled;row--)row>=0&&(this.currentGrid[row][x2]=this.finalGrid[row][x2]);if(drop.settled>=DISPLAY_HEIGHT)continue;allSettled=!1;let targetRow=-1;for(let row=DISPLAY_HEIGHT-1-drop.settled;row>=0;row--)if(this.finalGrid[row][x2]!==" "){targetRow=row;break}drop.y++,drop.y>=0&&drop.y<DISPLAY_HEIGHT&&(targetRow>=0&&drop.y>=targetRow?(drop.settled=DISPLAY_HEIGHT-targetRow,drop.y=-Math.floor(Math.random()*5)-1):this.currentGrid[drop.y][x2]="\u2593")}return allSettled}tickFade(){let state2=this.effectState,pixelsPerFrame=15;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}tickCrt(){let state2=this.effectState,midRow=Math.floor(DISPLAY_HEIGHT/2);this.currentGrid=this.createEmptyGrid();let top=midRow-state2.expansion,bottom=midRow+state2.expansion;for(let row=Math.max(0,top);row<=Math.min(DISPLAY_HEIGHT-1,bottom);row++)for(let x2=0;x2<WIDTH;x2++)this.currentGrid[row][x2]=this.finalGrid[row][x2];return state2.expansion++,state2.expansion>DISPLAY_HEIGHT}tickGlitch(){let state2=this.effectState;return state2.phase<state2.glitchFrames?(this.currentGrid=this.finalGrid.map(row=>{let offset=Math.floor(Math.random()*7)-3,glitchRow=[...row];if(Math.random()<.3)return glitchRow.slice(offset).concat(glitchRow.slice(0,offset)).slice(0,WIDTH);if(Math.random()<.2){let swapRow=Math.floor(Math.random()*DISPLAY_HEIGHT);return[...this.finalGrid[swapRow]]}return glitchRow}),state2.phase++,!1):(this.currentGrid=this.finalGrid.map(row=>[...row]),!0)}tickDissolve(){let state2=this.effectState,pixelsPerFrame=20;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}updateDisplay(){this.gridVersion++}dispose(){this.stopAnimation()}};function createMarkdownTransform(messageType,isStreaming,transformers){return(markdown,availableWidth)=>applyMarkdownTransformers(markdown,{messageType,isStreaming,availableWidth},transformers)}function applyMarkdownTransformers(markdown,context,transformers){let transformedMarkdown=markdown;for(let transformer of transformers)try{let transformed=transformer(transformedMarkdown,context);typeof transformed=="string"&&(transformedMarkdown=transformed)}catch{}return transformedMarkdown}var OSC133_ZONE_START="\x1B]133;A\x07",OSC133_ZONE_END="\x1B]133;B\x07",OSC133_ZONE_FINAL="\x1B]133;C\x07",AssistantMessageComponent=class extends Container{constructor(message,hideThinkingBlock=!1,markdownTheme=getMarkdownTheme(),hiddenThinkingLabel="Thinking...",outputPad=1,markdownTransformers=[]){super(),this.hasToolCalls=!1,this.isStreaming=!1,this.thinkingVisibilityOverrides=new Map,this.hideThinkingBlock=hideThinkingBlock,this.markdownTheme=markdownTheme,this.hiddenThinkingLabel=hiddenThinkingLabel,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.contentContainer=new Container,this.addChild(this.contentContainer),message&&this.updateContent(message)}invalidate(){super.invalidate(),this.lastMessage&&this.updateContent(this.lastMessage)}setHideThinkingBlock(hide){this.hideThinkingBlock=hide,this.thinkingVisibilityOverrides.clear(),this.lastMessage&&this.updateContent(this.lastMessage)}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label,this.lastMessage&&this.updateContent(this.lastMessage)}setOutputPad(padding){this.outputPad=padding,this.lastMessage&&this.updateContent(this.lastMessage)}render(width){let lines=super.render(width);return this.hasToolCalls||lines.length===0||(lines[0]=OSC133_ZONE_START+lines[0],lines[lines.length-1]=OSC133_ZONE_END+OSC133_ZONE_FINAL+lines[lines.length-1]),lines}updateContent(message,isStreaming=this.isStreaming){this.lastMessage=message,this.isStreaming=isStreaming,this.contentContainer.clear(),message.content.some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim())&&this.contentContainer.addChild(new Spacer(1));let thinkingRunIndex=0;for(let i=0;i<message.content.length;i++){let content=message.content[i];if(content.type==="text"&&content.text.trim())this.contentContainer.addChild(new Markdown(content.text.trim(),this.outputPad,0,this.markdownTheme,void 0,{transform:createMarkdownTransform("assistant",this.isStreaming,this.markdownTransformers)}));else if(content.type==="thinking"){let thinkingBlocks=[];for(;i<message.content.length;i++){let thinkingContent=message.content[i];if(thinkingContent.type!=="thinking")break;let thinking=thinkingContent.thinking.trim();thinking&&thinkingBlocks.push(thinking)}if(i--,thinkingBlocks.length===0)continue;let hasVisibleContentAfter=message.content.slice(i+1).some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim()),runIndex=thinkingRunIndex++,hidden=this.thinkingVisibilityOverrides.get(runIndex)??this.hideThinkingBlock,thinkingComponent=hidden?new Text(theme.italic(theme.fg("thinkingText",this.hiddenThinkingLabel)),this.outputPad,0):new Markdown(thinkingBlocks.join(`
|
|
@@ -1327,10 +1327,10 @@ ${statusParts.join(`
|
|
|
1327
1327
|
`),this.box.addChild(new Markdown(text2,0,0,this.markdownTheme,{color:text3=>theme.fg("customMessageText",text3)}))}};import{isAbsolute as isAbsolute5,relative as relative6,resolve as resolve11,sep as sep10}from"node:path";function areExperimentalFeaturesEnabled(){return process.env.PI_EXPERIMENTAL==="1"}function sanitizeStatusText(text2){return text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()}function formatTokens(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function formatCwdForFooter(cwd,home){if(!home)return cwd;let resolvedCwd=resolve11(cwd),resolvedHome=resolve11(home),relativeToHome=relative6(resolvedHome,resolvedCwd);return relativeToHome===""||relativeToHome!==".."&&!relativeToHome.startsWith(`..${sep10}`)&&!isAbsolute5(relativeToHome)?relativeToHome===""?"~":`~${sep10}${relativeToHome}`:cwd}var FooterComponent=class{constructor(session,footerData){this.autoCompactEnabled=!0,this.session=session,this.footerData=footerData}setSession(session){this.session=session}setAutoCompactEnabled(enabled){this.autoCompactEnabled=enabled}invalidate(){}dispose(){}render(width){let state2=this.session.state,usageTotals=createUsageTotals(),latestCacheHitRate,entries=this.session.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant"){let latestPromptTokens=entry.message.usage.input+entry.message.usage.cacheRead+entry.message.usage.cacheWrite;latestCacheHitRate=latestPromptTokens>0?entry.message.usage.cacheRead/latestPromptTokens*100:void 0}let contextUsage=this.session.getContextUsage(),contextWindow=contextUsage?.contextWindow??state2.model?.contextWindow??0,contextPercentValue=contextUsage?.percent??0,contextPercent=contextUsage?.percent!==null?contextPercentValue.toFixed(1):"?",pwd=formatCwdForFooter(this.session.sessionManager.getCwd(),process.env.HOME||process.env.USERPROFILE),branch=this.footerData.getGitBranch();branch&&(pwd=`${pwd} (${branch})`);let sessionName2=this.session.sessionManager.getSessionName();sessionName2&&(pwd=`${pwd} \u2022 ${sessionName2}`);let statsParts=[];usageTotals.input&&statsParts.push(`\u2191${formatTokens(usageTotals.input)}`),usageTotals.output&&statsParts.push(`\u2193${formatTokens(usageTotals.output)}`),usageTotals.cacheRead&&statsParts.push(`R${formatTokens(usageTotals.cacheRead)}`),usageTotals.cacheWrite&&statsParts.push(`W${formatTokens(usageTotals.cacheWrite)}`),(usageTotals.cacheRead>0||usageTotals.cacheWrite>0)&&latestCacheHitRate!==void 0&&statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);let usingSubscription=state2.model?state2.model.provider==="kimi-coding"||this.session.modelRuntime.isUsingSubscription(state2.model.provider):!1;if(usageTotals.cost||usingSubscription){let costStr=`$${usageTotals.cost.toFixed(3)}${usingSubscription?" (sub)":""}`;statsParts.push(costStr)}let contextPercentStr,autoIndicator=this.autoCompactEnabled?" (auto)":"",contextPercentDisplay=contextPercent==="?"?`?/${formatTokens(contextWindow)}${autoIndicator}`:`${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;contextPercentValue>90?contextPercentStr=theme.fg("error",contextPercentDisplay):contextPercentValue>70?contextPercentStr=theme.fg("warning",contextPercentDisplay):contextPercentStr=contextPercentDisplay,statsParts.push(contextPercentStr),areExperimentalFeaturesEnabled()&&statsParts.push(`${theme.fg("dim","\u2022")} ${theme.bold(theme.fg("warning","xp"))}`);let statsLeft=statsParts.join(" "),modelName=state2.model?.id||"no-model",statsLeftWidth=visibleWidth(statsLeft);statsLeftWidth>width&&(statsLeft=truncateToWidth(statsLeft,width,"..."),statsLeftWidth=visibleWidth(statsLeft));let minPadding=2,rightSideWithoutProvider=modelName;if(state2.model?.reasoning){let thinkingLevel=state2.thinkingLevel||"off";rightSideWithoutProvider=thinkingLevel==="off"?`${modelName} \u2022 thinking off`:`${modelName} \u2022 ${thinkingLevel}`}let rightSide=rightSideWithoutProvider;this.footerData.getAvailableProviderCount()>1&&state2.model&&(rightSide=`(${state2.model.provider}) ${rightSideWithoutProvider}`,statsLeftWidth+minPadding+visibleWidth(rightSide)>width&&(rightSide=rightSideWithoutProvider));let rightSideWidth=visibleWidth(rightSide),totalNeeded=statsLeftWidth+minPadding+rightSideWidth,statsLine;if(totalNeeded<=width){let padding=" ".repeat(width-statsLeftWidth-rightSideWidth);statsLine=statsLeft+padding+rightSide}else{let availableForRight=width-statsLeftWidth-minPadding;if(availableForRight>0){let truncatedRight=truncateToWidth(rightSide,availableForRight,""),truncatedRightWidth=visibleWidth(truncatedRight),padding=" ".repeat(Math.max(0,width-statsLeftWidth-truncatedRightWidth));statsLine=statsLeft+padding+truncatedRight}else statsLine=statsLeft}let dimStatsLeft=theme.fg("dim",statsLeft),remainder=statsLine.slice(statsLeft.length),dimRemainder=theme.fg("dim",remainder),lines=[truncateToWidth(theme.fg("dim",pwd),width,theme.fg("dim","...")),dimStatsLeft+dimRemainder],extensionStatuses=this.footerData.getExtensionStatuses();if(extensionStatuses.size>0){let statusLine=Array.from(extensionStatuses.entries()).sort(([a],[b2])=>a.localeCompare(b2)).map(([,text2])=>sanitizeStatusText(text2)).join(" ");lines.push(truncateToWidth(statusLine,width,theme.fg("dim","...")))}return lines}};import{spawn as spawn9}from"node:child_process";function openBrowser(target){let[cmd,args]=process.platform==="darwin"?["open",[target]]:process.platform==="win32"?["rundll32",["url.dll,FileProtocolHandler",target]]:["xdg-open",[target]];spawn9(cmd,args,{stdio:"ignore",detached:!0}).on("error",()=>{}).unref()}var LoginDialogComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.input.focused=value2}constructor(tui,providerId,onComplete,providerNameOverride,titleOverride){super(),this.abortController=new AbortController,this._focused=!1,this.tui=tui,this.onComplete=onComplete;let title=titleOverride??`Login to ${providerNameOverride||providerId}`;this.addChild(new DynamicBorder),this.addChild(new Text(theme.fg("accent",theme.bold(title)),1,0)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.input=new Input,this.input.onSubmit=()=>{if(this.inputResolver){let value2=this.input.getValue();this.replaceInputWithSubmittedText(value2),this.inputResolver(value2),this.inputResolver=void 0,this.inputRejecter=void 0}},this.input.onEscape=()=>{this.cancel()},this.addChild(new DynamicBorder)}get signal(){return this.abortController.signal}replaceInputWithSubmittedText(value2){this.contentContainer.children=this.contentContainer.children.map(child=>child===this.input?new Text(`> ${value2}`,0,0):child)}cancel(){this.abortController.abort(),this.inputRejecter&&(this.inputRejecter(new Error("Login cancelled")),this.inputResolver=void 0,this.inputRejecter=void 0),this.onComplete(!1,"Login cancelled")}showAuth(url,instructions){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${url}\x07${url}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?"Cmd+click to open":"Ctrl+click to open",hyperlink2=`\x1B]8;;${url}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),instructions&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",instructions),1,0))),openBrowser(url),this.tui.requestRender()}showDeviceCode(info){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${info.verificationUri}\x07${info.verificationUri}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?"Cmd+click to open":"Ctrl+click to open",hyperlink2=`\x1B]8;;${info.verificationUri}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",`Enter code: ${info.userCode}`),1,0)),this.tui.requestRender()}showManualInput(prompt){return this.input.setValue(""),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",prompt),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender(),new Promise((resolve17,reject)=>{this.inputResolver=resolve17,this.inputRejecter=reject})}showPrompt(message,placeholder){return this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0)),placeholder&&this.contentContainer.addChild(new Text(theme.fg("dim",`e.g., ${placeholder}`),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel,")} ${keyHint("tui.select.confirm","to submit")})`,1,0)),this.input.setValue(""),this.tui.requestRender(),new Promise((resolve17,reject)=>{this.inputResolver=resolve17,this.inputRejecter=reject})}showDetails(lines){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));for(let line of lines)this.contentContainer.addChild(new Text(line,1,0));this.tui.requestRender()}showInfo(message,links=[],showCloseHint=!1){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0));for(let link of links){let text2=link.label?`${link.label}: ${link.url}`:link.url,hyperlink2=`\x1B]8;;${link.url}\x07${text2}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",hyperlink2),1,0))}showCloseHint&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to close")})`,1,0))),this.tui.requestRender()}showWaiting(message){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender()}showProgress(message){this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.tui.requestRender()}handleInput(data){if(getKeybindings().matches(data,"tui.select.cancel")){this.cancel();return}this.input.handleInput(data)}};var ModelCatalogRefreshCoordinator=class{constructor(){this.activeByRuntime=new WeakMap}refresh(modelRuntime,signal){signal.throwIfAborted();let active=this.activeByRuntime.get(modelRuntime);if(!active){let controller=new AbortController,created,operation=modelRuntime.refresh({signal:controller.signal}),promise=raceWithAbortSignal(operation,controller.signal).finally(()=>{this.activeByRuntime.get(modelRuntime)===created&&this.activeByRuntime.delete(modelRuntime)});created={controller,promise,waiters:0},active=created,this.activeByRuntime.set(modelRuntime,active)}return active.waiters++,raceWithAbortSignal(active.promise,signal).finally(()=>{active.waiters--,active.waiters===0&&this.activeByRuntime.get(modelRuntime)===active&&active.controller.abort()})}},modelCatalogRefreshCoordinator=new ModelCatalogRefreshCoordinator;function refreshModelCatalogs(modelRuntime,signal){return modelCatalogRefreshCoordinator.refresh(modelRuntime,signal)}function getModelSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${id} ${provider} ${provider}/${id} ${provider} ${id}${name}`}function getModelSelectorSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${provider} ${provider}/${id} ${provider} ${id}${name}`}var ModelSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(tui,currentModel,modelRuntime,scopedModels,onSelect,onCancel,initialSearchInput,onSelectAsDefault,defaultModel){if(super(),this._focused=!1,this.allModels=[],this.scopedModelItems=[],this.activeModels=[],this.filteredModels=[],this.selectedIndex=0,this.refreshStatusMessage="Refreshing model catalogs\u2026",this.refreshStatusSuccess=!1,this.scope="all",this.refreshAbortController=new AbortController,this.closed=!1,this.tui=tui,this.currentModel=currentModel,this.modelRuntime=modelRuntime,this.scopedModels=scopedModels,this.defaultModel=defaultModel,this.scope=scopedModels.length>0?"scoped":"all",this.onSelectCallback=onSelect,this.onSelectAsDefaultCallback=onSelectAsDefault,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),scopedModels.length>0)this.scopeText=new Text(this.getScopeText(),0,0),this.addChild(this.scopeText),this.scopeHintText=new Text(this.getScopeHintText(),0,0),this.addChild(this.scopeHintText);else{let hintText="Only showing models from configured providers. Use /login to add providers.";this.addChild(new Text(theme.fg("warning",hintText),0,0))}this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{this.filteredModels[this.selectedIndex]&&this.handleSelect(this.filteredModels[this.selectedIndex].model)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.onSelectAsDefaultCallback&&this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.models.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder),this.loadModelsFromSnapshot(),initialSearchInput?this.filterModels(initialSearchInput):this.updateList(),this.tui.requestRender(),this.refreshModels()}loadModelsFromSnapshot(){let models=this.modelRuntime.getAvailableSnapshot().map(model=>({provider:model.provider,id:model.id,model}));this.allModels=this.sortModels(models),this.scopedModels=this.scopedModels.map(scoped=>{let refreshed=this.modelRuntime.getModel(scoped.model.provider,scoped.model.id);return refreshed?{...scoped,model:refreshed}:scoped}),this.scopedModelItems=this.scopedModels.map(scoped=>({provider:scoped.model.provider,id:scoped.model.id,model:scoped.model})),this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels,this.filteredModels=this.activeModels;let currentIndex=this.filteredModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1))}async refreshModels(){let timedOut=!1;this.refreshTimeout=setTimeout(()=>{timedOut=!0,this.refreshAbortController.abort()},15e3);try{let result2=await refreshModelCatalogs(this.modelRuntime,this.refreshAbortController.signal);if(this.closed)return;this.refreshStatusMessage="",result2.aborted&&timedOut?this.errorMessage="Model refresh timed out; showing cached models.":result2.errors.size===1?this.errorMessage=`Could not refresh ${result2.errors.keys().next().value}; showing cached models.`:result2.errors.size>1?this.errorMessage=`Could not refresh ${result2.errors.size} model catalogs (${[...result2.errors.keys()].join(", ")}); showing cached models.`:(this.errorMessage=this.modelRuntime.getError(),this.errorMessage||(this.refreshStatusMessage="Model catalogs refreshed.",this.refreshStatusSuccess=!0)),this.loadModelsFromSnapshot(),this.filterModels(this.searchInput.getValue()),this.tui.requestRender()}catch(error){if(this.closed)return;this.refreshStatusMessage="",this.errorMessage=timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,this.updateList(),this.tui.requestRender()}finally{this.refreshTimeout&&clearTimeout(this.refreshTimeout)}}dispose(){this.closed||(this.closed=!0,this.refreshTimeout&&clearTimeout(this.refreshTimeout),this.refreshAbortController.abort())}sortModels(models){let sorted=[...models];return sorted.sort((a,b2)=>{let aIsCurrent=modelsAreEqual(this.currentModel,a.model),bIsCurrent=modelsAreEqual(this.currentModel,b2.model);if(aIsCurrent&&!bIsCurrent)return-1;if(!aIsCurrent&&bIsCurrent)return 1;let aIsDefault=this.isDefaultModel(a.model),bIsDefault=this.isDefaultModel(b2.model);return aIsDefault&&!bIsDefault?-1:!aIsDefault&&bIsDefault?1:a.provider.localeCompare(b2.provider)}),sorted}getScopeText(){let allText=this.scope==="all"?theme.fg("accent","all"):theme.fg("muted","all"),scopedText=this.scope==="scoped"?theme.fg("accent","scoped"):theme.fg("muted","scoped");return`${theme.fg("muted","Scope: ")}${allText}${theme.fg("muted"," | ")}${scopedText}`}getScopeHintText(){return keyHint("tui.input.tab","scope")+theme.fg("muted"," (all/scoped)")}isDefaultModel(model){return this.defaultModel?.provider===model.provider&&this.defaultModel.id===model.id}isDefaultSearch(query){let normalized=query.trim().toLowerCase();return normalized.length>0&&"default".startsWith(normalized)}setScope(scope){if(this.scope===scope)return;this.scope=scope,this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels;let currentIndex=this.activeModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:0,this.filterModels(this.searchInput.getValue()),this.scopeText&&this.scopeText.setText(this.getScopeText())}filterModels(query){if(query){let filtered=fuzzyFilter(this.activeModels,query,item=>{let defaultText=this.isDefaultModel(item.model)?" default":"";return`${getModelSelectorSearchText({id:item.id,provider:item.provider,name:item.model.name})}${defaultText}`});if(this.isDefaultSearch(query)){let defaultItems=this.activeModels.filter(item=>this.isDefaultModel(item.model)),defaultKeys=new Set(defaultItems.map(item=>`${item.provider}\0${item.id}`));this.filteredModels=[...defaultItems,...filtered.filter(item=>!defaultKeys.has(`${item.provider}\0${item.id}`))]}else this.filteredModels=filtered}else this.filteredModels=this.activeModels;this.selectedIndex=query?0:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1)),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=10,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredModels.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredModels.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredModels[i];if(!item)continue;let isSelected=i===this.selectedIndex,isCurrent=modelsAreEqual(this.currentModel,item.model),defaultBadge=this.isDefaultModel(item.model)?theme.fg("muted"," \xB7 default"):"",cursor=isSelected?theme.fg("accent","\u2192 "):" ",currentMarker=isCurrent?theme.fg("accent","\u2713 "):" ",modelText2=isSelected?theme.fg("accent",item.id):item.id,providerBadge=theme.fg("muted",`[${item.provider}]`),line=`${cursor}${currentMarker}${modelText2} ${providerBadge}${defaultBadge}`;this.listContainer.addChild(new Text(line,0,0))}if(startIndex>0||endIndex<this.filteredModels.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredModels.length})`);this.listContainer.addChild(new Text(scrollInfo,0,0))}if(this.errorMessage){let errorLines=this.errorMessage.split(`
|
|
1328
1328
|
`);for(let line of errorLines)this.listContainer.addChild(new Text(theme.fg("error",line),0,0))}else if(this.filteredModels.length===0)this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));else{let selected=this.filteredModels[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` Model Name: ${selected.model.name}`),0,0))}this.refreshStatusMessage&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg(this.refreshStatusSuccess?"success":"muted",` ${this.refreshStatusMessage}`),0,0)))}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.input.tab")){if(this.scopedModelItems.length>0){let nextScope=this.scope==="all"?"scoped":"all";this.setScope(nextScope),this.scopeHintText&&this.scopeHintText.setText(this.getScopeHintText())}return}if(kb.matches(keyData,"tui.select.up")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredModels.length-1:this.selectedIndex-1,this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredModels.length-1?0:this.selectedIndex+1,this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&this.handleSelect(selectedModel.model)}else if(kb.matches(keyData,"tui.select.cancel"))this.dispose(),this.onCancelCallback();else if(kb.matches(keyData,"app.models.save")&&this.onSelectAsDefaultCallback){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&(this.dispose(),this.onSelectAsDefaultCallback(selectedModel.model))}else this.searchInput.handleInput(keyData),this.filterModels(this.searchInput.getValue())}handleSelect(model){this.dispose(),this.onSelectCallback(model)}getSearchInput(){return this.searchInput}};function formatAuthSelectorProviderType(authType){return authType==="oauth"?"subscription":"API key"}var OAuthSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(mode,providers,onSelect,onCancel,initialSearchInput){super(),this._focused=!1,this.selectedIndex=0,this.mode=mode,this.allProviders=providers,this.filteredProviders=providers,this.showAuthTypeLabels=new Set(providers.map(provider=>provider.authType)).size>1,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1));let title=mode==="login"?"Select provider to configure:":"Select provider to logout:";this.addChild(new TruncatedText(theme.fg("accent",theme.bold(title)),1,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.filterProviders(initialSearchInput??"")}filterProviders(query){this.filteredProviders=query?fuzzyFilter(this.allProviders,query,provider=>`${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name??""}`):this.allProviders,this.selectedIndex=Math.max(0,Math.min(this.selectedIndex,Math.max(0,this.filteredProviders.length-1))),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=8,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredProviders.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredProviders.length);for(let i=startIndex;i<endIndex;i++){let provider=this.filteredProviders[i];if(!provider)continue;let isSelected=i===this.selectedIndex,statusIndicator=this.formatStatusIndicator(provider),authTypeLabel=this.showAuthTypeLabels?theme.fg("muted",` [${formatAuthSelectorProviderType(provider.authType)}]`):"",line="";if(isSelected){let prefix=theme.fg("accent","\u2192 "),text2=theme.fg("accent",provider.name);line=prefix+text2+authTypeLabel+statusIndicator}else line=` ${theme.fg("text",provider.name)}`+authTypeLabel+statusIndicator;this.listContainer.addChild(new TruncatedText(line,1,0))}if(startIndex>0||endIndex<this.filteredProviders.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredProviders.length})`);this.listContainer.addChild(new TruncatedText(scrollInfo,1,0))}if(this.filteredProviders.length===0){let message=this.allProviders.length===0?this.mode==="login"?"No providers available":"No providers logged in. Use /login first.":"No matching providers";this.listContainer.addChild(new TruncatedText(theme.fg("muted",` ${message}`),1,0))}}formatStatusIndicator(provider){if(!provider.status)return theme.fg("muted"," \u2022 unconfigured");if(provider.status.type!==provider.authType){let label=provider.status.type==="oauth"?"subscription configured":"API key configured";return theme.fg("muted"," \u2022 ")+theme.fg("warning",label)}if(!provider.status.source||provider.status.source==="OAuth"||provider.status.source==="stored credential")return theme.fg("success"," \u2713 configured");let source=/^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)?`env: ${provider.status.source}`:provider.status.source;return theme.fg("success",` \u2713 ${source}`)}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.min(this.filteredProviders.length-1,this.selectedIndex+1),this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)}else kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():(this.searchInput.handleInput(keyData),this.filterProviders(this.searchInput.getValue()))}};var SUBMENU_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},SelectSubmenu=class extends Container{constructor(title,description,options,currentValue,onSelect,onCancel,onSelectionChange,submenuOptions){super(),this.allOptions=options,this.listLayout=submenuOptions?.layout??SUBMENU_SELECT_LIST_LAYOUT,this.onSelectCb=onSelect,this.onCancelCb=onCancel,this.onSelectionChangeCb=onSelectionChange,this.addChild(new Text(theme.bold(theme.fg("accent",title)),0,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",description),0,0))),submenuOptions?.searchable&&(this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>{this.selectList.handleInput("\r")},this.addChild(this.searchInput)),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(options,currentValue),this.listChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1));let hint2=submenuOptions?.searchable?" Type to filter \xB7 Enter to select \xB7 Esc to go back":" Enter to select \xB7 Esc to go back";this.addChild(new Text(theme.fg("dim",hint2),0,0))}buildSelectList(options,preselect){let list2=new SelectList(options,Math.min(options.length,10),getSelectListTheme(),this.listLayout),idx=options.findIndex(o=>o.value===preselect);if(idx!==-1&&list2.setSelectedIndex(idx),list2.onSelect=item=>this.onSelectCb(item.value),list2.onCancel=this.onCancelCb,this.onSelectionChangeCb){let cb=this.onSelectionChangeCb;list2.onSelectionChange=item=>cb(item.value)}return list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allOptions,query,item=>`${item.label} ${item.description??""}`):this.allOptions,newList=this.buildSelectList(filtered,"");this.children[this.listChildIndex]=newList,this.selectList=newList}handleInput(data){if(this.searchInput){let kb=getKeybindings();kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")?this.selectList.handleInput(data):(this.searchInput.handleInput(data),this.applyFilter(this.searchInput.getValue()))}else this.selectList.handleInput(data)}},SteppedSubmenu=class extends Container{constructor(steps,onComplete,onCancel,opts={}){super(),this.steps=steps,this.onComplete=onComplete,this.onCancel=onCancel,this.opts=opts,this.context={...opts.initialContext??{}},this.activeComponent=this.buildStep(opts.startAtStep??0)}buildStep(stepIndex){let step=this.steps[stepIndex],total=this.steps.length,stepLabel=total>1?`Step ${stepIndex+1}/${total} \xB7 `:"",title=typeof step.title=="function"?step.title(this.context):step.title,desc=typeof step.description=="function"?step.description(this.context):step.description,items=step.options(this.context),preselect=step.preselect?.(this.context)??"";return new SelectSubmenu(title,`${stepLabel}${desc}`,items,preselect,value2=>{this.context[step.key]=value2,stepIndex<total-1?this.activeComponent=this.buildStep(stepIndex+1):(this.onComplete({...this.context}),this.opts.loop?(this.context={},this.activeComponent=this.buildStep(0)):this.onCancel())},()=>{stepIndex>0?(delete this.context[step.key],this.activeComponent=this.buildStep(stepIndex-1)):this.onCancel()},void 0,step.searchable||step.layout?{searchable:step.searchable,layout:step.layout}:void 0)}render(width){return this.activeComponent.render(width)}handleInput(data){this.activeComponent.handleInput?.(data)}invalidate(){this.activeComponent.invalidate?.()}};var MODEL_PICKER_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:46},THINKING_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},DEFAULT_PROJECT_TRUST_LABELS={ask:"Ask",always:"Always trust",never:"Never trust"},DEFAULT_PROJECT_TRUST_BY_LABEL=new Map(Object.entries(DEFAULT_PROJECT_TRUST_LABELS).map(([value2,label])=>[label,value2])),WarningSettingsSubmenu=class extends Container{constructor(warnings,onChange,onCancel){super(),this.state={...warnings};let items=[{id:"anthropic-extra-usage",label:"Anthropic extra usage",description:"Warn when Anthropic subscription auth may use paid extra usage",currentValue:this.state.anthropicExtraUsage??!0?"true":"false",values:["true","false"]}];this.settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),(id,newValue)=>{id==="anthropic-extra-usage"&&(this.state={...this.state,anthropicExtraUsage:newValue==="true"},onChange({...this.state}))},onCancel),this.addChild(this.settingsList)}handleInput(data){this.settingsList.handleInput(data)}},CLEAR_OVERRIDE_VALUE="__clear__";function modelSettingKey(model){return`${model.provider}/${model.id}`}function modelDisplayLabel(model){return`${model.id} [${model.provider}]`}function modelThinkingOverridesSummary(overrides){let count=Object.keys(overrides).length;return count===0?"none":`${count} configured`}function modelItemLabel(model){return`${model.id} ${theme.fg("muted",`[${model.provider}]`)}`}function themeItems(availableThemes,currentTheme){return availableThemes.map(name=>({value:name,label:`${name===currentTheme?"\u2713 ":" "}${name}`}))}var AUTOMATIC_THEME_VALUE="/";function singleModeThemeItems(availableThemes,currentTheme){return[{value:AUTOMATIC_THEME_VALUE,label:" Automatic",description:"Use separate themes for light and dark terminal appearance"},...themeItems(availableThemes,currentTheme)]}function preferredTheme(availableThemes,preferred,fallback){return preferred&&availableThemes.includes(preferred)?preferred:availableThemes.includes(fallback)?fallback:availableThemes[0]??fallback}function defaultAutomaticThemes(currentThemeSetting,availableThemes){let autoTheme=parseAutoThemeSetting(currentThemeSetting);if(autoTheme)return autoTheme;let currentFixedTheme=currentThemeSetting.includes("/")?void 0:currentThemeSetting,themeName=preferredTheme(availableThemes,currentFixedTheme,"dark");return{lightTheme:themeName,darkTheme:themeName}}var ThemeSubmenu=class extends Container{constructor(currentThemeSetting,terminalTheme,availableThemes,callbacks,onDone){super(),this.callbacks=callbacks,this.availableThemes=availableThemes,this.terminalTheme=terminalTheme,this.onDone=onDone,this.originalThemeSetting=currentThemeSetting;let autoTheme=parseAutoThemeSetting(currentThemeSetting),automaticThemes=defaultAutomaticThemes(currentThemeSetting,availableThemes),fixedTheme=autoTheme||currentThemeSetting.includes("/")?void 0:currentThemeSetting;this.mode=autoTheme?"automatic":"single",this.lightTheme=automaticThemes.lightTheme,this.darkTheme=automaticThemes.darkTheme,this.singleTheme=preferredTheme(availableThemes,fixedTheme??(autoTheme?this.getActiveAutomaticTheme():void 0),"dark"),this.mode==="automatic"?this.showAutomaticMenu():this.showSingleMenu()}handleInput(data){this.inputComponent?.handleInput?.(data)}setContent(renderComponent,inputComponent=renderComponent){this.clear(),this.addChild(renderComponent),this.inputComponent=inputComponent}showSingleMenu(){this.mode="single";let menu=new SelectSubmenu("Theme","Select a theme, or choose Automatic to follow terminal appearance.",singleModeThemeItems(this.availableThemes,this.singleTheme),this.singleTheme,value2=>{if(value2===AUTOMATIC_THEME_VALUE){this.mode="automatic",this.callbacks.onThemePreview?.(this.getThemeSetting()),this.showAutomaticMenu();return}this.singleTheme=value2,this.apply(value2)},()=>this.cancel(),value2=>{this.callbacks.onThemePreview?.(value2===AUTOMATIC_THEME_VALUE?this.getAutomaticThemeSetting():value2)});this.setContent(menu)}showAutomaticMenu(){this.mode="automatic";let content=new Container;content.addChild(new Text(theme.bold(theme.fg("accent","Automatic Theme")),0,0)),content.addChild(new Spacer(1)),content.addChild(new Text(theme.fg("muted","Choose themes for terminal light and dark appearance."),0,0)),content.addChild(new Text(theme.fg("muted","Light/dark detection requires terminal support."),0,0)),content.addChild(new Spacer(1));let items=[{id:"light-theme",label:"Light theme",description:"Theme to use in automatic mode when the terminal is light",currentValue:this.lightTheme,submenu:(currentValue,done)=>this.createThemeSelect("Light Theme","Select the theme to use for light terminal appearance",currentValue,done,value2=>{this.lightTheme=value2,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value2)})},{id:"dark-theme",label:"Dark theme",description:"Theme to use in automatic mode when the terminal is dark",currentValue:this.darkTheme,submenu:(currentValue,done)=>this.createThemeSelect("Dark Theme","Select the theme to use for dark terminal appearance",currentValue,done,value2=>{this.darkTheme=value2,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value2)})},{id:"apply",label:"Apply",description:"Save and go back",currentValue:"save and go back",values:["save and go back"]},{id:"single-mode",label:"Change mode",description:"Switch to one theme for light and dark",currentValue:"switch to single theme",values:["switch to single theme"]}],settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),id=>{switch(id){case"single-mode":this.mode="single",this.singleTheme=this.getActiveAutomaticTheme(),this.callbacks.onThemePreview?.(this.singleTheme),this.showSingleMenu();break;case"apply":this.apply(this.getAutomaticThemeSetting());break}},()=>this.cancel());content.addChild(settingsList),this.setContent(content,settingsList)}createThemeSelect(title,description,currentValue,done,onSelect){return new SelectSubmenu(title,description,themeItems(this.availableThemes,currentValue),currentValue,onSelect,()=>{this.callbacks.onThemePreview?.(this.getThemeSetting()),done()},value2=>this.callbacks.onThemePreview?.(value2))}getThemeSetting(){return this.mode==="automatic"?this.getAutomaticThemeSetting():this.singleTheme}getActiveAutomaticTheme(){return this.terminalTheme==="light"?this.lightTheme:this.darkTheme}getAutomaticThemeSetting(){return`${this.lightTheme}/${this.darkTheme}`}apply(themeSetting){this.onDone(themeSetting)}cancel(){this.callbacks.onThemePreview?.(this.originalThemeSetting),this.onDone()}},SettingsSelectorComponent=class extends Container{constructor(config,callbacks){super();let supportsImages=getCapabilities().images,followUpKey=keyDisplayText("app.message.followUp"),cycleThinkingKey=keyDisplayText("app.thinking.cycle"),currentWarnings={...config.warnings},currentModelThinkingLevels={...config.modelThinkingLevels},defaultModelByValue=new Map(config.availableDefaultModels.map(model=>[modelSettingKey(model),model])),currentDefaultModelKey=defaultModelByValue.has(config.defaultModel)?config.defaultModel:void 0,currentModelKey=config.currentModel?modelSettingKey(config.currentModel):void 0,items=[{id:"autocompact",label:"Auto-compact",description:"Automatically compact context when it gets too large",currentValue:config.autoCompact?"true":"false",values:["true","false"]},{id:"steering-mode",label:"Steering mode",description:"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.",currentValue:config.steeringMode,values:["one-at-a-time","all"]},{id:"follow-up-mode",label:"Follow-up mode",description:`${followUpKey} queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.`,currentValue:config.followUpMode,values:["one-at-a-time","all"]},{id:"transport",label:"Transport",description:"Preferred transport for providers that support multiple transports",currentValue:config.transport,values:["sse","websocket","websocket-cached","auto"]},{id:"http-idle-timeout",label:"HTTP idle timeout",description:"Maximum idle gap while waiting for HTTP headers or body chunks. Disable for local models that pause longer than five minutes.",currentValue:formatHttpIdleTimeoutMs(config.httpIdleTimeoutMs),values:HTTP_IDLE_TIMEOUT_CHOICES.map(choice=>choice.label)},{id:"cache-warming-mode",label:"Cache warming",description:"off; streaming while the agent runs; idle also between runs while continuation stays profitable",currentValue:config.cacheWarmingMode,values:[...CACHE_WARMING_MODES]},{id:"hide-thinking",label:"Hide thinking",description:"Hide thinking blocks in assistant responses",currentValue:config.hideThinkingBlock?"true":"false",values:["true","false"]},{id:"mermaid-rendering",label:"Mermaid diagrams",description:"Render Mermaid code blocks as Unicode diagrams",currentValue:config.mermaidRenderingMode,values:["off","final","streaming"]},{id:"cache-miss-notices",label:"Cache miss notices",description:"Show transcript notices for cache costs and provider recovery diagnostics",currentValue:config.showCacheMissNotices?"true":"false",values:["true","false"]},{id:"collapse-changelog",label:"Collapse changelog",description:"Show condensed changelog after updates",currentValue:config.collapseChangelog?"true":"false",values:["true","false"]},{id:"quiet-startup",label:"Quiet startup",description:"Disable verbose printing at startup",currentValue:config.quietStartup?"true":"false",values:["true","false"]},{id:"install-telemetry",label:"Provider attribution",description:"Send optional provider attribution headers for supported services",currentValue:config.enableInstallTelemetry?"true":"false",values:["true","false"]},{id:"default-project-trust",label:"Default project trust",description:"Fallback behavior when no extension or saved trust decision decides project trust",currentValue:DEFAULT_PROJECT_TRUST_LABELS[config.defaultProjectTrust],values:Object.values(DEFAULT_PROJECT_TRUST_LABELS)},{id:"double-escape-action",label:"Double-escape action",description:"Action when pressing Escape twice with empty editor",currentValue:config.doubleEscapeAction,values:["tree","fork","none"]},{id:"tree-filter-mode",label:"Tree filter mode",description:"Default filter when opening /tree",currentValue:config.treeFilterMode,values:["default","no-tools","user-only","labeled-only","all"]},{id:"warnings",label:"Warnings",description:"Enable or disable individual warnings",currentValue:"configure",submenu:(_currentValue,done)=>new WarningSettingsSubmenu(currentWarnings,warnings=>{currentWarnings=warnings,callbacks.onWarningsChange(warnings)},()=>done())},{id:"model-thinking",label:"Default thinking level per model",description:`Override the default thinking level for specific models. ${cycleThinkingKey} cycles in-session.`,currentValue:modelThinkingOverridesSummary(currentModelThinkingLevels),submenu:(_currentValue,done)=>{let steps=[{key:"model",title:"Per-Model Thinking Level",description:"Select a model to configure",options:()=>{let items2=[...config.availableDefaultModels].sort((a,b2)=>{let aKey=modelSettingKey(a),bKey=modelSettingKey(b2);return aKey===currentModelKey?-1:bKey===currentModelKey?1:aKey===currentDefaultModelKey?-1:bKey===currentDefaultModelKey?1:a.provider.localeCompare(b2.provider)}).map(model=>{let key=modelSettingKey(model),override=currentModelThinkingLevels[key];return{value:key,label:modelItemLabel(model),description:override??void 0}});return items2.length===0&&items2.push({value:"__none__",label:"No models available",description:"Log in to a provider or configure an API key first"}),items2},preselect:()=>currentModelKey??currentDefaultModelKey,searchable:!0,layout:MODEL_PICKER_LAYOUT},{key:"level",title:ctx=>{let m2=defaultModelByValue.get(ctx.model);return`Thinking Level for ${m2?modelDisplayLabel(m2):ctx.model}`},description:"Select default thinking level for this model",options:ctx=>{let model=defaultModelByValue.get(ctx.model);if(!model)return[];let levels=model.reasoning?getSupportedThinkingLevels(model):["off"],activeLevel=currentModelThinkingLevels[ctx.model],items2=levels.map(level=>({value:level,label:`${level===activeLevel?"\u2713 ":" "}${level}`,description:THINKING_DESCRIPTIONS[level]}));return currentModelThinkingLevels[ctx.model]!==void 0&&items2.push({value:CLEAR_OVERRIDE_VALUE,label:" (clear override)",description:`Revert to global default (${config.thinkingLevel})`}),items2},preselect:ctx=>currentModelThinkingLevels[ctx.model]}],summary=()=>modelThinkingOverridesSummary(currentModelThinkingLevels);return new SteppedSubmenu(steps,selections=>{let model=defaultModelByValue.get(selections.model);model&&(selections.level===CLEAR_OVERRIDE_VALUE?(callbacks.onModelThinkingLevelRemove(model.provider,model.id),delete currentModelThinkingLevels[selections.model]):(callbacks.onModelThinkingLevelChange(model.provider,model.id,selections.level),currentModelThinkingLevels[selections.model]=selections.level))},()=>{done(summary())},{loop:!0})}},{id:"tui-mode",label:"TUI mode",description:"Interface layout; regular mode renders inline in the terminal scrollback",currentValue:config.tuiMode,values:["regular","fullscreen"]},{id:"fullscreen-exit-output",label:"Fullscreen exit output",description:"Print the transcript or only a session resume hint when exiting fullscreen mode",currentValue:config.fullscreenExitOutput,values:["transcript","resume-hint"]},{id:"fullscreen-scrollbar",label:"Fullscreen scrollbar",description:"Scrollbar behavior in fullscreen mode; has no effect in regular mode",currentValue:config.fullscreenScrollbar,values:["auto","always","hidden"]},{id:"fullscreen-copy-on-select",label:"Fullscreen copy on select",description:"Automatically copy selected text in fullscreen mode; disable to copy selections with Ctrl+X",currentValue:config.fullscreenCopyOnSelect?"true":"false",values:["true","false"]},{id:"theme",label:"Theme",description:"Color theme for the interface",currentValue:config.currentTheme,submenu:(currentValue,done)=>new ThemeSubmenu(currentValue,config.terminalTheme,config.availableThemes,callbacks,done)}];supportsImages&&(items.splice(1,0,{id:"show-images",label:"Show images",description:"Render images inline in terminal",currentValue:config.showImages?"true":"false",values:["true","false"]}),items.splice(2,0,{id:"image-width-cells",label:"Image width",description:"Preferred inline image width in terminal cells",currentValue:String(config.imageWidthCells),values:["60","80","120"]})),items.splice(supportsImages?3:1,0,{id:"auto-resize-images",label:"Auto-resize images",description:"Resize large images to 2000x2000 max for better model compatibility",currentValue:config.autoResizeImages?"true":"false",values:["true","false"]});let autoResizeIndex=items.findIndex(item=>item.id==="auto-resize-images");items.splice(autoResizeIndex+1,0,{id:"block-images",label:"Block images",description:"Prevent images from being sent to LLM providers",currentValue:config.blockImages?"true":"false",values:["true","false"]});let blockImagesIndex=items.findIndex(item=>item.id==="block-images");items.splice(blockImagesIndex+1,0,{id:"skill-commands",label:"Skill commands",description:"Register skills as /skill:name commands",currentValue:config.enableSkillCommands?"true":"false",values:["true","false"]});let skillCommandsIndex=items.findIndex(item=>item.id==="skill-commands");items.splice(skillCommandsIndex+1,0,{id:"show-hardware-cursor",label:"Show hardware cursor",description:"Show the terminal cursor while still positioning it for IME support",currentValue:config.showHardwareCursor?"true":"false",values:["true","false"]});let hardwareCursorIndex=items.findIndex(item=>item.id==="show-hardware-cursor");items.splice(hardwareCursorIndex+1,0,{id:"editor-padding",label:"Editor padding",description:"Horizontal padding for input editor (0-3)",currentValue:String(config.editorPaddingX),values:["0","1","2","3"]});let editorPaddingIndex=items.findIndex(item=>item.id==="editor-padding");items.splice(editorPaddingIndex+1,0,{id:"output-padding",label:"Output padding",description:"Horizontal padding for user messages, assistant messages, and thinking",currentValue:String(config.outputPad),values:["0","1"]});let outputPaddingIndex=items.findIndex(item=>item.id==="output-padding");items.splice(outputPaddingIndex+1,0,{id:"autocomplete-max-visible",label:"Autocomplete max items",description:"Max visible items in autocomplete dropdown (3-20)",currentValue:String(config.autocompleteMaxVisible),values:["3","5","7","10","15","20"]});let autocompleteIndex=items.findIndex(item=>item.id==="autocomplete-max-visible");items.splice(autocompleteIndex+1,0,{id:"clear-on-shrink",label:"Clear on shrink",description:"Clear empty rows when content shrinks (may cause flicker)",currentValue:config.clearOnShrink?"true":"false",values:["true","false"]});let clearOnShrinkIndex=items.findIndex(item=>item.id==="clear-on-shrink");items.splice(clearOnShrinkIndex+1,0,{id:"terminal-progress",label:"Terminal progress",description:"Show OSC 9;4 progress indicators in the terminal tab bar",currentValue:config.showTerminalProgress?"true":"false",values:["true","false"]}),this.addChild(new DynamicBorder),this.settingsList=new SettingsList(items,10,getSettingsListTheme(),(id,newValue)=>{switch(id){case"autocompact":callbacks.onAutoCompactChange(newValue==="true");break;case"show-images":callbacks.onShowImagesChange(newValue==="true");break;case"image-width-cells":callbacks.onImageWidthCellsChange(parseInt(newValue,10));break;case"auto-resize-images":callbacks.onAutoResizeImagesChange(newValue==="true");break;case"block-images":callbacks.onBlockImagesChange(newValue==="true");break;case"skill-commands":callbacks.onEnableSkillCommandsChange(newValue==="true");break;case"steering-mode":callbacks.onSteeringModeChange(newValue);break;case"follow-up-mode":callbacks.onFollowUpModeChange(newValue);break;case"transport":callbacks.onTransportChange(newValue);break;case"http-idle-timeout":{let choice=HTTP_IDLE_TIMEOUT_CHOICES.find(item=>item.label===newValue);choice&&callbacks.onHttpIdleTimeoutMsChange(choice.timeoutMs);break}case"cache-warming-mode":callbacks.onCacheWarmingModeChange(newValue);break;case"hide-thinking":callbacks.onHideThinkingBlockChange(newValue==="true");break;case"mermaid-rendering":callbacks.onMermaidRenderingModeChange(newValue);break;case"cache-miss-notices":callbacks.onShowCacheMissNoticesChange(newValue==="true");break;case"collapse-changelog":callbacks.onCollapseChangelogChange(newValue==="true");break;case"quiet-startup":callbacks.onQuietStartupChange(newValue==="true");break;case"install-telemetry":callbacks.onEnableInstallTelemetryChange(newValue==="true");break;case"default-project-trust":{let defaultProjectTrust=DEFAULT_PROJECT_TRUST_BY_LABEL.get(newValue);defaultProjectTrust&&callbacks.onDefaultProjectTrustChange(defaultProjectTrust);break}case"double-escape-action":callbacks.onDoubleEscapeActionChange(newValue);break;case"tree-filter-mode":callbacks.onTreeFilterModeChange(newValue);break;case"show-hardware-cursor":callbacks.onShowHardwareCursorChange(newValue==="true");break;case"editor-padding":callbacks.onEditorPaddingXChange(parseInt(newValue,10));break;case"output-padding":callbacks.onOutputPadChange(newValue==="0"?0:1);break;case"autocomplete-max-visible":callbacks.onAutocompleteMaxVisibleChange(parseInt(newValue,10));break;case"clear-on-shrink":callbacks.onClearOnShrinkChange(newValue==="true");break;case"terminal-progress":callbacks.onShowTerminalProgressChange(newValue==="true");break;case"tui-mode":callbacks.onTuiModeChange(newValue);break;case"fullscreen-exit-output":callbacks.onFullscreenExitOutputChange(newValue);break;case"fullscreen-scrollbar":callbacks.onFullscreenScrollbarChange(newValue);break;case"fullscreen-copy-on-select":callbacks.onFullscreenCopyOnSelectChange(newValue==="true");break;case"theme":callbacks.onThemeChange(newValue);break}},callbacks.onCancel,{enableSearch:!0}),this.addChild(this.settingsList),this.addChild(new DynamicBorder)}getSettingsList(){return this.settingsList}};var SkillInvocationMessageComponent=class extends Box{constructor(skillBlock,markdownTheme=getMarkdownTheme()){super(1,1,t=>theme.bg("customMessageBg",t)),this.expanded=!1,this.skillBlock=skillBlock,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let content=new Container;if(this.expanded){let label=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m");content.addChild(new Text(label,0,0));let header=`**${this.skillBlock.name}**
|
|
1329
1329
|
|
|
1330
|
-
`;content.addChild(new Markdown(header+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var TOOL_CHROME_WIDTH=2,FALLBACK_ARGS_WIDTH=120,FALLBACK_RESULT_LINES=10;function formatElapsed(ms){let roundedTenths=Math.round(ms/100)/10;if(roundedTenths<60)return`${roundedTenths.toFixed(1)}s`;let roundedSeconds=Math.round(ms/1e3),minutes=Math.floor(roundedSeconds/60);return minutes<60?`${minutes}m ${roundedSeconds%60}s`:`${Math.floor(minutes/60)}h ${minutes%60}m ${roundedSeconds%60}s`}var ToolChromeComponent=class{constructor(component,prefix,options={}){this.component=component,this.prefix=prefix,this.continuationPrefix=options.continuationPrefix??" ",this.blankLinePrefix=options.blankLinePrefix??"",this.trimLeadingBlankLines=options.trimLeadingBlankLines??!1}render(width){let renderedLines=this.component.render(Math.max(1,width-TOOL_CHROME_WIDTH)),start=0;if(this.trimLeadingBlankLines)for(;renderedLines[start]==="";)start++;let lines=renderedLines.slice(start);return lines.length===0?[]:lines.map((line,index3)=>index3===0?`${this.prefix}${line}`:line?`${this.continuationPrefix}${line}`:this.blankLinePrefix)}invalidate(){this.component.invalidate()}},FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,FALLBACK_RESULT_LINES,width);if(preview.skippedCount<=0)return preview.visualLines;let hint2=collapsedLinesHint(theme,preview.skippedCount,"earlier");return[truncateToWidth(hint2,width,"\u2026"),...preview.visualLines]}invalidate(){}};function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value2])=>{try{return`${key}=${JSON.stringify(value2)??String(value2)}`}catch{return`${key}=${String(value2)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,FALLBACK_ARGS_WIDTH,"...")}var PROGRESS_THRESHOLD_MS=2e3,PROGRESS_REFRESH_INTERVAL_MS=1e3,DETACH_HINT_DELAY_MS=1e4,ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.convertedImages=new Map,this.pendingImageConversions=new Map,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.toolGroup=this.getRenderShell()==="self"?void 0:this.toolDefinition?.toolGroup,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.detachHint=options.detachHint,this.ui=ui,this.cwd=cwd,this.addChild(new Spacer(1)),this.contentContainer=new Container,this.selfRenderContainer=new Container,this.addChild(this.getRenderShell()==="self"?this.selfRenderContainer:this.contentContainer),this.updateDisplay()}getCallRenderer(){return this.toolDefinition?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult}hasRendererDefinition(){return this.toolDefinition!==void 0}getRenderShell(){return this.toolDefinition?.renderShell??"default"}shouldRenderGenericProgress(){return this.toolName==="bash"&&this.getRenderShell()!=="self"}shouldRenderDetachHint(){return this.getRenderShell()!=="self"&&this.detachHint?.isDetachable(this.toolName)===!0}detachHintText(){if(!this.shouldRenderDetachHint())return;let key=this.detachHint?.keyLabel();return key?`Press ${key} to run in background, /bg to manage`:void 0}getRenderContext(lastComponent,toolGroupSummary=!1){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,result:this.result?{content:this.result.content,details:this.result.details}:void 0,toolGroupSummary}}createCallFallback(){let args=formatFallbackArgs(this.args),suffix=args?theme.fg("dim",`(${args})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(this.toolName))}${suffix}`,0,0)}wrapCall(component){let color2=this.isPartial?"warning":this.result?.isError?"error":"success",rail=theme.fg("dim","\u2502 ");return new ToolChromeComponent(component,`${theme.fg(color2,"\u25CF")} `,{continuationPrefix:rail,blankLinePrefix:theme.fg("dim","\u2502")})}wrapResult(component){let rail=theme.fg("dim","\u2502 ");return new ToolChromeComponent(component,rail,{trimLeadingBlankLines:!0,continuationPrefix:rail,blankLinePrefix:theme.fg("dim","\u2502")})}createResultFallback(){let output=this.getTextOutput();if(output)return new FallbackResultComponent(output,this.expanded)}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,(this.shouldRenderGenericProgress()||this.shouldRenderDetachHint())&&(this.progressStartedAt===void 0&&(this.progressStartedAt=Date.now()),this.refreshTimer===void 0&&(this.refreshTimer=setInterval(()=>{if(this.disposed||!this.isPartial){this.clearRefreshTimer();return}this.invalidate(),this.ui.requestRender()},PROGRESS_REFRESH_INTERVAL_MS),this.refreshTimer.unref?.())),this.updateDisplay(),this.ui.requestRender())}clearRefreshTimer(){this.refreshTimer&&(clearInterval(this.refreshTimer),this.refreshTimer=void 0)}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,isPartial||this.clearRefreshTimer(),this.updateDisplay(),this.maybeConvertImagesForKitty()}maybeConvertImagesForKitty(){if(getCapabilities().images!=="kitty"||!this.result)return;let imageBlocks=this.result.content.filter(content=>content.type==="image"),sourceMatches=(image,entry)=>image?.data===entry?.sourceData&&image?.mimeType===entry?.sourceMimeType;for(let[index3,converted]of this.convertedImages)sourceMatches(imageBlocks[index3],converted)||this.convertedImages.delete(index3);for(let[index3,pending]of this.pendingImageConversions)sourceMatches(imageBlocks[index3],pending)||this.pendingImageConversions.delete(index3);for(let i=0;i<imageBlocks.length;i++){let image=imageBlocks[i];if(!image.data||!image.mimeType||image.mimeType==="image/png"||sourceMatches(image,this.convertedImages.get(i))||sourceMatches(image,this.pendingImageConversions.get(i)))continue;let index3=i,sourceData=image.data,sourceMimeType=image.mimeType;this.pendingImageConversions.set(index3,{sourceData,sourceMimeType}),convertToPng(sourceData,sourceMimeType).then(converted=>{let pending=this.pendingImageConversions.get(index3);if(pending?.sourceData!==sourceData||pending.sourceMimeType!==sourceMimeType||(this.pendingImageConversions.delete(index3),this.disposed))return;let currentImage=this.result?.content.filter(content=>content.type==="image")[index3];currentImage?.data!==sourceData||currentImage.mimeType!==sourceMimeType||converted&&(this.convertedImages.set(index3,{sourceData,sourceMimeType,...converted}),this.updateDisplay(),this.ui.requestRender())}).catch(()=>{let pending=this.pendingImageConversions.get(index3);pending?.sourceData===sourceData&&pending.sourceMimeType===sourceMimeType&&this.pendingImageConversions.delete(index3)})}}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}getFinalErrorSummary(){return this.isPartial||!this.result?.isError?void 0:this.getTextOutput().replace(/\s+/gu," ").trim()||void 0}renderCallSummary(width){let callRenderer=this.getCallRenderer(),component;if(!callRenderer)component=this.createCallFallback();else try{component=callRenderer(this.args,theme,this.getRenderContext(void 0,!0))}catch{component=this.createCallFallback()}return this.wrapCall(component).render(width)}render(width){if(this.hideComponent)return[];if(this.getRenderShell()==="self"){let contentLines=this.selfRenderContainer.render(width);if(this.selfRenderHeight=contentLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[];contentLines.length>0&&(lines.push(""),lines.push(...contentLines));for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.hasRendererDefinition()||this.getRenderShell()!=="self")return super.handleMouse(event);if(!(event.y<=0||event.y>this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-1,height:this.selfRenderHeight})}updateDisplay(){let hasContent=!1;this.hideComponent=!1;let selfRendered=this.getRenderShell()==="self",renderContainer=selfRendered?this.selfRenderContainer:this.contentContainer;renderContainer.clear();let addCall=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.wrapCall(component))),hasContent=!0},addResult=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.wrapResult(component))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(this.createCallFallback());else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(this.createCallFallback())}if(this.result){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}if(this.executionStarted&&this.isPartial&&this.progressStartedAt!==void 0){let elapsedMs=Date.now()-this.progressStartedAt;if(this.shouldRenderGenericProgress()&&elapsedMs>=PROGRESS_THRESHOLD_MS&&addResult(new Text(theme.fg("muted",`Running\u2026 (${formatElapsed(elapsedMs)})`),0,0)),elapsedMs>=DETACH_HINT_DELAY_MS){let hint2=this.detachHintText();hint2&&addResult(new Text(theme.fg("dim",hint2),0,0))}}for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let i=0;i<imageBlocks.length;i++){let img=imageBlocks[i];if(caps.images&&this.showImages&&img.data&&img.mimeType){let cached=this.convertedImages.get(i),converted=cached?.sourceData===img.data&&cached.sourceMimeType===img.mimeType?cached:void 0,imageData=converted?.data??img.data,imageMimeType=converted?.mimeType??img.mimeType;if(caps.images==="kitty"&&imageMimeType!=="image/png")continue;let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let imageComponent=new Image(imageData,imageMimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:this.imageWidthCells});this.imageComponents.push(imageComponent),this.addChild(imageComponent)}}}!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}dispose(){this.disposed||(this.disposed=!0,this.clearRefreshTimer(),this.rendererState.dispose?.(),this.pendingImageConversions.clear())}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected=i===this.selectedIndex,cursor=isSelected?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body=prefixPart+label+labelTimestamp+content;isSelected&&(gutter=theme.bg("selectedBg",gutter),body=theme.bg("selectedBg",body)),renderedRows.push({gutter,body,anchorCol,bodyWidth:visibleWidth(body),isSelected})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected){let entry=node.entry,result2,normalize=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":{let path14=shortenPath3(String(args.path||args.file_path||"")),offset=args.offset,limit=args.limit,display=path14;if(offset!==void 0||limit!==void 0){let start=offset??1,end=limit!==void 0?start+limit-1:"";display+=`:${start}${end?`-${end}`:""}`}return`[read: ${display}]`}case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value2){this._focused=value2,this.input.focused=value2}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value2=this.input.getValue().trim();this.onSubmit?.(this.entryId,value2||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.labelInput&&(this.labelInput.focused=value2)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear();let contentBox=new Box(this.outputPad,1,content=>theme.bg("userMessageBg",content));contentBox.addChild(new Markdown(this.text,0,0,this.markdownTheme,{color:content=>theme.fg("userMessageText",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)})),this.addChild(contentBox)}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};import*as crypto2 from"node:crypto";import*as fs8 from"node:fs";import*as os7 from"node:os";import*as path13 from"node:path";import{spawn as spawn11}from"child_process";function detectMiss(prev,message,models){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!prev||promptTokens<=0||usage.cacheRead+usage.cacheWrite===0&&!prev.reportedCache)return;let missedTokens=Math.min(prev.promptTokens,promptTokens)-usage.cacheRead;if(missedTokens<=1024)return;let paidTokens=usage.input+usage.cacheWrite,paidPerToken=paidTokens>0?(usage.cost.input+usage.cost.cacheWrite)/paidTokens:0,readPerToken=usage.cacheRead>0?usage.cost.cacheRead/usage.cacheRead:(models.getModel(message.provider,message.model)?.cost.cacheRead??0)/1e6;return{missedTokens,missedCost:missedTokens*Math.max(0,paidPerToken-readPerToken),idleMs:Math.max(0,message.timestamp-prev.timestamp),modelChanged:`${message.provider}/${message.model}`!==prev.modelKey}}function asPreviousRequest(message,reportedCache){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!(promptTokens<=0))return{promptTokens,modelKey:`${message.provider}/${message.model}`,timestamp:message.timestamp,reportedCache:reportedCache||usage.cacheRead+usage.cacheWrite>0}}function scan(entries,models){let prev,totals={missedTokens:0,missedCost:0,missCount:0},misses=new Map;for(let entry of entries){if(entry.type==="compaction"||entry.type==="branch_summary"){prev=void 0;continue}if(entry.type==="usage"&&entry.kind==="cache_warm"){let promptTokens=entry.usage.input+entry.usage.cacheRead+entry.usage.cacheWrite;promptTokens>0&&(prev={promptTokens,modelKey:`${entry.provider}/${entry.model}`,timestamp:Date.parse(entry.timestamp),reportedCache:!0})}else if(entry.type==="message"&&entry.message.role==="assistant"){let miss=detectMiss(prev,entry.message,models);miss&&(totals.missedTokens+=miss.missedTokens,totals.missedCost+=miss.missedCost,totals.missCount+=1,misses.set(entry.message,miss)),prev=asPreviousRequest(entry.message,prev?.reportedCache??!1)??prev}}return{prev,totals,misses}}function computeCacheWaste(entries,models){return scan(entries,models).totals}function collectCacheMisses(entries,models){return scan(entries,models).misses}function detectCacheMiss(entries,message,models){return detectMiss(scan(entries,models).prev,message,models)}import{mkdirSync as mkdirSync11,readFileSync as readFileSync17,rmSync as rmSync4,writeFileSync as writeFileSync11}from"node:fs";import{dirname as dirname21,join as join35}from"node:path";var MAX_CRASH_RECORDS=5,MAX_AGE=10080*60*1e3;function crashLogPath(agentDir=getAgentDir()){return join35(agentDir,"crashes.json")}function readCrashLog(path14=crashLogPath()){try{let records=JSON.parse(readFileSync17(path14,"utf8"));return Array.isArray(records)?records.filter(record=>typeof record=="object"&&record!==null&&typeof record.timestamp=="string"&&typeof record.message=="string"):[]}catch{return[]}}function writeCrashLog(records,path14){mkdirSync11(dirname21(path14),{recursive:!0}),writeFileSync11(path14,`${JSON.stringify(records,null,2)}
|
|
1330
|
+
`;content.addChild(new Markdown(header+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected=i===this.selectedIndex,cursor=isSelected?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body=prefixPart+label+labelTimestamp+content;isSelected&&(gutter=theme.bg("selectedBg",gutter),body=theme.bg("selectedBg",body)),renderedRows.push({gutter,body,anchorCol,bodyWidth:visibleWidth(body),isSelected})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected){let entry=node.entry,result2,normalize=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":{let path14=shortenPath3(String(args.path||args.file_path||"")),offset=args.offset,limit=args.limit,display=path14;if(offset!==void 0||limit!==void 0){let start=offset??1,end=limit!==void 0?start+limit-1:"";display+=`:${start}${end?`-${end}`:""}`}return`[read: ${display}]`}case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value2){this._focused=value2,this.input.focused=value2}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value2=this.input.getValue().trim();this.onSubmit?.(this.entryId,value2||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.labelInput&&(this.labelInput.focused=value2)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear();let contentBox=new Box(this.outputPad,1,content=>theme.bg("userMessageBg",content));contentBox.addChild(new Markdown(this.text,0,0,this.markdownTheme,{color:content=>theme.fg("userMessageText",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)})),this.addChild(contentBox)}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};function createAllToolRenderers(){return{read:readRenderers,bash:createShellRenderers({name:"bash",prompt:"$"}),powershell:createShellRenderers({name:"powershell",prompt:"PS>"}),edit:editRenderers,write:writeRenderers,grep:grepRenderers,find:findRenderers,ls:lsRenderers}}function withBuiltInRenderers(toolName,definition){let builtIn=createAllToolRenderers()[toolName];return definition?builtIn?{...definition,renderCall:definition.renderCall??builtIn.renderCall,renderResult:definition.renderResult??builtIn.renderResult}:definition:builtIn}var toolStyle={marker:{glyph:"\u25CF",color:{pending:"warning",success:"success",error:"error"}},rail:{glyph:"\u2502",color:"dim"},gap:{afterTool:0,afterOther:1},collapsed:{headerOnly:new Set(["read","grep","find","ls"]),fallbackLines:10},fallbackArgsWidth:120};function toolStatus(state2){return state2.isPartial?"pending":state2.isError?"error":"success"}function toolMarkerColor(status){return toolStyle.marker.color[status]}function cellWidth(){return Math.max(visibleWidth(toolStyle.marker.glyph),visibleWidth(toolStyle.rail.glyph))}function gutterWidth(){return cellWidth()+1}function gutterCell(glyph,color2){return`${theme.fg(color2,glyph)}${" ".repeat(cellWidth()-visibleWidth(glyph)+1)}`}function isBlankLine(line){return line===""||stripAnsi(line).trim()===""}function dropLeadingBlankLines(lines){let start=0;for(;start<lines.length&&isBlankLine(lines[start]);)start++;return lines.slice(start)}var FramedComponent=class{constructor(component,kind,markerColor){this.component=component,this.kind=kind,this.markerColor=markerColor}render(width){let rendered=this.component.render(Math.max(1,width-gutterWidth())),lines=this.kind==="body"?dropLeadingBlankLines(rendered):rendered.length>1?[rendered[0],...dropLeadingBlankLines(rendered.slice(1))]:rendered;if(lines.length===0)return[];let rail=gutterCell(toolStyle.rail.glyph,toolStyle.rail.color),bareRail=theme.fg(toolStyle.rail.color,toolStyle.rail.glyph);return lines.map((line,index3)=>index3===0&&this.kind==="header"?`${gutterCell(toolStyle.marker.glyph,this.markerColor())}${line}`:isBlankLine(line)?bareRail:`${rail}${line}`)}invalidate(){this.component.invalidate()}};function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value2])=>{try{return`${key}=${JSON.stringify(value2)??String(value2)}`}catch{return`${key}=${String(value2)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,toolStyle.fallbackArgsWidth,"...")}function createCallFallback(toolName,args){let summary=formatFallbackArgs(args),suffix=summary?theme.fg("dim",`(${summary})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(toolName))}${suffix}`,0,0)}var FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,toolStyle.collapsed.fallbackLines,width);if(preview.skippedCount<=0)return preview.visualLines;let noun=preview.skippedCount===1?"line":"lines",hint2=theme.fg("muted",`... (${preview.skippedCount} earlier ${noun},`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return[truncateToWidth(hint2,width,"..."),...preview.visualLines]}invalidate(){}};var builtInRenderers,ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.convertedImages=new Map,this.pendingImageConversions=new Map,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.ui=ui,this.cwd=cwd,this.gap=new Spacer(toolStyle.gap.afterOther),this.addChild(this.gap),this.contentContainer=new Container,this.selfRenderContainer=new Container,this.addChild(this.isSelfRendered()?this.selfRenderContainer:this.contentContainer),this.updateDisplay()}getCallRenderer(){return this.toolDefinition?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult}isSelfRendered(){return this.toolDefinition?.renderShell==="self"}status(){return toolStatus({isPartial:this.isPartial,isError:this.result?.isError??!1})}setLeadingGap(lines){this.gap.setLines(lines)}getRenderContext(lastComponent){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,result:this.result?{content:this.result.content,details:this.result.details}:void 0}}frame(component,kind){return new FramedComponent(component,kind,()=>toolMarkerColor(this.status()))}createResultFallback(){let output=this.getTextOutput();if(output)return new FallbackResultComponent(output,this.expanded)}hidesCollapsedResult(){if(this.expanded||this.result?.isError||!toolStyle.collapsed.headerOnly.has(this.toolName))return!1;builtInRenderers??=createAllToolRenderers();let builtIn=builtInRenderers[this.toolName];return builtIn?.renderResult!==void 0&&builtIn.renderResult===this.getResultRenderer()}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,this.updateDisplay(),this.ui.requestRender())}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,this.updateDisplay(),this.maybeConvertImagesForKitty()}maybeConvertImagesForKitty(){if(getCapabilities().images!=="kitty"||!this.result)return;let imageBlocks=this.result.content.filter(content=>content.type==="image"),sourceMatches=(image,entry)=>image?.data===entry?.sourceData&&image?.mimeType===entry?.sourceMimeType;for(let[index3,converted]of this.convertedImages)sourceMatches(imageBlocks[index3],converted)||this.convertedImages.delete(index3);for(let[index3,pending]of this.pendingImageConversions)sourceMatches(imageBlocks[index3],pending)||this.pendingImageConversions.delete(index3);for(let i=0;i<imageBlocks.length;i++){let image=imageBlocks[i];if(!image.data||!image.mimeType||image.mimeType==="image/png"||sourceMatches(image,this.convertedImages.get(i))||sourceMatches(image,this.pendingImageConversions.get(i)))continue;let index3=i,sourceData=image.data,sourceMimeType=image.mimeType;this.pendingImageConversions.set(index3,{sourceData,sourceMimeType}),convertToPng(sourceData,sourceMimeType).then(converted=>{let pending=this.pendingImageConversions.get(index3);if(pending?.sourceData!==sourceData||pending.sourceMimeType!==sourceMimeType||(this.pendingImageConversions.delete(index3),this.disposed))return;let currentImage=this.result?.content.filter(content=>content.type==="image")[index3];currentImage?.data!==sourceData||currentImage.mimeType!==sourceMimeType||converted&&(this.convertedImages.set(index3,{sourceData,sourceMimeType,...converted}),this.updateDisplay(),this.ui.requestRender())}).catch(()=>{let pending=this.pendingImageConversions.get(index3);pending?.sourceData===sourceData&&pending.sourceMimeType===sourceMimeType&&this.pendingImageConversions.delete(index3)})}}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}render(width){if(this.hideComponent)return[];if(this.isSelfRendered()){let contentLines=this.selfRenderContainer.render(width);if(this.selfRenderHeight=contentLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[];contentLines.length>0&&(lines.push(""),lines.push(...contentLines));for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.isSelfRendered())return super.handleMouse(event);if(!(event.y<=0||event.y>this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-1,height:this.selfRenderHeight})}updateDisplay(){let hasContent=!1;this.hideComponent=!1;let selfRendered=this.isSelfRendered(),renderContainer=selfRendered?this.selfRenderContainer:this.contentContainer;renderContainer.clear();let addCall=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"header"))),hasContent=!0},addResult=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"body"))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(createCallFallback(this.toolName,this.args));else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(createCallFallback(this.toolName,this.args))}if(this.result&&(selfRendered||!this.hidesCollapsedResult())){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let i=0;i<imageBlocks.length;i++){let img=imageBlocks[i];if(caps.images&&this.showImages&&img.data&&img.mimeType){let cached=this.convertedImages.get(i),converted=cached?.sourceData===img.data&&cached.sourceMimeType===img.mimeType?cached:void 0,imageData=converted?.data??img.data,imageMimeType=converted?.mimeType??img.mimeType;if(caps.images==="kitty"&&imageMimeType!=="image/png")continue;let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let imageComponent=new Image(imageData,imageMimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:this.imageWidthCells});this.imageComponents.push(imageComponent),this.addChild(imageComponent)}}}!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}dispose(){this.disposed||(this.disposed=!0,this.rendererState.dispose?.(),this.pendingImageConversions.clear())}};import*as crypto2 from"node:crypto";import*as fs8 from"node:fs";import*as os7 from"node:os";import*as path13 from"node:path";import{spawn as spawn11}from"child_process";function detectMiss(prev,message,models){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!prev||promptTokens<=0||usage.cacheRead+usage.cacheWrite===0&&!prev.reportedCache)return;let missedTokens=Math.min(prev.promptTokens,promptTokens)-usage.cacheRead;if(missedTokens<=1024)return;let paidTokens=usage.input+usage.cacheWrite,paidPerToken=paidTokens>0?(usage.cost.input+usage.cost.cacheWrite)/paidTokens:0,readPerToken=usage.cacheRead>0?usage.cost.cacheRead/usage.cacheRead:(models.getModel(message.provider,message.model)?.cost.cacheRead??0)/1e6;return{missedTokens,missedCost:missedTokens*Math.max(0,paidPerToken-readPerToken),idleMs:Math.max(0,message.timestamp-prev.timestamp),modelChanged:`${message.provider}/${message.model}`!==prev.modelKey}}function asPreviousRequest(message,reportedCache){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!(promptTokens<=0))return{promptTokens,modelKey:`${message.provider}/${message.model}`,timestamp:message.timestamp,reportedCache:reportedCache||usage.cacheRead+usage.cacheWrite>0}}function scan(entries,models){let prev,totals={missedTokens:0,missedCost:0,missCount:0},misses=new Map;for(let entry of entries){if(entry.type==="compaction"||entry.type==="branch_summary"){prev=void 0;continue}if(entry.type==="usage"&&entry.kind==="cache_warm"){let promptTokens=entry.usage.input+entry.usage.cacheRead+entry.usage.cacheWrite;promptTokens>0&&(prev={promptTokens,modelKey:`${entry.provider}/${entry.model}`,timestamp:Date.parse(entry.timestamp),reportedCache:!0})}else if(entry.type==="message"&&entry.message.role==="assistant"){let miss=detectMiss(prev,entry.message,models);miss&&(totals.missedTokens+=miss.missedTokens,totals.missedCost+=miss.missedCost,totals.missCount+=1,misses.set(entry.message,miss)),prev=asPreviousRequest(entry.message,prev?.reportedCache??!1)??prev}}return{prev,totals,misses}}function computeCacheWaste(entries,models){return scan(entries,models).totals}function collectCacheMisses(entries,models){return scan(entries,models).misses}function detectCacheMiss(entries,message,models){return detectMiss(scan(entries,models).prev,message,models)}import{mkdirSync as mkdirSync11,readFileSync as readFileSync17,rmSync as rmSync4,writeFileSync as writeFileSync11}from"node:fs";import{dirname as dirname21,join as join35}from"node:path";var MAX_CRASH_RECORDS=5,MAX_AGE=10080*60*1e3;function crashLogPath(agentDir=getAgentDir()){return join35(agentDir,"crashes.json")}function readCrashLog(path14=crashLogPath()){try{let records=JSON.parse(readFileSync17(path14,"utf8"));return Array.isArray(records)?records.filter(record=>typeof record=="object"&&record!==null&&typeof record.timestamp=="string"&&typeof record.message=="string"):[]}catch{return[]}}function writeCrashLog(records,path14){mkdirSync11(dirname21(path14),{recursive:!0}),writeFileSync11(path14,`${JSON.stringify(records,null,2)}
|
|
1331
1331
|
`)}function normalizeStackPath(value2){return value2.replace(/\\/g,"/").replace(/\/+$/u,"")}function stackContainsPath(stack,targetPath,includeDescendants){let target=normalizeStackPath(targetPath);if(!target||target.startsWith("<"))return!1;let caseInsensitive=/^[a-z]:\//iu.test(target),haystack=caseInsensitive?stack.toLowerCase():stack,needle=caseInsensitive?target.toLowerCase():target;if(includeDescendants)return haystack.includes(`${needle}/`);let index3=haystack.indexOf(needle);for(;index3!==-1;){let next=haystack[index3+needle.length];if(next===void 0||next===":"||next===")"||/\s/u.test(next))return!0;index3=haystack.indexOf(needle,index3+needle.length)}return!1}function findExtensionStackMatches(stack,extensions){if(!stack)return[];let normalizedStack=stack.split(`
|
|
1332
1332
|
`).slice(1).filter(line=>/^\s+at\s/u.test(line)).map(line=>{try{return decodeURI(line)}catch{return line}}).join(`
|
|
1333
|
-
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var BUILTIN_SLASH_COMMANDS=[{name:"settings",description:"Open settings menu"},{name:"model",description:"Select model (opens selector UI)",argumentHint:"<provider/model>"},{name:"tree",description:"Navigate session tree (switch branches)"},{name:"thinking",description:"Set thinking level",argumentHint:"<level>"},{name:"scoped-models",description:"Enable/disable models for Ctrl+P cycling"},{name:"export",description:"Export session (HTML default, or specify path: .html/.jsonl)"},{name:"import",description:"Import and resume a session from a JSONL file"},{name:"share",description:"Share session as a secret GitHub gist"},{name:"bug",description:"Report a bug to the Pi developers",argumentHint:"<description>"},{name:"copy",description:"Copy last agent message to clipboard"},{name:"name",description:"Set session display name"},{name:"session",description:"Show session info and stats"},{name:"changelog",description:"Show changelog entries"},{name:"hotkeys",description:"Show all keyboard shortcuts"},{name:"fork",description:"Create a new fork from a previous user message"},{name:"clone",description:"Duplicate the current session at the current position"},{name:"trust",description:"Save project trust decision for future sessions"},{name:"login",description:"Configure provider authentication",argumentHint:"<provider>"},{name:"logout",description:"Remove provider authentication"},{name:"new",description:"Start a new session"},{name:"compact",description:"Manually compact the session context"},{name:"resume",description:"Resume a different session"},{name:"reload",description:"Reload keybindings, extensions, skills, prompts, themes, and context files"},{name:"quit",description:`Quit ${APP_NAME}`}];
|
|
1333
|
+
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var BUILTIN_SLASH_COMMANDS=[{name:"settings",description:"Open settings menu"},{name:"model",description:"Select model (opens selector UI)",argumentHint:"<provider/model>"},{name:"tree",description:"Navigate session tree (switch branches)"},{name:"thinking",description:"Set thinking level",argumentHint:"<level>"},{name:"scoped-models",description:"Enable/disable models for Ctrl+P cycling"},{name:"export",description:"Export session (HTML default, or specify path: .html/.jsonl)"},{name:"import",description:"Import and resume a session from a JSONL file"},{name:"share",description:"Share session as a secret GitHub gist"},{name:"bug",description:"Report a bug to the Pi developers",argumentHint:"<description>"},{name:"copy",description:"Copy last agent message to clipboard"},{name:"name",description:"Set session display name"},{name:"session",description:"Show session info and stats"},{name:"changelog",description:"Show changelog entries"},{name:"hotkeys",description:"Show all keyboard shortcuts"},{name:"fork",description:"Create a new fork from a previous user message"},{name:"clone",description:"Duplicate the current session at the current position"},{name:"trust",description:"Save project trust decision for future sessions"},{name:"login",description:"Configure provider authentication",argumentHint:"<provider>"},{name:"logout",description:"Remove provider authentication"},{name:"new",description:"Start a new session"},{name:"compact",description:"Manually compact the session context"},{name:"resume",description:"Resume a different session"},{name:"reload",description:"Reload keybindings, extensions, skills, prompts, themes, and context files"},{name:"quit",description:`Quit ${APP_NAME}`}];import path10 from"node:path";import{existsSync as existsSync21,readFileSync as readFileSync18}from"fs";var GITHUB_REPO="earendil-works/pi",CHANGELOG_LINK_BASE_PATH="packages/coding-agent",LEGACY_REPO_RE=/^https:\/\/github\.com\/(?:badlogic|earendil-works)\/pi-mono(?=\/|$)/,URL_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,INLINE_MARKDOWN_LINK_RE=/(!?\[[^\]\n]+\]\()([^\s)]+)((?:\s+[^)]*)?\))/g;function entryVersion(entry){return`${entry.major}.${entry.minor}.${entry.patch}`}function normalizeTag(version2){let versionString=typeof version2=="string"?version2:entryVersion(version2);return versionString.startsWith("v")?versionString:`v${versionString}`}function splitLocalTarget(target){let hashIndex=target.indexOf("#"),beforeHash=hashIndex===-1?target:target.slice(0,hashIndex),fragment=hashIndex===-1?"":target.slice(hashIndex),queryIndex=beforeHash.indexOf("?");return queryIndex===-1?{fragment,pathPart:beforeHash,query:""}:{fragment,pathPart:beforeHash.slice(0,queryIndex),query:beforeHash.slice(queryIndex)}}function normalizePathPart(value2){return value2.replaceAll("\\","/")}function resolveRepositoryPath(targetPath){let normalizedTarget=normalizePathPart(targetPath),joined=normalizedTarget.startsWith("/")?path10.posix.normalize(normalizedTarget.replace(/^\/+/,"")):path10.posix.normalize(path10.posix.join(CHANGELOG_LINK_BASE_PATH,normalizedTarget));if(!(joined==="."||joined.startsWith("../")||joined===".."))return joined}function isDirectoryTarget(originalPath,repositoryPath){return originalPath.endsWith("/")?!0:!path10.posix.basename(repositoryPath).includes(".")}function normalizeChangelogLinkTarget(target,tag){let canonicalTarget=target.replace(LEGACY_REPO_RE,`https://github.com/${GITHUB_REPO}`),repoUrl=`https://github.com/${GITHUB_REPO}`;for(let route2 of["blob","tree"])for(let branch of["main","master"]){let floatingRefPrefix=`${repoUrl}/${route2}/${branch}/`;canonicalTarget.startsWith(floatingRefPrefix)&&(canonicalTarget=`${repoUrl}/${route2}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`)}if(canonicalTarget.startsWith("#")||canonicalTarget.startsWith("//")||URL_SCHEME_RE.test(canonicalTarget))return canonicalTarget;let{fragment,pathPart,query}=splitLocalTarget(canonicalTarget);if(!pathPart)return canonicalTarget;let repositoryPath=resolveRepositoryPath(pathPart);if(!repositoryPath)return canonicalTarget;let route=isDirectoryTarget(pathPart,repositoryPath)?"tree":"blob";return`https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`}function normalizeChangelogLinks(markdown,version2){let tag=normalizeTag(version2);return markdown.replace(INLINE_MARKDOWN_LINK_RE,(_match,prefix,target,suffix)=>`${prefix}${normalizeChangelogLinkTarget(target,tag)}${suffix}`)}function parseChangelog(changelogPath){if(!existsSync21(changelogPath))return[];try{let lines=readFileSync18(changelogPath,"utf-8").split(`
|
|
1334
1334
|
`),entries=[],currentLines=[],currentVersion=null;for(let line of lines)if(line.startsWith("## ")){currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1335
1335
|
`).trim()});let versionMatch=line.match(/##\s+\[?(\d+)\.(\d+)\.(\d+)\]?/);versionMatch?(currentVersion={major:Number.parseInt(versionMatch[1],10),minor:Number.parseInt(versionMatch[2],10),patch:Number.parseInt(versionMatch[3],10)},currentLines=[line]):(currentVersion=null,currentLines=[])}else currentVersion&¤tLines.push(line);return currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1336
1336
|
`).trim()}),entries}catch(error){return console.error(`Warning: Could not parse changelog: ${error}`),[]}}function compareVersions(v1,v2){return v1.major!==v2.major?v1.major-v2.major:v1.minor!==v2.minor?v1.minor-v2.minor:v1.patch-v2.patch}function getNewEntries(entries,lastVersion){let parts=lastVersion.split(".").map(Number),last={major:parts[0]||0,minor:parts[1]||0,patch:parts[2]||0,content:""};return entries.filter(entry=>compareVersions(entry,last)>0)}import{randomUUID as randomUUID5}from"crypto";import{readFileSync as readFileSync19,unlinkSync as unlinkSync2}from"fs";import{tmpdir as tmpdir6}from"os";import{join as join36}from"path";var SUPPORTED_IMAGE_MIME_TYPES=["image/png","image/jpeg","image/webp","image/gif"],DEFAULT_LIST_TIMEOUT_MS=1e3,DEFAULT_POWERSHELL_TIMEOUT_MS=5e3;function isWaylandSession(env2=process.env){return!!env2.WAYLAND_DISPLAY||env2.XDG_SESSION_TYPE==="wayland"}function baseMimeType2(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function extensionForImageMimeType(mimeType){switch(baseMimeType2(mimeType)){case"image/png":return"png";case"image/jpeg":return"jpg";case"image/webp":return"webp";case"image/gif":return"gif";default:return null}}function selectPreferredImageMimeType(mimeTypes){let normalized=mimeTypes.map(t=>t.trim()).filter(Boolean).map(t=>({raw:t,base:baseMimeType2(t)}));for(let preferred of SUPPORTED_IMAGE_MIME_TYPES){let match2=normalized.find(t=>t.base===preferred);if(match2)return match2.raw}return normalized.find(t=>t.base.startsWith("image/"))?.raw??null}function isSupportedImageMimeType(mimeType){let base=baseMimeType2(mimeType);return SUPPORTED_IMAGE_MIME_TYPES.some(t=>t===base)}async function convertToPng2(bytes){let photon=await loadPhoton();if(!photon)return null;try{let image=photon.PhotonImage.new_from_byteslice(bytes);try{return image.get_bytes()}finally{image.free()}}catch{return null}}async function readClipboardImageViaWlPaste(){let list2=await runClipboardCommand("wl-paste",["--list-types"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(list2===void 0)return;let types2=list2.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean),selectedType=selectPreferredImageMimeType(types2);if(!selectedType)return null;let data=await runClipboardCommand("wl-paste",["--type",selectedType,"--no-newline"]);if(data!==void 0)return data.length===0?null:{bytes:data,mimeType:baseMimeType2(selectedType)}}async function readClipboardImageViaPowerShell(){let tmpFile=join36(tmpdir6(),`pi-wsl-clip-${randomUUID5()}.png`);try{let winPathResult=await runClipboardCommand("wslpath",["-w",tmpFile],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(winPathResult===void 0)return null;let winPath=winPathResult.toString("utf-8").trim();if(!winPath)return null;let psScript=["Add-Type -AssemblyName System.Windows.Forms","Add-Type -AssemblyName System.Drawing",`$path = '${winPath.replaceAll("'","''")}'`,"$img = [System.Windows.Forms.Clipboard]::GetImage()","if ($img) { $img.Save($path, [System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'ok' } else { Write-Output 'empty' }"].join("; "),result2=await runClipboardCommand("powershell.exe",["-NoProfile","-Command",psScript],{timeoutMs:DEFAULT_POWERSHELL_TIMEOUT_MS});if(result2===void 0||result2.toString("utf-8").trim()!=="ok")return null;let bytes=readFileSync19(tmpFile);return bytes.length===0?null:{bytes:new Uint8Array(bytes),mimeType:"image/png"}}catch{return null}finally{try{unlinkSync2(tmpFile)}catch{}}}async function readClipboardImageViaXclip(){let targets=await runClipboardCommand("xclip",["-selection","clipboard","-t","TARGETS","-o"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS}),candidateTypes=[];targets!==void 0&&(candidateTypes=targets.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean));let preferred=selectPreferredImageMimeType(candidateTypes);if(targets!==void 0&&!preferred)return null;let tryTypes=new Set(preferred?[preferred,...SUPPORTED_IMAGE_MIME_TYPES]:SUPPORTED_IMAGE_MIME_TYPES);for(let mimeType of tryTypes){let data=await runClipboardCommand("xclip",["-selection","clipboard","-t",mimeType,"-o"]);if(data!==void 0&&data.length>0)return{bytes:data,mimeType:baseMimeType2(mimeType)}}}async function readClipboardImageViaNativeClipboard(){let bytes=await getNativeClipboard()?.getImage();if(bytes!==void 0)return bytes?.length?{bytes,mimeType:detectSupportedImageMimeType(bytes)??"application/octet-stream"}:null}async function readClipboardImage(options){let env2=options?.env??process.env,platform3=options?.platform??process.platform;if(env2.TERMUX_VERSION)return null;let image;if(platform3==="linux"){let wsl=isWSL(env2);(isWaylandSession(env2)||wsl)&&(image=await readClipboardImageViaWlPaste()),image===void 0&&(image=await readClipboardImageViaXclip()),!image&&wsl&&(image=await readClipboardImageViaPowerShell()??image),image===void 0&&(image=await readClipboardImageViaNativeClipboard())}else image=await readClipboardImageViaNativeClipboard();if(!image)return null;if(!isSupportedImageMimeType(image.mimeType)){let pngBytes=await convertToPng2(image.bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png"}:null}return image}var import_semver2=__toESM(require_semver2(),1);var LATEST_VERSION_URL=`https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`,DEFAULT_VERSION_CHECK_TIMEOUT_MS=1e4;function formatVersionCheckError(error){let rootMessage=error instanceof Error&&error.message?error.message:String(error),cause=error instanceof Error?error.cause:void 0,causes=cause instanceof AggregateError?cause.errors:cause===void 0?[]:[cause],codes=causes.map(value2=>typeof value2=="object"&&value2!==null&&"code"in value2&&typeof value2.code=="string"?value2.code:void 0).filter(code=>code!==void 0);if(codes.length>0)return`${rootMessage} (${[...new Set(codes)].join(", ")})`;let causeMessage=causes.find(value2=>value2 instanceof Error&&!!value2.message)?.message;return causeMessage?`${rootMessage} (cause: ${causeMessage})`:rootMessage}function comparePackageVersions(leftVersion,rightVersion){let left=(0,import_semver2.valid)(leftVersion.trim()),right=(0,import_semver2.valid)(rightVersion.trim());if(!(!left||!right))return(0,import_semver2.compare)(left,right)}function isNewerPackageVersion(candidateVersion,currentVersion){let comparison=comparePackageVersions(candidateVersion,currentVersion);return comparison!==void 0?comparison>0:candidateVersion.trim()!==currentVersion.trim()}async function getLatestPiRelease(currentVersion,options={}){if(process.env.PI_OFFLINE)return;let response=await fetchWithRetry(LATEST_VERSION_URL,{headers:{"User-Agent":getPiUserAgent(currentVersion),accept:"application/json"}},{maxRetries:options.retry?2:0,timeoutMs:options.timeoutMs??DEFAULT_VERSION_CHECK_TIMEOUT_MS});if(!response.ok)return;let data=await response.json();if(!(typeof data.version!="string"||!data.version.trim()))return{version:data.version.trim(),packageName:PACKAGE_NAME}}async function checkForNewPiVersion(currentVersion){if(!process.env.PI_SKIP_VERSION_CHECK)try{let latestRelease=await getLatestPiRelease(currentVersion);return latestRelease&&isNewerPackageVersion(latestRelease.version,currentVersion)?latestRelease:void 0}catch{return}}import*as path12 from"node:path";var AuthCommandError=class extends Error{},AUTH_COMMAND_USAGE={check:`${APP_NAME} auth check --provider <provider> [--json] [--credentials] [--no-refresh]`,api_key:`${APP_NAME} auth print-api-key --provider <provider> [--model <model>]`,bearer_token:`${APP_NAME} auth print-bearer-token --provider <provider> [--model <model>] [--min-expiry <duration>]`};function getAuthCommandName(kind){return kind==="check"?"auth check":kind==="api_key"?"auth print-api-key":"auth print-bearer-token"}function getAuthCommandUsage(kind){return AUTH_COMMAND_USAGE[kind]}function isAuthCommandHelp(args){return args[0]==="auth"&&(args[1]===void 0||args[1]==="help"||args.includes("--help")||args.includes("-h"))}function printAuthCommandHelp(){console.log(`Usage:
|
|
@@ -1356,7 +1356,7 @@ ${codeSpan(styledWarning)}
|
|
|
1356
1356
|
`)}
|
|
1357
1357
|
`}).join("")}}function isEnabled(enabledIds,id){return enabledIds===null||enabledIds.includes(id)}function normalizeEnabled(result2,allIds){return result2.length===allIds.length&&result2.every(id=>allIds.includes(id))?null:result2}function toggle(enabledIds,allIds,id){if(enabledIds===null)return allIds.filter(modelId2=>modelId2!==id);let index3=enabledIds.indexOf(id);return index3>=0?[...enabledIds.slice(0,index3),...enabledIds.slice(index3+1)]:normalizeEnabled([...enabledIds,id],allIds)}function enableAll(enabledIds,allIds,targetIds){if(enabledIds===null)return null;let targets=targetIds??allIds,result2=[...enabledIds];for(let id of targets)result2.includes(id)||result2.push(id);return normalizeEnabled(result2,allIds)}function clearAll(enabledIds,allIds,targetIds){if(enabledIds===null)return targetIds?allIds.filter(id=>!targetIds.includes(id)):[];let targets=new Set(targetIds??enabledIds);return enabledIds.filter(id=>!targets.has(id))}function move(enabledIds,id,delta){if(enabledIds===null)return null;let list2=[...enabledIds],index3=list2.indexOf(id);if(index3<0)return list2;let newIndex=index3+delta;if(newIndex<0||newIndex>=list2.length)return list2;let result2=[...list2];return[result2[index3],result2[newIndex]]=[result2[newIndex],result2[index3]],result2}function getSortedIds(enabledIds,allIds){if(enabledIds===null)return allIds;let enabledSet=new Set(enabledIds);return[...enabledIds,...allIds.filter(id=>!enabledSet.has(id))]}var ScopedModelsSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(config,callbacks){super(),this.modelsById=new Map,this.allIds=[],this.enabledIds=null,this.filteredItems=[],this.selectedIndex=0,this._focused=!1,this.maxVisible=8,this.isDirty=!1,this.callbacks=callbacks;for(let model of config.allModels){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.enabledIds=config.enabledModelIds===null?null:[...config.enabledModelIds],this.filteredItems=this.buildItems(),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Model Configuration")),0,0)),this.addChild(new Text(theme.fg("muted",`Session-only. ${keyDisplayText("app.models.save")} to save to settings.`),0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),config.refreshStatus&&(this.refreshStatusText=new Text(theme.fg("muted",` ${config.refreshStatus}`),0,0),this.addChild(this.refreshStatusText)),this.footerText=new Text(this.getFooterText(),0,0),this.addChild(this.footerText),this.addChild(new DynamicBorder),this.updateList()}updateModels(models,enabledModelIds){let selectedId=this.filteredItems[this.selectedIndex]?.fullId;enabledModelIds!==void 0&&(this.enabledIds=enabledModelIds===null?null:[...enabledModelIds]),this.modelsById.clear(),this.allIds=[];for(let model of models){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.refresh();let refreshedIndex=selectedId?this.filteredItems.findIndex(item=>item.fullId===selectedId):-1;refreshedIndex>=0&&(this.selectedIndex=refreshedIndex,this.updateList())}setRefreshStatus(message,kind){this.refreshStatusText?.setText(theme.fg(kind,` ${message}`))}buildItems(){return getSortedIds(this.enabledIds,this.allIds).map(id=>({fullId:id,model:this.modelsById.get(id),enabled:isEnabled(this.enabledIds,id)}))}getFooterText(){let enabledCount=this.enabledIds?.filter(id=>this.modelsById.has(id)).length??this.allIds.length,unavailableCount=this.enabledIds?.filter(id=>!this.modelsById.has(id)).length??0,countText=this.enabledIds===null?"all enabled":`${enabledCount}/${this.allIds.length} enabled${unavailableCount?` \xB7 ${unavailableCount} unavailable`:""}`,parts=[`${keyDisplayText("tui.select.confirm")} toggle`,`${keyDisplayText("app.models.enableAll")} all`,`${keyDisplayText("app.models.clearAll")} clear`,`${keyDisplayText("app.models.toggleProvider")} provider`,`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} reorder`,`${keyDisplayText("app.models.save")} save`,countText];return this.isDirty?theme.fg("dim",` ${parts.join(" \xB7 ")} `)+theme.fg("warning","(unsaved)"):theme.fg("dim",` ${parts.join(" \xB7 ")}`)}refresh(){let query=this.searchInput.getValue(),items=this.buildItems();this.filteredItems=query?fuzzyFilter(items,query,item=>item.model?getModelSearchText({id:item.model.id,provider:item.model.provider,name:item.model.name}):item.fullId):items,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredItems.length-1)),this.updateList(),this.footerText.setText(this.getFooterText())}notifyChange(){this.callbacks.onChange(this.enabledIds===null?null:[...this.enabledIds])}updateList(){if(this.listContainer.clear(),this.filteredItems.length===0){this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));return}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredItems.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredItems.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredItems[i],isSelected=i===this.selectedIndex,prefix=isSelected?theme.fg("accent","\u2192 "):" ",id=item.model?.id??item.fullId,styledId=item.model?id:theme.strikethrough(id),modelText2=isSelected?theme.fg("accent",styledId):styledId,providerBadge=theme.fg("muted",item.model?` [${item.model.provider}]`:" [unavailable]"),status=item.model&&item.enabled?theme.fg("accent","\u2713 "):" ";this.listContainer.addChild(new Text(`${prefix}${status}${modelText2}${providerBadge}`,0,0))}if((startIndex>0||endIndex<this.filteredItems.length)&&this.listContainer.addChild(new Text(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredItems.length})`),0,0)),this.filteredItems.length>0){let selected=this.filteredItems[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` ${selected.model?`Model Name: ${selected.model.name}`:"Model unavailable"}`),0,0))}}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.up")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredItems.length-1:this.selectedIndex-1,this.updateList();return}if(kb.matches(data,"tui.select.down")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredItems.length-1?0:this.selectedIndex+1,this.updateList();return}let reorderUp=kb.matches(data,"app.models.reorderUp"),reorderDown=kb.matches(data,"app.models.reorderDown");if(reorderUp||reorderDown){if(this.enabledIds===null)return;let item=this.filteredItems[this.selectedIndex];if(item&&isEnabled(this.enabledIds,item.fullId)){let delta=reorderUp?-1:1,newIndex=this.enabledIds.indexOf(item.fullId)+delta;newIndex>=0&&newIndex<this.enabledIds.length&&(this.enabledIds=move(this.enabledIds,item.fullId,delta),this.isDirty=!0,this.selectedIndex+=delta,this.refresh(),this.notifyChange())}return}if(kb.matches(data,"tui.select.confirm")){let item=this.filteredItems[this.selectedIndex];item&&(this.enabledIds=toggle(this.enabledIds,this.allIds,item.fullId),this.isDirty=!0,this.refresh(),this.notifyChange());return}if(kb.matches(data,"app.models.enableAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=enableAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.clearAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=clearAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.toggleProvider")){let item=this.filteredItems[this.selectedIndex];if(item?.model){let provider=item.model.provider,providerIds=this.allIds.filter(id=>this.modelsById.get(id).provider===provider),allEnabled=providerIds.every(id=>isEnabled(this.enabledIds,id));this.enabledIds=allEnabled?clearAll(this.enabledIds,this.allIds,providerIds):enableAll(this.enabledIds,this.allIds,providerIds),this.isDirty=!0,this.refresh(),this.notifyChange()}return}if(kb.matches(data,"app.models.save")){this.callbacks.onPersist(this.enabledIds===null?null:[...this.enabledIds]),this.isDirty=!1,this.footerText.setText(this.getFooterText());return}if(matchesKey(data,Key.ctrl("c"))){this.searchInput.getValue()?(this.searchInput.setValue(""),this.refresh()):this.callbacks.onCancel();return}if(matchesKey(data,Key.escape)){this.callbacks.onCancel();return}this.searchInput.handleInput(data),this.refresh()}getSearchInput(){return this.searchInput}};var StatusIndicator=class extends Loader{constructor(kind,ui,spinnerColorFn,messageColorFn,message,indicator){super(ui,spinnerColorFn,messageColorFn,message,indicator),this.kind=kind}renderInBorder(width){let line=super.render(width+2)[1]??"";return truncateToWidth(line.startsWith(" ")?line.slice(1).trimEnd():line.trimEnd(),width,"")}renderSpinnerInBorder(width){return truncateToWidth(this.getRenderedIndicator(),width,"")}dispose(){this.stop()}},WorkingStatusIndicator=class extends StatusIndicator{constructor(ui,message,indicator,colorFn){super("working",ui,colorFn??(text2=>theme.fg("accent",text2)),colorFn??(text2=>theme.fg("muted",text2)),message,indicator)}},RetryStatusIndicator=class extends StatusIndicator{constructor(ui,attempt2,maxAttempts,delayMs){let retryMessage=seconds=>`Retrying (${attempt2}/${maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;super("retry",ui,spinner=>theme.fg("warning",spinner),text2=>theme.fg("muted",text2),retryMessage(Math.ceil(delayMs/1e3))),this.countdown=new CountdownTimer(delayMs,ui,seconds=>{this.setMessage(retryMessage(seconds))},()=>{this.countdown=void 0})}dispose(){this.countdown?.dispose(),this.countdown=void 0,super.dispose()}},CompactionStatusIndicator=class extends StatusIndicator{constructor(ui,reason){let cancelHint=`(${keyText("app.interrupt")} to cancel)`,label=reason==="manual"?`Compacting context... ${cancelHint}`:`${reason==="overflow"?"Context overflow detected, ":""}Auto-compacting... ${cancelHint}`;super("compaction",ui,spinner=>theme.fg("accent",spinner),text2=>theme.fg("muted",text2),label)}},BranchSummaryStatusIndicator=class extends StatusIndicator{constructor(ui){super("branchSummary",ui,spinner=>theme.fg("accent",spinner),text2=>theme.fg("muted",text2),`Summarizing branch... (${keyText("app.interrupt")} to cancel)`)}},IdleStatus=class{invalidate(){}render(width){let emptyLine=" ".repeat(width);return[emptyLine,emptyLine]}};function formatDecision(trustPath,decision){if(decision===null)return"none";let label=decision.decision?"trusted":"untrusted";return trustPath!==void 0&&decision.path!==trustPath?`${label} (inherited from ${decision.path})`:`${label} (${decision.path})`}var TrustSelectorComponent=class extends Container{constructor(options){super(),this.savedDecision=options.savedDecision,this.trustOptions=getProjectTrustOptions(options.cwd),this.selectedIndex=Math.max(0,this.trustOptions.findIndex(option=>this.isSavedOption(option))),this.onSelectCallback=options.onSelect,this.onCancelCallback=options.onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Project trust")),1,0)),this.addChild(new Text(theme.fg("muted",options.cwd),1,0)),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",`Saved decision: ${formatDecision(this.trustOptions[0]?.savedPath,options.savedDecision)}`),1,0)),this.addChild(new Text(theme.fg("muted",`Current session: ${options.projectTrusted?"trusted":"untrusted"}`),1,0)),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new Text(rawKeyHint("\u2191\u2193","navigate")+" "+keyHint("tui.select.confirm","save")+" "+keyHint("tui.select.cancel","cancel"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}isSavedOption(option){return option.savedPath!==void 0&&this.savedDecision?.decision===option.trusted&&this.savedDecision.path===option.savedPath}updateList(){this.listContainer.clear();for(let i=0;i<this.trustOptions.length;i++){let option=this.trustOptions[i];if(!option)continue;let isSelected=i===this.selectedIndex,currentMarker=this.isSavedOption(option)?theme.fg("accent","\u2713 "):" ",prefix=isSelected?theme.fg("accent","\u2192 "):" ",label=isSelected?theme.fg("accent",option.label):theme.fg("text",option.label);this.listContainer.addChild(new Text(`${prefix}${currentMarker}${label}`,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.trustOptions.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
1358
1358
|
`){let selected=this.trustOptions[this.selectedIndex];selected&&this.onSelectCallback({trusted:selected.trusted,updates:selected.updates})}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}};var HIDDEN_BUILTIN_COMMANDS=["debug","arminsayshi","dementedelves"],InteractiveEditorHost=class{constructor(options){this.submitHandlers=new Set,this.options=options}onSubmit(handler){return this.submitHandlers.add(handler),()=>this.submitHandlers.delete(handler)}getCursor(){return this.options.getEditor().getCursor?.()}onInput(handler){return this.options.addTerminalInputListener(data=>this.isEditorFocused()?handler(data):void 0)}isEditorFocused(){let editor=this.options.getEditor();return this.options.getFocusedComponent()===editor&&!this.options.hasOverlay()&&!editor.isShowingAutocomplete?.()}clear(){this.submitHandlers.clear()}classify(text2){if(text2.startsWith("!"))return"bash";if(!text2.startsWith("/"))return"prompt";let name=text2.slice(1).split(/\s/,1)[0];return BUILTIN_SLASH_COMMANDS.some(command=>command.name===name)||HIDDEN_BUILTIN_COMMANDS.includes(name)||this.options.isSessionCommand(name)?"command":"prompt"}intercept(text2,mode){if(mode==="steer"&&this.declinedFollowUp===text2||this.submitHandlers.size===0)return!1;let event={text:text2,mode,kind:this.classify(text2)};for(let handler of this.submitHandlers)try{let result2=handler(event);if(!result2?.handled)continue;return this.options.setEditorText(result2.editorText??""),this.options.requestRender(),!0}catch(error){return this.options.setEditorText(text2),this.options.showError(`Editor submit handler failed: ${error instanceof Error?error.message:String(error)}`),!0}return mode==="followUp"&&(this.declinedFollowUp=text2,queueMicrotask(()=>{this.declinedFollowUp=void 0})),!1}};var InteractiveThemeController=class{constructor(ui,options){this.terminalTheme=detectTerminalBackgroundFromEnv().theme,this.autoSyncEnabled=!1,this.ui=ui,this.getSettingsManager=options.getSettingsManager,this.showError=options.showError,this.onChanged=options.onChanged,this.currentThemeSetting=options.initialThemeSetting,this.activeThemeName=resolveThemeSetting(this.currentThemeSetting??this.getSettingsManager().getThemeSetting(),this.terminalTheme),initTheme(this.activeThemeName,!0),this.bindTerminalColorSchemeListener()}rebindTui(){this.terminalColorSchemeUnsubscribe?.(),this.bindTerminalColorSchemeListener(),this.ui.setTerminalColorSchemeNotifications(this.autoSyncEnabled)}async applyFromSettings(){let settingsManager=this.getSettingsManager(),themeSetting=this.currentThemeSetting??settingsManager.getThemeSetting(),autoTheme=parseAutoThemeSetting(themeSetting);if(autoTheme){this.terminalTheme=await detectTerminalThemeForAuto({ui:this.ui,timeoutMs:100}),this.setAutoSync(!0),this.applyThemeName(this.terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme,!0);return}if(this.setAutoSync(!1),themeSetting!==void 0){this.applyThemeName(themeSetting,!0);return}let detection=await detectTerminalBackgroundTheme({ui:this.ui,timeoutMs:100});this.terminalTheme=detection.theme,this.applyThemeName(detection.theme).success&&detection.confidence==="high"&&(settingsManager.setTheme(detection.theme),await settingsManager.flush())}getThemeSelection(){return this.currentThemeSetting??this.getSettingsManager().getThemeSetting()??this.activeThemeName}setThemeName(themeName,showError=!1){this.setAutoSync(!1);let result2=this.applyThemeName(themeName,showError);return result2.success&&(this.currentThemeSetting=themeName),result2}async setThemeSetting(themeSetting){this.currentThemeSetting=themeSetting,await this.applyFromSettings()}setThemeInstance(themeInstance){return this.setAutoSync(!1),setThemeInstance(themeInstance),this.activeThemeName="<in-memory>",this.notifyChanged(),{success:!0}}preview(themeSettingOrName){let themeName=resolveThemeSetting(themeSettingOrName,this.terminalTheme)??this.activeThemeName;themeName&&setTheme(themeName,!0).success&&(this.ui.invalidate(),this.ui.requestRender())}disableAutoSync(){this.setAutoSync(!1)}dispose(){this.setAutoSync(!1),this.terminalColorSchemeUnsubscribe?.(),this.terminalColorSchemeUnsubscribe=void 0}getTerminalTheme(){return this.terminalTheme}applyThemeName(themeName,showError=!1){let result2=setTheme(themeName,!0);return this.activeThemeName=result2.success?themeName:"dark",this.notifyChanged(),!result2.success&&showError&&this.showError(`Failed to load theme "${themeName}": ${result2.error}
|
|
1359
|
-
Fell back to dark theme.`),result2}notifyChanged(){this.ui.invalidate(),this.onChanged()}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalTheme(terminalTheme))}applyTerminalTheme(terminalTheme){if(!this.autoSyncEnabled)return;this.terminalTheme=terminalTheme;let autoTheme=parseAutoThemeSetting(this.currentThemeSetting??this.getSettingsManager().getThemeSetting());if(!autoTheme){this.setAutoSync(!1);return}let themeName=terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;themeName!==this.activeThemeName&&this.applyThemeName(themeName)}};var ToolGroupComponent=class{constructor(toolGroup,tools=[]){this.tools=[],this.expanded=!1,this.toolGroup=toolGroup;for(let tool of tools)this.addTool(tool)}addTool(tool){tool.setExpanded(this.expanded),this.tools.push(tool)}setExpanded(expanded){this.expanded=expanded;for(let tool of this.tools)tool.setExpanded(expanded)}setShowImages(show){for(let tool of this.tools)tool.setShowImages(show)}setImageWidthCells(width){for(let tool of this.tools)tool.setImageWidthCells(width)}invalidate(){for(let tool of this.tools)tool.invalidate()}dispose(){for(let tool of this.tools)tool.dispose()}render(width){if(this.tools.length===0)return[];let safeWidth=Math.max(1,width);return this.expanded?this.tools.flatMap(tool=>tool.render(safeWidth)):["",...this.renderCollapsed(safeWidth)]}renderCollapsed(width){let lines=this.tools.flatMap(tool=>tool.renderCallSummary(width).map(line=>line.replace(/[ \t]+$/g,"")));for(let i=lines.length-1;i>=0;i--)if(lines[i].trim().length>0){let hint2=theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`),hintWidth=visibleWidth(hint2);lines[i]=hintWidth>=width?truncateToWidth(hint2,width,"..."):truncateToWidth(lines[i],width-hintWidth,"...")+hint2;break}if(this.toolGroup==="explore"){let error;for(let index3=this.tools.length-1;index3>=0&&(error=this.tools[index3]?.getFinalErrorSummary(),!error);index3--);error&&lines.push(truncateToWidth(theme.fg("error",` ${error}`),width,"..."))}return lines}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat){disposeAll(chat.children)}function isToolChatComponent(child){return child instanceof ToolExecutionComponent||child instanceof ToolGroupComponent}function appendToolRow(chat,component,expanded){let toolGroup=component.toolGroup?.trim(),children=chat.children,lastChild=children[children.length-1];if(toolGroup&&lastChild instanceof ToolGroupComponent&&lastChild.toolGroup===toolGroup){lastChild.addTool(component);return}if(toolGroup&&lastChild instanceof ToolExecutionComponent&&lastChild.toolGroup?.trim()===toolGroup){let group=new ToolGroupComponent(toolGroup,[lastChild,component]);group.setExpanded(expanded),children[children.length-1]=group;return}chat.addChild(component)}function toolDetachHint(keybindings){return{isDetachable:name=>name==="bash"||name==="powershell"||name==="subagent",keyLabel:()=>keyLabel("app.backgroundTasks.detach",{keybindings})}}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value2=Reflect.get(tui,property,tui);if(typeof value2!="function")return value2;let methodTui=tui,method=value2;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value2)=>{let tui=getTui();return Reflect.set(tui,property,value2,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isWorkingStatusEditor(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends Text{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){super(expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.getCollapsedText=getCollapsedText,this.getExpandedText=getExpandedText}setExpanded(expanded){this.setText(expanded?this.getExpandedText():this.getCollapsedText())}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value2){return value2.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value2)?value2:`'${value2.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType]})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(formatAuthSelectorProviderType).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.defaultHiddenThinkingLabel="Thinking...",this.hiddenThinkingLabel=this.defaultHiddenThinkingLabel,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.bugReportHintShown=!1,this.extensionSelector=void 0,this.extensionInput=void 0,this.extensionEditor=void 0,this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),await this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo)return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&(this.options.verbose||!this.settingsManager.getQuietStartup())){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,await this.themeController.applyFromSettings(),this.options.verbose||!this.settingsManager.getQuietStartup()){let logo=theme.bold(theme.fg("accent",APP_NAME))+theme.fg("dim",` v${this.version}`),hint2=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=[hint2("app.interrupt","to interrupt"),hint2("app.clear","to clear"),rawKeyHint(`${keyText("app.clear")} twice`,"to exit"),hint2("app.exit","to exit (empty)"),hint2("app.suspend","to suspend"),keyHint("tui.editor.deleteToLineEnd","to delete to end"),hint2("app.thinking.cycle","to cycle thinking level"),rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`,"to cycle models"),hint2("app.model.select","to select model"),hint2("app.tools.expand","to expand tools"),hint2("app.thinking.toggle","to expand thinking"),hint2("app.editor.external","for external editor"),rawKeyHint("/","for commands"),rawKeyHint("!","to run bash"),rawKeyHint("!!","to run bash (no context)"),hint2("app.message.followUp","to queue follow-up"),hint2("app.message.dequeue","to edit all queued messages"),hint2("app.clipboard.pasteImage","to paste image (with text fallback)"),rawKeyHint("drop files","to attach")].join(`
|
|
1359
|
+
Fell back to dark theme.`),result2}notifyChanged(){this.ui.invalidate(),this.onChanged()}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalTheme(terminalTheme))}applyTerminalTheme(terminalTheme){if(!this.autoSyncEnabled)return;this.terminalTheme=terminalTheme;let autoTheme=parseAutoThemeSetting(this.currentThemeSetting??this.getSettingsManager().getThemeSetting());if(!autoTheme){this.setAutoSync(!1);return}let themeName=terminalTheme==="light"?autoTheme.lightTheme:autoTheme.darkTheme;themeName!==this.activeThemeName&&this.applyThemeName(themeName)}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{render(width){let previous;for(let child of this.children){if(child instanceof ToolExecutionComponent){let{afterTool,afterOther}=toolStyle.gap;child.setLeadingGap(previous instanceof ToolExecutionComponent?afterTool:afterOther)}previous=child}return super.render(width)}clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat){disposeAll(chat.children)}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value2=Reflect.get(tui,property,tui);if(typeof value2!="function")return value2;let methodTui=tui,method=value2;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value2)=>{let tui=getTui();return Reflect.set(tui,property,value2,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isWorkingStatusEditor(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends Text{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){super(expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.getCollapsedText=getCollapsedText,this.getExpandedText=getExpandedText}setExpanded(expanded){this.setText(expanded?this.getExpandedText():this.getCollapsedText())}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value2){return value2.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value2)?value2:`'${value2.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType]})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(formatAuthSelectorProviderType).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.defaultHiddenThinkingLabel="Thinking...",this.hiddenThinkingLabel=this.defaultHiddenThinkingLabel,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.bugReportHintShown=!1,this.extensionSelector=void 0,this.extensionInput=void 0,this.extensionEditor=void 0,this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),await this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo)return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&(this.options.verbose||!this.settingsManager.getQuietStartup())){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,await this.themeController.applyFromSettings(),this.options.verbose||!this.settingsManager.getQuietStartup()){let logo=theme.bold(theme.fg("accent",APP_NAME))+theme.fg("dim",` v${this.version}`),hint2=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=[hint2("app.interrupt","to interrupt"),hint2("app.clear","to clear"),rawKeyHint(`${keyText("app.clear")} twice`,"to exit"),hint2("app.exit","to exit (empty)"),hint2("app.suspend","to suspend"),keyHint("tui.editor.deleteToLineEnd","to delete to end"),hint2("app.thinking.cycle","to cycle thinking level"),rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`,"to cycle models"),hint2("app.model.select","to select model"),hint2("app.tools.expand","to expand tools"),hint2("app.thinking.toggle","to expand thinking"),hint2("app.editor.external","for external editor"),rawKeyHint("/","for commands"),rawKeyHint("!","to run bash"),rawKeyHint("!!","to run bash (no context)"),hint2("app.message.followUp","to queue follow-up"),hint2("app.message.dequeue","to edit all queued messages"),hint2("app.clipboard.pasteImage","to paste image (with text fallback)"),rawKeyHint("drop files","to attach")].join(`
|
|
1360
1360
|
`),compactInstructions=[hint2("app.interrupt","interrupt"),rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`,"clear/exit"),rawKeyHint("/","commands"),rawKeyHint("!","bash"),hint2("app.tools.expand","more")].join(theme.fg("muted"," \xB7 ")),compactOnboarding=theme.fg("dim",`Press ${keyText("app.tools.expand")} to show full startup help and loaded resources.`),onboarding=theme.fg("dim","Pi can explain its own features and look up its docs. Ask it how to use or extend Pi.");this.builtInHeader=new ExpandableText(()=>`${logo}
|
|
1361
1361
|
${compactInstructions}
|
|
1362
1362
|
${compactOnboarding}
|
|
@@ -1377,7 +1377,7 @@ ${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let
|
|
|
1377
1377
|
${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let themeDiagnostics=themesResult.diagnostics;if(themeDiagnostics.length>0){let warningLines=this.formatDiagnostics(themeDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new Text(`${theme.fg("warning","[Theme conflicts]")}
|
|
1378
1378
|
${warningLines}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}}}async bindCurrentSessionExtensions(){let uiContext=this.createExtensionUIContext();await this.session.bindExtensions({uiContext,mode:"tui",backgroundEnabled:!0,abortHandler:()=>{this.restoreQueuedMessagesToEditor({abort:!0})},commandContextActions:{waitForIdle:()=>this.session.waitForIdle(),newSession:async options=>{this.clearStatusIndicator();try{return await this.runtimeHost.newSession(options)}catch(error){return this.handleFatalRuntimeError("Failed to create session",error)}},fork:async(entryId,options)=>{try{let result2=await this.runtimeHost.fork(entryId,options);return result2.cancelled||(this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")),{cancelled:result2.cancelled}}catch(error){return this.handleFatalRuntimeError("Failed to fork session",error)}},navigateTree:async(targetId,options)=>{let result2=await this.session.navigateTree(targetId,{summarize:options?.summarize,customInstructions:options?.customInstructions,replaceInstructions:options?.replaceInstructions,label:options?.label});return result2.cancelled?{cancelled:!0}:(this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1}),{cancelled:!1})},switchSession:async(sessionPath,options)=>this.handleResumeSession(sessionPath,options),reload:async()=>{await this.handleReloadCommand()}},shutdownHandler:()=>{this.shutdownRequested=!0,this.session.isIdle&&this.shutdown()},onError:error=>{this.showExtensionError(error.extensionPath,error.error,error.stack)}}),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.setupAutocompleteProvider();let extensionRunner=this.session.extensionRunner;this.setupExtensionShortcuts(extensionRunner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0}),this.showStartupNoticesIfNeeded()}applyFullscreenScrollbarSetting(){this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar())}applyRuntimeSettings(){setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides()),configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs()),this.applyFullscreenScrollbarSetting(),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect()),this.footer.setSession(this.session),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerDataProvider.setCwd(this.sessionManager.getCwd()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());let clearOnShrink=this.settingsManager.getClearOnShrink();this.ui.setClearOnShrink(clearOnShrink),!clearOnShrink&&!this.activeStatusIndicator&&this.statusContainer.clear();let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor.setPaddingX(editorPaddingX),this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible),this.editor!==this.defaultEditor&&(this.editor.setPaddingX?.(editorPaddingX),this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible))}async rebindCurrentSession(options={}){let session=this.session;this.unsubscribe?.(),this.unsubscribe=void 0,this.applyRuntimeSettings(),options.renderBeforeBind&&(this.renderCurrentSessionState(),this.subscribeToAgent()),await this.bindCurrentSessionExtensions(),this.session===session&&(options.renderBeforeBind||this.subscribeToAgent(),await this.updateAvailableProviderCount(),this.updateEditorBorderColor(),this.updateTerminalTitle())}async handleFatalRuntimeError(prefix,error){let message=error instanceof Error?error.message:String(error);this.showError(`${prefix}: ${message}`);let extensionHint=this.getCrashExtensionHint(error);extensionHint&&this.chatContainer.addChild(new Text(theme.fg("warning",extensionHint),this.outputPad,0)),this.recordCrash("fatal_error",error)&&this.chatContainer.addChild(new Text(theme.fg("muted",this.crashReportInstructions()),this.outputPad,0)),stopThemeWatcher(),this.stop("transcript"),process.exit(1)}getCrashExtensionHint(error){try{return formatCrashExtensionHint(findExtensionStackMatches(error instanceof Error?error.stack:void 0,this.session.resourceLoader.getExtensions().extensions))}catch{return}}recordCrash(kind,error){try{return recordCrash({kind,error,sessionFile:this.session.sessionFile,cwd:this.session.sessionManager.getCwd()})!==void 0}catch{return!1}}crashReportInstructions(){return`To report this crash: ${this.session.sessionFile?`run \`${APP_NAME} -r\` to resume the session, then`:"start pi and"} run /bug. The crash details are attached automatically.`}suggestBugReport(){this.bugReportHintShown||(this.bugReportHintShown=!0,this.chatContainer.addChild(new Text(theme.fg("muted",`If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`),this.outputPad,0)),this.ui.requestRender())}maybeSuggestBugReport(message){message.stopReason!=="error"||isRetryableAssistantError(message)||/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage??"")||this.suggestBugReport()}renderCurrentSessionState(){this.loadedResourcesContainer.clear(),this.chatContainer.clear(),this.pendingMessagesContainer.clear(),this.compactionQueuedMessages=[],this.streamingComponent=void 0,this.streamingMessage=void 0,this.pendingTools.clear(),this.renderInitialMessages()}getRegisteredToolDefinition(toolName){return withBuiltInRenderers(toolName,this.session.getToolDefinition(toolName))}getMarkdownTransformers(){return[this.mermaidMarkdownTransformer,...this.session.extensionRunner.getMarkdownTransformers()]}setupExtensionShortcuts(extensionRunner){let shortcuts=extensionRunner.getShortcuts(this.keybindings.getEffectiveConfig());shortcuts.size!==0&&(this.defaultEditor.onExtensionShortcut=data=>{for(let[shortcutStr,shortcut]of shortcuts)if(matchesKey(data,shortcutStr))return Promise.resolve(shortcut.handler(extensionRunner.createContext())).catch(err2=>{this.showError(`Shortcut handler error: ${err2 instanceof Error?err2.message:String(err2)}`)}),!0;return!1})}setExtensionStatus(key,text2){this.footerDataProvider.setExtensionStatus(key,text2),this.ui.requestRender()}setEditorWorkingStatusIndicator(indicator){return this.defaultEditor.setWorkingStatusIndicator(void 0),isWorkingStatusEditor(this.editor)?(this.editor.setWorkingStatusIndicator(indicator),!0):!1}showStatusIndicator(indicator){if(this.activeStatusIndicator?.dispose(),this.activeStatusIndicator=indicator,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),this.setEditorWorkingStatusIndicator(indicator)){this.activeWorkingIndicatorEmbedded=!0;return}this.statusContainer.addChild(indicator)}clearStatusIndicator(kind){if(kind&&this.activeStatusIndicator?.kind!==kind)return;let clearedIndicator=this.activeStatusIndicator,clearedIndicatorWasEmbedded=this.activeWorkingIndicatorEmbedded;clearedIndicator?.dispose(),this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),clearedIndicator&&!clearedIndicatorWasEmbedded&&this.options.tuiMode==="regular"&&this.ui.getClearOnShrink()&&this.statusContainer.addChild(this.idleStatus)}showWorkingStatusIndicator(){let colorFn=isWorkingStatusEditor(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new WorkingStatusIndicator(this.ui,this.workingMessage??this.defaultWorkingMessage,this.workingIndicatorOptions,colorFn))}setWorkingVisible(visible){if(this.workingVisible=visible,!visible){this.clearStatusIndicator("working"),this.ui.requestRender();return}this.session.isStreaming&&this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator(),this.ui.requestRender()}setWorkingIndicator(options){this.workingIndicatorOptions=options,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setIndicator(options),this.ui.requestRender()}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label??this.defaultHiddenThinkingLabel;for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHiddenThinkingLabel(this.hiddenThinkingLabel);this.streamingComponent&&this.streamingComponent.setHiddenThinkingLabel(this.hiddenThinkingLabel),this.ui.requestRender()}setExtensionWidget(key,content,options){let placement=options?.placement??"aboveEditor",removeExisting=map=>{let existing=map.get(key);existing?.dispose&&existing.dispose(),map.delete(key)};if(removeExisting(this.extensionWidgetsAbove),removeExisting(this.extensionWidgetsBelow),content===void 0){this.renderWidgets();return}let component;if(Array.isArray(content)){let container=new Container;for(let line of content.slice(0,_InteractiveMode.MAX_WIDGET_LINES))container.addChild(new Text(line,1,0));content.length>_InteractiveMode.MAX_WIDGET_LINES&&container.addChild(new Text(theme.fg("muted","... (widget truncated)"),1,0)),component=container}else component=content(this.ui,theme);(placement==="belowEditor"?this.extensionWidgetsBelow:this.extensionWidgetsAbove).set(key,component),this.renderWidgets()}clearExtensionWidgets(){for(let widget of this.extensionWidgetsAbove.values())widget.dispose?.();for(let widget of this.extensionWidgetsBelow.values())widget.dispose?.();this.extensionWidgetsAbove.clear(),this.extensionWidgetsBelow.clear(),this.renderWidgets()}resetExtensionUI(){this.editorHost.clear(),this.extensionSelector&&this.hideExtensionSelector(),this.extensionInput&&this.hideExtensionInput(),this.extensionEditor&&this.hideExtensionEditor(),this.ui.hideOverlay(),this.clearExtensionTerminalInputListeners(),this.setExtensionFooter(void 0),this.setExtensionHeader(void 0),this.clearExtensionWidgets(),this.footerDataProvider.clearExtensionStatuses(),this.footer.invalidate(),this.autocompleteProviderWrappers=[],this.setCustomEditorComponent(void 0),this.setupAutocompleteProvider(),this.defaultEditor.onExtensionShortcut=void 0,this.updateTerminalTitle(),this.workingMessage=void 0,this.workingVisible=!0,this.setWorkingIndicator(),this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`),this.setHiddenThinkingLabel()}static{this.MAX_WIDGET_LINES=10}renderWidgets(){!this.widgetContainerAbove||!this.widgetContainerBelow||(this.renderWidgetContainer(this.widgetContainerAbove,this.extensionWidgetsAbove,!0,!0),this.renderWidgetContainer(this.widgetContainerBelow,this.extensionWidgetsBelow,!1,!1),this.ui.requestRender())}renderWidgetContainer(container,widgets,spacerWhenEmpty,leadingSpacer){if(container.clear(),widgets.size===0){spacerWhenEmpty&&container.addChild(new Spacer(1));return}leadingSpacer&&container.addChild(new Spacer(1));for(let component of widgets.values())container.addChild(component)}setExtensionFooter(factory){this.customFooter?.dispose&&this.customFooter.dispose(),this.footerContainer.clear(),factory?(this.customFooter=factory(this.ui,theme,this.footerDataProvider),this.footerContainer.addChild(this.customFooter)):(this.customFooter=void 0,this.footerContainer.addChild(this.footer)),this.ui.requestRender()}setExtensionHeader(factory){if(!this.builtInHeader)return;this.customHeader?.dispose&&this.customHeader.dispose();let currentHeader=this.customHeader||this.builtInHeader,index3=this.headerContainer.children.indexOf(currentHeader);factory?(this.customHeader=factory(this.ui,theme),isExpandable(this.customHeader)&&this.customHeader.setExpanded(this.toolOutputExpanded),index3!==-1?this.headerContainer.children[index3]=this.customHeader:this.headerContainer.children.unshift(this.customHeader)):(this.customHeader=void 0,isExpandable(this.builtInHeader)&&this.builtInHeader.setExpanded(this.toolOutputExpanded),index3!==-1&&(this.headerContainer.children[index3]=this.builtInHeader)),this.ui.requestRender()}addExtensionTerminalInputListener(handler){let subscription={handler,unsubscribe:this.ui.addInputListener(handler)};return this.extensionTerminalInputSubscriptions.add(subscription),()=>{subscription.unsubscribe(),this.extensionTerminalInputSubscriptions.delete(subscription)}}rebindExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe(),subscription.unsubscribe=this.ui.addInputListener(subscription.handler)}clearExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe();this.extensionTerminalInputSubscriptions.clear()}createProjectTrustContext(cwd){let ui=this.createExtensionUIContext();return{cwd,mode:"tui",hasUI:!0,ui:{select:ui.select,confirm:ui.confirm,input:ui.input,notify:ui.notify}}}createExtensionUIContext(){return{select:(title,options,opts)=>this.showExtensionSelector(title,options,opts),confirm:(title,message,opts)=>this.showExtensionConfirm(title,message,opts),input:(title,placeholder,opts)=>this.showExtensionInput(title,placeholder,opts),notify:(message,type)=>this.showExtensionNotify(message,type),onTerminalInput:handler=>this.addExtensionTerminalInputListener(handler),editorHost:this.editorHost,setStatus:(key,text2)=>this.setExtensionStatus(key,text2),setWorkingMessage:message=>{this.workingMessage=message,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(message??this.defaultWorkingMessage)},setWorkingVisible:visible=>this.setWorkingVisible(visible),setWorkingIndicator:options=>this.setWorkingIndicator(options),setHiddenThinkingLabel:label=>this.setHiddenThinkingLabel(label),setWidget:(key,content,options)=>this.setExtensionWidget(key,content,options),setFooter:factory=>this.setExtensionFooter(factory),setHeader:factory=>this.setExtensionHeader(factory),setTitle:title=>this.ui.terminal.setTitle(title),custom:(factory,options)=>this.showExtensionCustom(factory,options),pasteToEditor:text2=>this.editor.handleInput(`\x1B[200~${text2}\x1B[201~`),setEditorText:text2=>this.editor.setText(text2),getEditorText:()=>this.editor.getExpandedText?.()??this.editor.getText(),editor:(title,prefill)=>this.showExtensionEditor(title,prefill),addAutocompleteProvider:factory=>{this.autocompleteProviderWrappers.push(factory),this.setupAutocompleteProvider()},setEditorComponent:factory=>this.setCustomEditorComponent(factory),getEditorComponent:()=>this.editorComponentFactory,get theme(){return theme},getAllThemes:()=>getAvailableThemesWithPaths(),getTheme:name=>getThemeByName(name),setTheme:themeOrName=>{if(themeOrName instanceof Theme)return this.themeController.setThemeInstance(themeOrName);let result2=this.themeController.setThemeName(themeOrName);return result2.success&&this.settingsManager.getTheme()!==themeOrName&&this.settingsManager.setTheme(themeOrName),result2},getToolsExpanded:()=>this.toolOutputExpanded,setToolsExpanded:expanded=>this.setToolsExpanded(expanded)}}showExtensionSelector(title,options,opts){return new Promise(resolve17=>{if(opts?.signal?.aborted){resolve17(void 0);return}let onAbort=()=>{this.hideExtensionSelector(),resolve17(void 0)};opts?.signal?.addEventListener("abort",onAbort,{once:!0}),this.extensionSelector=new ExtensionSelectorComponent(title,options,option=>{opts?.signal?.removeEventListener("abort",onAbort),this.hideExtensionSelector(),resolve17(option)},()=>{opts?.signal?.removeEventListener("abort",onAbort),this.hideExtensionSelector(),resolve17(void 0)},{tui:this.ui,timeout:opts?.timeout,description:opts?.description,onToggleToolsExpanded:()=>this.toggleToolOutputExpansion()}),this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(this.extensionSelector),this.ui.setFocus(this.extensionSelector),this.ui.requestRender()})}hideExtensionSelector(){this.extensionSelector?.dispose(),this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.extensionSelector=void 0,this.ui.setFocus(this.editor),this.ui.requestRender()}async showExtensionConfirm(title,message,opts){return await this.showExtensionSelector(title,["Yes","No"],{...opts,description:message})==="Yes"}async promptForMissingSessionCwd(error){return await this.showExtensionConfirm("Session cwd not found",formatMissingSessionCwdPrompt(error.issue))?error.issue.fallbackCwd:void 0}showExtensionInput(title,placeholder,opts){return new Promise(resolve17=>{if(opts?.signal?.aborted){resolve17(void 0);return}let onAbort=()=>{this.hideExtensionInput(),resolve17(void 0)};opts?.signal?.addEventListener("abort",onAbort,{once:!0}),this.extensionInput=new ExtensionInputComponent(title,placeholder,value2=>{opts?.signal?.removeEventListener("abort",onAbort),this.hideExtensionInput(),resolve17(value2)},()=>{opts?.signal?.removeEventListener("abort",onAbort),this.hideExtensionInput(),resolve17(void 0)},{tui:this.ui,timeout:opts?.timeout}),this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(this.extensionInput),this.ui.setFocus(this.extensionInput),this.ui.requestRender()})}hideExtensionInput(){this.extensionInput?.dispose(),this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.extensionInput=void 0,this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionEditor(title,prefill){return new Promise(resolve17=>{this.extensionEditor=new ExtensionEditorComponent(this.ui,this.keybindings,title,prefill,value2=>{this.hideExtensionEditor(),resolve17(value2)},()=>{this.hideExtensionEditor(),resolve17(void 0)},void 0,this.settingsManager.getExternalEditorCommand()),this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(this.extensionEditor),this.ui.setFocus(this.extensionEditor),this.ui.requestRender()})}hideExtensionEditor(){this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.extensionEditor=void 0,this.ui.setFocus(this.editor),this.ui.requestRender()}setCustomEditorComponent(factory){this.editorComponentFactory=factory;let currentText=this.editor.getText();if(this.disposeActiveSelector(),this.editorContainer.clear(),factory){let newEditor=factory(this.ui,getEditorTheme(),this.keybindings);newEditor.onSubmit=this.defaultEditor.onSubmit,newEditor.onChange=this.defaultEditor.onChange,newEditor.setText(currentText),newEditor.borderColor!==void 0&&(newEditor.borderColor=this.defaultEditor.borderColor),newEditor.setPaddingX!==void 0&&newEditor.setPaddingX(this.defaultEditor.getPaddingX()),newEditor.setAutocompleteMaxVisible!==void 0&&newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible()),newEditor.setAutocompleteProvider&&this.autocompleteProvider&&newEditor.setAutocompleteProvider(this.autocompleteProvider);let customEditor=newEditor;if("actionHandlers"in customEditor&&customEditor.actionHandlers instanceof Map){customEditor.onEscape||(customEditor.onEscape=()=>this.defaultEditor.onEscape?.()),customEditor.onCtrlD||(customEditor.onCtrlD=()=>this.defaultEditor.onCtrlD?.()),customEditor.onPasteImage||(customEditor.onPasteImage=()=>this.defaultEditor.onPasteImage?.()),customEditor.onExtensionShortcut||(customEditor.onExtensionShortcut=data=>this.defaultEditor.onExtensionShortcut?.(data));for(let[action,handler]of this.defaultEditor.actionHandlers)customEditor.actionHandlers.set(action,handler)}this.editor=newEditor}else this.defaultEditor.setText(currentText),this.editor=this.defaultEditor;this.editorContainer.addChild(this.editor),this.activeStatusIndicator&&(this.statusContainer.clear(),this.activeWorkingIndicatorEmbedded=this.setEditorWorkingStatusIndicator(this.activeStatusIndicator),this.activeWorkingIndicatorEmbedded||this.statusContainer.addChild(this.activeStatusIndicator)),this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionNotify(message,type){type==="error"?this.showError(message):type==="warning"?this.showWarning(message):this.showStatus(message)}async showExtensionCustom(factory,options){let savedText2=this.editor.getText(),isOverlay=options?.overlay??!1,restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.editor.setText(savedText2),this.ui.setFocus(this.editor),this.ui.requestRender()};return new Promise((resolve17,reject)=>{let component,closed=!1,close=result2=>{if(!closed){closed=!0,isOverlay?this.ui.hideOverlay():restoreEditor3(),resolve17(result2);try{component?.dispose?.()}catch{}}};Promise.resolve(factory(this.ui,theme,this.keybindings,close)).then(c=>{if(!closed)if(component=c,isOverlay){let resolveOptions=()=>{if(options?.overlayOptions)return typeof options.overlayOptions=="function"?options.overlayOptions():options.overlayOptions;let w=component.width;return w?{width:w}:void 0},handle=this.ui.showOverlay(component,resolveOptions());options?.onHandle?.(handle)}else this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(component),this.ui.setFocus(component),this.ui.requestRender()}).catch(err2=>{closed||(isOverlay||restoreEditor3(),reject(err2))})})}showExtensionError(extensionPath,error,stack){let errorMsg=`Extension "${extensionPath}" error: ${error}`,errorText2=new Text(theme.fg("error",errorMsg),1,0);if(this.chatContainer.addChild(errorText2),stack){let stackLines=stack.split(`
|
|
1379
1379
|
`).slice(1).map(line=>theme.fg("dim",` ${line.trim()}`)).join(`
|
|
1380
|
-
`);stackLines&&this.chatContainer.addChild(new Text(stackLines,1,0))}this.ui.requestRender()}setupKeyHandlers(){this.defaultEditor.onEscape=()=>{if(this.session.isStreaming)this.restoreQueuedMessagesToEditor({abort:!0});else if(this.session.isBashRunning)this.session.abortBash();else if(this.isBashMode)this.editor.setText(""),this.isBashMode=!1,this.updateEditorBorderColor();else if(!this.editor.getText().trim()){let action=this.settingsManager.getDoubleEscapeAction();if(action!=="none"){let now=Date.now();now-this.lastEscapeTime<500?(action==="tree"?this.showTreeSelector():this.showUserMessageSelector(),this.lastEscapeTime=0):this.lastEscapeTime=now}}},this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onAction("app.suspend",()=>this.handleCtrlZ()),this.defaultEditor.onAction("app.thinking.cycle",()=>this.cycleThinkingLevel()),this.defaultEditor.onAction("app.model.cycleForward",()=>this.cycleModel("forward")),this.defaultEditor.onAction("app.model.cycleBackward",()=>this.cycleModel("backward")),this.ui.onDebug=()=>this.handleDebugCommand(),this.defaultEditor.onAction("app.model.select",()=>this.showModelSelector()),this.defaultEditor.onAction("app.tools.expand",()=>this.toggleToolOutputExpansion()),this.defaultEditor.onAction("app.thinking.toggle",()=>this.toggleThinkingBlockVisibility()),this.defaultEditor.onAction("app.editor.external",()=>{this.handleOpenExternalEditor()}),this.defaultEditor.onAction("app.message.copy",()=>{this.handleCopyCommand({flashConfirmation:!0,preferSelection:!0})}),this.defaultEditor.onAction("app.message.followUp",()=>this.handleFollowUp()),this.defaultEditor.onAction("app.message.dequeue",()=>this.handleDequeue()),this.defaultEditor.onAction("app.session.new",()=>this.handleClearCommand()),this.defaultEditor.onAction("app.session.tree",()=>this.showTreeSelector()),this.defaultEditor.onAction("app.session.fork",()=>this.showUserMessageSelector()),this.defaultEditor.onAction("app.session.resume",()=>this.showSessionSelector()),this.defaultEditor.onChange=text2=>{let wasBashMode=this.isBashMode;this.isBashMode=text2.trimStart().startsWith("!"),wasBashMode!==this.isBashMode&&this.updateEditorBorderColor()},this.defaultEditor.onPasteImage=()=>{this.handleClipboardPaste()}}async handleRightClickPaste(){let target=this.renderer.getFocusedComponent(),handleInput=target?.handleInput;if(!(!target||!handleInput))try{let text2=await readClipboardText();if(!text2||this.renderer.getFocusedComponent()!==target)return;handleInput.call(target,`\x1B[200~${text2}\x1B[201~`),this.ui.requestRender()}catch{}}async handleClipboardPaste(){try{let image=await readClipboardImage();if(image){let tmpDir=os7.tmpdir(),ext2=extensionForImageMimeType(image.mimeType)??"png",fileName=`pi-clipboard-${crypto2.randomUUID()}.${ext2}`,filePath=path13.join(tmpDir,fileName);fs8.writeFileSync(filePath,Buffer.from(image.bytes)),this.editor.insertTextAtCursor?.(filePath),this.ui.requestRender();return}let text2=await readClipboardText();text2&&(this.editor.insertTextAtCursor?.(text2),this.ui.requestRender())}catch{}}handleStartupSubmit(text2){this.editor.setText(text2),this.showStatus("Startup is still in progress")}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async text2=>{if(text2=text2.trim(),!!text2&&!this.editorHost.intercept(text2,"steer")){if(text2==="/settings"){this.showSettingsSelector(),this.editor.setText("");return}if(text2==="/scoped-models"){this.editor.setText(""),await this.showModelsSelector();return}if(text2==="/model"||text2.startsWith("/model ")){let searchTerm=text2.startsWith("/model ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleModelCommand(searchTerm);return}if(text2==="/thinking"||text2.startsWith("/thinking ")){let searchTerm=text2.startsWith("/thinking ")?text2.slice(10).trim():void 0;this.editor.setText(""),this.handleThinkingCommand(searchTerm);return}if(text2==="/export"||text2.startsWith("/export ")){await this.handleExportCommand(text2),this.editor.setText("");return}if(text2==="/import"||text2.startsWith("/import ")){await this.handleImportCommand(text2),this.editor.setText("");return}if(text2==="/share"){await this.handleShareCommand(),this.editor.setText("");return}if(text2==="/bug"||text2.startsWith("/bug ")){let hint2=text2.slice(4).trim();this.editor.setText(""),await this.handleBugCommand(hint2||void 0);return}if(text2==="/copy"){await this.handleCopyCommand(),this.editor.setText("");return}if(text2==="/name"||text2.startsWith("/name ")){this.handleNameCommand(text2),this.editor.setText("");return}if(text2==="/session"){this.handleSessionCommand(),this.editor.setText("");return}if(text2==="/changelog"){this.handleChangelogCommand(),this.editor.setText("");return}if(text2==="/hotkeys"){this.handleHotkeysCommand(),this.editor.setText("");return}if(text2==="/fork"){this.showUserMessageSelector(),this.editor.setText("");return}if(text2==="/clone"){this.editor.setText(""),await this.handleCloneCommand();return}if(text2==="/tree"){this.showTreeSelector(),this.editor.setText("");return}if(text2==="/trust"){this.showTrustSelector(),this.editor.setText("");return}if(text2==="/login"||text2.startsWith("/login ")){let providerRef=text2.startsWith("/login ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleLoginCommand(providerRef);return}if(text2==="/logout"){this.showOAuthSelector("logout"),this.editor.setText("");return}if(text2==="/new"){this.editor.setText(""),await this.handleClearCommand();return}if(text2==="/compact"||text2.startsWith("/compact ")){let customInstructions=text2.startsWith("/compact ")?text2.slice(9).trim():void 0;this.editor.setText(""),await this.handleCompactCommand(customInstructions);return}if(text2==="/reload"){this.editor.setText(""),await this.handleReloadCommand();return}if(text2==="/debug"){this.handleDebugCommand(),this.editor.setText("");return}if(text2==="/arminsayshi"){this.handleArminSaysHi(),this.editor.setText("");return}if(text2==="/dementedelves"){this.handleDementedDelves(),this.editor.setText("");return}if(text2==="/resume"){this.showSessionSelector(),this.editor.setText("");return}if(text2==="/quit"){this.editor.setText(""),await this.shutdown();return}if(text2.startsWith("!")){let isExcluded=text2.startsWith("!!"),command=isExcluded?text2.slice(2).trim():text2.slice(1).trim();if(command){if(this.session.isBashRunning){this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(text2);return}this.editor.addToHistory?.(text2),await this.handleBashCommand(command,isExcluded),this.isBashMode=!1,this.updateEditorBorderColor();return}}if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"steer");return}if(this.session.isStreaming){this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(text2):this.pendingUserInputs.push(text2),this.editor.addToHistory?.(text2)}}}subscribeToAgent(){this.unsubscribe=this.session.subscribe(async event=>{await this.handleEvent(event)})}async handleEvent(event){switch(this.isInitialized||await this.init(),this.footer.invalidate(),event.type){case"agent_start":this.pendingTools.clear(),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0);break;case"turn_start":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.workingVisible?this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator():this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":if(this.entriesRenderedByBoundaryCompaction.delete(event.entry.id))break;if(event.entry.type==="custom")this.addCustomEntryToChat(event.entry),this.ui.requestRender();else if(event.entry.type==="usage"&&event.entry.kind==="cache_warm")this.addCacheWarmingUsage(event.entry),this.ui.requestRender();else if(event.entry.type==="custom_message"&&event.entry.display)this.addMessageToChat(createCustomMessage(event.entry.customType,event.entry.content,event.entry.display,event.entry.details,event.entry.timestamp)),this.ui.requestRender();else if(event.entry.type==="compaction"){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.id!==event.entry.id)break;this.chatContainer.clear();let branch=this.sessionManager.getBranch(),compactionIndex=branch.findIndex(entry=>entry.id===event.entry.id),entriesAfterCompaction=new Set(branch.slice(compactionIndex+1).map(entry=>entry.id)),retainedEntries=entries.slice(1);this.renderSessionEntries(retainedEntries.filter(entry=>!entriesAfterCompaction.has(entry.id))),this.addMessageToChat(createCompactionSummaryMessage(event.entry.summary,event.entry.tokensBefore,event.entry.timestamp)),event.entry.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.entry.usage}),this.renderSessionEntries(retainedEntries.filter(entry=>entriesAfterCompaction.has(entry.id)));for(let entryId of entriesAfterCompaction)this.entriesRenderedByBoundaryCompaction.add(entryId);this.footer.invalidate(),this.ui.requestRender()}break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":event.message.role==="custom"?(this.addMessageToChat(event.message),this.ui.requestRender()):event.message.role==="user"?(this.addMessageToChat(event.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):event.message.role==="assistant"&&(this.streamingComponent=new AssistantMessageComponent(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=event.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let content of this.streamingMessage.content)if(content.type==="toolCall")if(this.pendingTools.has(content.id)){let component=this.pendingTools.get(content.id);component&&component.updateArgs(content.arguments)}else{let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),detachHint:toolDetachHint(this.keybindings)},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());component.setExpanded(this.toolOutputExpanded),appendToolRow(this.chatContainer,component,this.toolOutputExpanded),this.pendingTools.set(content.id,component)}this.ui.requestRender()}break;case"message_end":if(event.message.role==="user")break;if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message;let errorMessage6;if(this.streamingMessage.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage6=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=errorMessage6}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){errorMessage6||(errorMessage6=this.streamingMessage.errorMessage||"Error");for(let[,component]of this.pendingTools.entries())component.updateResult({content:[{type:"text",text:errorMessage6}],isError:!0});this.pendingTools.clear(),this.maybeSuggestBugReport(this.streamingMessage)}else{for(let[,component]of this.pendingTools.entries())component.setArgsComplete();this.maybeShowThinkingDropNotice(this.streamingMessage),this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{let component=this.pendingTools.get(event.toolCallId);component||(component=new ToolExecutionComponent(event.toolName,event.toolCallId,event.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),detachHint:toolDetachHint(this.keybindings)},this.getRegisteredToolDefinition(event.toolName),this.ui,this.sessionManager.getCwd()),component.setExpanded(this.toolOutputExpanded),appendToolRow(this.chatContainer,component,this.toolOutputExpanded),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError}),this.pendingTools.delete(event.toolCallId),this.ui.requestRender());break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortCompaction()},this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else event.errorMessage&&(event.reason==="manual"?this.showError(event.errorMessage):(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",event.errorMessage),1,0))));this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{this.clearStatusIndicator("retry"),event.source==="branchSummary"?this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)):this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c=>c.type==="text")).map(c=>c.text).join("")}showManagedToolStatus(status){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status.type==="warning"?`Warning: ${status.message}`:status.message,color2=status.type==="warning"?"warning":"dim";this.chatContainer.addChild(new Text(theme.fg(color2,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusText.setText(theme.fg("dim",message)),this.ui.requestRender();return}let spacer=new Spacer(1),text2=new Text(theme.fg("dim",message),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text2),this.lastStatusSpacer=spacer,this.lastStatusText=text2,this.ui.requestRender()}addCustomEntryToChat(entry){let renderer=this.session.extensionRunner.getEntryRenderer(entry.customType);if(!renderer)return;let component=new CustomEntryComponent(entry,renderer);if(component.setExpanded(this.toolOutputExpanded),!!component.hasContent()){if(this.streamingComponent){let streamingIndex=this.chatContainer.children.indexOf(this.streamingComponent);if(streamingIndex>=0){this.chatContainer.children.splice(streamingIndex,0,component);return}}this.chatContainer.addChild(component)}}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let renderer=this.session.extensionRunner.getMessageRenderer(message.customType),component=new CustomMessageComponent(message,renderer,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"system":break;case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.sessionManager.getEntries(),this.session.modelRuntime):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item)){this.addCustomEntryToChat(item);continue}if(isUsageSessionEntry(item)){this.addCacheWarmingUsage(item);continue}if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),detachHint:toolDetachHint(this.keybindings)},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());if(component.setExpanded(this.toolOutputExpanded),appendToolRow(this.chatContainer,component,this.toolOutputExpanded),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage6;if(message.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage6=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage6=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage6}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){let items=entries.flatMap(entry=>{if(entry.type==="custom"||entry.type==="usage"&&entry.kind==="cache_warm")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCacheWarmingUsage(entry){this.settingsManager.getShowCacheMissNotices()&&(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",formatCacheWarmingUsage(entry)),1,0)))}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens2=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`${label}: ${formatTokens(tokens2)} tokens billed${cost}`),1,0))}static countDroppedThinkingBlocks(message){let count=0;for(let diagnostic of message.diagnostics??[]){if(diagnostic.type!=="anthropic_input_transformations")continue;let transformations=diagnostic.details?.transformations;Array.isArray(transformations)&&(count+=transformations.filter(transformation=>typeof transformation=="object"&&transformation!==null&&transformation.type==="thinking_dropped").length)}return count}maybeShowThinkingDropNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let droppedCount=_InteractiveMode.countDroppedThinkingBlocks(message);if(droppedCount===0)return;let previousDroppedCount=0,branch=this.sessionManager.getBranch();for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="message"&&entry.message.role==="assistant"){previousDroppedCount=_InteractiveMode.countDroppedThinkingBlocks(entry.message);break}}if(droppedCount<=previousDroppedCount)return;let noun=droppedCount===1?"thinking block":"thinking blocks";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Anthropic dropped ${droppedCount} ${noun} (details in session)`),1,0))}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.sessionManager.getEntries(),message,this.session.modelRuntime);miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`);let text2=theme.fg("warning",`${label}: ${reBilled}`);this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(text2,1,0))}renderInitialMessages(){let entries=this.sessionManager.buildContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0}),this.renderProjectTrustWarningIfNeeded();let compactionCount=this.sessionManager.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}renderProjectTrustWarningIfNeeded(){this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(this.sessionManager.getCwd())||(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`),1,0)))}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve17=>{this.onInputCallback=text2=>{this.onInputCallback=void 0,resolve17(text2)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.sessionManager.buildContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,this.session.background.close(),options?.fromSignal&&(await this.runtimeHost.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeHost.dispose();let resumeCommand=formatResumeCommand(this.sessionManager);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1380
|
+
`);stackLines&&this.chatContainer.addChild(new Text(stackLines,1,0))}this.ui.requestRender()}setupKeyHandlers(){this.defaultEditor.onEscape=()=>{if(this.session.isStreaming)this.restoreQueuedMessagesToEditor({abort:!0});else if(this.session.isBashRunning)this.session.abortBash();else if(this.isBashMode)this.editor.setText(""),this.isBashMode=!1,this.updateEditorBorderColor();else if(!this.editor.getText().trim()){let action=this.settingsManager.getDoubleEscapeAction();if(action!=="none"){let now=Date.now();now-this.lastEscapeTime<500?(action==="tree"?this.showTreeSelector():this.showUserMessageSelector(),this.lastEscapeTime=0):this.lastEscapeTime=now}}},this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onAction("app.suspend",()=>this.handleCtrlZ()),this.defaultEditor.onAction("app.thinking.cycle",()=>this.cycleThinkingLevel()),this.defaultEditor.onAction("app.model.cycleForward",()=>this.cycleModel("forward")),this.defaultEditor.onAction("app.model.cycleBackward",()=>this.cycleModel("backward")),this.ui.onDebug=()=>this.handleDebugCommand(),this.defaultEditor.onAction("app.model.select",()=>this.showModelSelector()),this.defaultEditor.onAction("app.tools.expand",()=>this.toggleToolOutputExpansion()),this.defaultEditor.onAction("app.thinking.toggle",()=>this.toggleThinkingBlockVisibility()),this.defaultEditor.onAction("app.editor.external",()=>{this.handleOpenExternalEditor()}),this.defaultEditor.onAction("app.message.copy",()=>{this.handleCopyCommand({flashConfirmation:!0,preferSelection:!0})}),this.defaultEditor.onAction("app.message.followUp",()=>this.handleFollowUp()),this.defaultEditor.onAction("app.message.dequeue",()=>this.handleDequeue()),this.defaultEditor.onAction("app.session.new",()=>this.handleClearCommand()),this.defaultEditor.onAction("app.session.tree",()=>this.showTreeSelector()),this.defaultEditor.onAction("app.session.fork",()=>this.showUserMessageSelector()),this.defaultEditor.onAction("app.session.resume",()=>this.showSessionSelector()),this.defaultEditor.onChange=text2=>{let wasBashMode=this.isBashMode;this.isBashMode=text2.trimStart().startsWith("!"),wasBashMode!==this.isBashMode&&this.updateEditorBorderColor()},this.defaultEditor.onPasteImage=()=>{this.handleClipboardPaste()}}async handleRightClickPaste(){let target=this.renderer.getFocusedComponent(),handleInput=target?.handleInput;if(!(!target||!handleInput))try{let text2=await readClipboardText();if(!text2||this.renderer.getFocusedComponent()!==target)return;handleInput.call(target,`\x1B[200~${text2}\x1B[201~`),this.ui.requestRender()}catch{}}async handleClipboardPaste(){try{let image=await readClipboardImage();if(image){let tmpDir=os7.tmpdir(),ext2=extensionForImageMimeType(image.mimeType)??"png",fileName=`pi-clipboard-${crypto2.randomUUID()}.${ext2}`,filePath=path13.join(tmpDir,fileName);fs8.writeFileSync(filePath,Buffer.from(image.bytes)),this.editor.insertTextAtCursor?.(filePath),this.ui.requestRender();return}let text2=await readClipboardText();text2&&(this.editor.insertTextAtCursor?.(text2),this.ui.requestRender())}catch{}}handleStartupSubmit(text2){this.editor.setText(text2),this.showStatus("Startup is still in progress")}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async text2=>{if(text2=text2.trim(),!!text2&&!this.editorHost.intercept(text2,"steer")){if(text2==="/settings"){this.showSettingsSelector(),this.editor.setText("");return}if(text2==="/scoped-models"){this.editor.setText(""),await this.showModelsSelector();return}if(text2==="/model"||text2.startsWith("/model ")){let searchTerm=text2.startsWith("/model ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleModelCommand(searchTerm);return}if(text2==="/thinking"||text2.startsWith("/thinking ")){let searchTerm=text2.startsWith("/thinking ")?text2.slice(10).trim():void 0;this.editor.setText(""),this.handleThinkingCommand(searchTerm);return}if(text2==="/export"||text2.startsWith("/export ")){await this.handleExportCommand(text2),this.editor.setText("");return}if(text2==="/import"||text2.startsWith("/import ")){await this.handleImportCommand(text2),this.editor.setText("");return}if(text2==="/share"){await this.handleShareCommand(),this.editor.setText("");return}if(text2==="/bug"||text2.startsWith("/bug ")){let hint2=text2.slice(4).trim();this.editor.setText(""),await this.handleBugCommand(hint2||void 0);return}if(text2==="/copy"){await this.handleCopyCommand(),this.editor.setText("");return}if(text2==="/name"||text2.startsWith("/name ")){this.handleNameCommand(text2),this.editor.setText("");return}if(text2==="/session"){this.handleSessionCommand(),this.editor.setText("");return}if(text2==="/changelog"){this.handleChangelogCommand(),this.editor.setText("");return}if(text2==="/hotkeys"){this.handleHotkeysCommand(),this.editor.setText("");return}if(text2==="/fork"){this.showUserMessageSelector(),this.editor.setText("");return}if(text2==="/clone"){this.editor.setText(""),await this.handleCloneCommand();return}if(text2==="/tree"){this.showTreeSelector(),this.editor.setText("");return}if(text2==="/trust"){this.showTrustSelector(),this.editor.setText("");return}if(text2==="/login"||text2.startsWith("/login ")){let providerRef=text2.startsWith("/login ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleLoginCommand(providerRef);return}if(text2==="/logout"){this.showOAuthSelector("logout"),this.editor.setText("");return}if(text2==="/new"){this.editor.setText(""),await this.handleClearCommand();return}if(text2==="/compact"||text2.startsWith("/compact ")){let customInstructions=text2.startsWith("/compact ")?text2.slice(9).trim():void 0;this.editor.setText(""),await this.handleCompactCommand(customInstructions);return}if(text2==="/reload"){this.editor.setText(""),await this.handleReloadCommand();return}if(text2==="/debug"){this.handleDebugCommand(),this.editor.setText("");return}if(text2==="/arminsayshi"){this.handleArminSaysHi(),this.editor.setText("");return}if(text2==="/dementedelves"){this.handleDementedDelves(),this.editor.setText("");return}if(text2==="/resume"){this.showSessionSelector(),this.editor.setText("");return}if(text2==="/quit"){this.editor.setText(""),await this.shutdown();return}if(text2.startsWith("!")){let isExcluded=text2.startsWith("!!"),command=isExcluded?text2.slice(2).trim():text2.slice(1).trim();if(command){if(this.session.isBashRunning){this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(text2);return}this.editor.addToHistory?.(text2),await this.handleBashCommand(command,isExcluded),this.isBashMode=!1,this.updateEditorBorderColor();return}}if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"steer");return}if(this.session.isStreaming){this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(text2):this.pendingUserInputs.push(text2),this.editor.addToHistory?.(text2)}}}subscribeToAgent(){this.unsubscribe=this.session.subscribe(async event=>{await this.handleEvent(event)})}async handleEvent(event){switch(this.isInitialized||await this.init(),this.footer.invalidate(),event.type){case"agent_start":this.pendingTools.clear(),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0);break;case"turn_start":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.workingVisible?this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator():this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":if(this.entriesRenderedByBoundaryCompaction.delete(event.entry.id))break;if(event.entry.type==="custom")this.addCustomEntryToChat(event.entry),this.ui.requestRender();else if(event.entry.type==="usage"&&event.entry.kind==="cache_warm")this.addCacheWarmingUsage(event.entry),this.ui.requestRender();else if(event.entry.type==="custom_message"&&event.entry.display)this.addMessageToChat(createCustomMessage(event.entry.customType,event.entry.content,event.entry.display,event.entry.details,event.entry.timestamp)),this.ui.requestRender();else if(event.entry.type==="compaction"){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.id!==event.entry.id)break;this.chatContainer.clear();let branch=this.sessionManager.getBranch(),compactionIndex=branch.findIndex(entry=>entry.id===event.entry.id),entriesAfterCompaction=new Set(branch.slice(compactionIndex+1).map(entry=>entry.id)),retainedEntries=entries.slice(1);this.renderSessionEntries(retainedEntries.filter(entry=>!entriesAfterCompaction.has(entry.id))),this.addMessageToChat(createCompactionSummaryMessage(event.entry.summary,event.entry.tokensBefore,event.entry.timestamp)),event.entry.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.entry.usage}),this.renderSessionEntries(retainedEntries.filter(entry=>entriesAfterCompaction.has(entry.id)));for(let entryId of entriesAfterCompaction)this.entriesRenderedByBoundaryCompaction.add(entryId);this.footer.invalidate(),this.ui.requestRender()}break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":event.message.role==="custom"?(this.addMessageToChat(event.message),this.ui.requestRender()):event.message.role==="user"?(this.addMessageToChat(event.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):event.message.role==="assistant"&&(this.streamingComponent=new AssistantMessageComponent(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=event.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let content of this.streamingMessage.content)if(content.type==="toolCall")if(this.pendingTools.has(content.id)){let component=this.pendingTools.get(content.id);component&&component.updateArgs(content.arguments)}else{let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(content.id,component)}this.ui.requestRender()}break;case"message_end":if(event.message.role==="user")break;if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message;let errorMessage6;if(this.streamingMessage.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage6=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=errorMessage6}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){errorMessage6||(errorMessage6=this.streamingMessage.errorMessage||"Error");for(let[,component]of this.pendingTools.entries())component.updateResult({content:[{type:"text",text:errorMessage6}],isError:!0});this.pendingTools.clear(),this.maybeSuggestBugReport(this.streamingMessage)}else{for(let[,component]of this.pendingTools.entries())component.setArgsComplete();this.maybeShowThinkingDropNotice(this.streamingMessage),this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{let component=this.pendingTools.get(event.toolCallId);component||(component=new ToolExecutionComponent(event.toolName,event.toolCallId,event.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(event.toolName),this.ui,this.sessionManager.getCwd()),component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError}),this.pendingTools.delete(event.toolCallId),this.ui.requestRender());break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortCompaction()},this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else event.errorMessage&&(event.reason==="manual"?this.showError(event.errorMessage):(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",event.errorMessage),1,0))));this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{this.clearStatusIndicator("retry"),event.source==="branchSummary"?this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)):this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason)),this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c=>c.type==="text")).map(c=>c.text).join("")}showManagedToolStatus(status){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status.type==="warning"?`Warning: ${status.message}`:status.message,color2=status.type==="warning"?"warning":"dim";this.chatContainer.addChild(new Text(theme.fg(color2,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusText.setText(theme.fg("dim",message)),this.ui.requestRender();return}let spacer=new Spacer(1),text2=new Text(theme.fg("dim",message),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text2),this.lastStatusSpacer=spacer,this.lastStatusText=text2,this.ui.requestRender()}addCustomEntryToChat(entry){let renderer=this.session.extensionRunner.getEntryRenderer(entry.customType);if(!renderer)return;let component=new CustomEntryComponent(entry,renderer);if(component.setExpanded(this.toolOutputExpanded),!!component.hasContent()){if(this.streamingComponent){let streamingIndex=this.chatContainer.children.indexOf(this.streamingComponent);if(streamingIndex>=0){this.chatContainer.children.splice(streamingIndex,0,component);return}}this.chatContainer.addChild(component)}}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let renderer=this.session.extensionRunner.getMessageRenderer(message.customType),component=new CustomMessageComponent(message,renderer,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"system":break;case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.sessionManager.getEntries(),this.session.modelRuntime):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item)){this.addCustomEntryToChat(item);continue}if(isUsageSessionEntry(item)){this.addCacheWarmingUsage(item);continue}if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage6;if(message.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage6=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage6=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage6}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){let items=entries.flatMap(entry=>{if(entry.type==="custom"||entry.type==="usage"&&entry.kind==="cache_warm")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCacheWarmingUsage(entry){this.settingsManager.getShowCacheMissNotices()&&(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",formatCacheWarmingUsage(entry)),1,0)))}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens2=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`${label}: ${formatTokens(tokens2)} tokens billed${cost}`),1,0))}static countDroppedThinkingBlocks(message){let count=0;for(let diagnostic of message.diagnostics??[]){if(diagnostic.type!=="anthropic_input_transformations")continue;let transformations=diagnostic.details?.transformations;Array.isArray(transformations)&&(count+=transformations.filter(transformation=>typeof transformation=="object"&&transformation!==null&&transformation.type==="thinking_dropped").length)}return count}maybeShowThinkingDropNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let droppedCount=_InteractiveMode.countDroppedThinkingBlocks(message);if(droppedCount===0)return;let previousDroppedCount=0,branch=this.sessionManager.getBranch();for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="message"&&entry.message.role==="assistant"){previousDroppedCount=_InteractiveMode.countDroppedThinkingBlocks(entry.message);break}}if(droppedCount<=previousDroppedCount)return;let noun=droppedCount===1?"thinking block":"thinking blocks";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Anthropic dropped ${droppedCount} ${noun} (details in session)`),1,0))}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.sessionManager.getEntries(),message,this.session.modelRuntime);miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`);let text2=theme.fg("warning",`${label}: ${reBilled}`);this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(text2,1,0))}renderInitialMessages(){let entries=this.sessionManager.buildContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0}),this.renderProjectTrustWarningIfNeeded();let compactionCount=this.sessionManager.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}renderProjectTrustWarningIfNeeded(){this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(this.sessionManager.getCwd())||(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`),1,0)))}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve17=>{this.onInputCallback=text2=>{this.onInputCallback=void 0,resolve17(text2)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.sessionManager.buildContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,this.session.background.close(),options?.fromSignal&&(await this.runtimeHost.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeHost.dispose();let resumeCommand=formatResumeCommand(this.sessionManager);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1381
1381
|
`),process.exit(0)}emergencyTerminalExit(){this.isShuttingDown=!0,this.unregisterSignalHandlers(),killTrackedDetachedChildren(),process.exit(129)}uncaughtCrash(error){this.isShuttingDown&&process.exit(1),this.isShuttingDown=!0;try{this.unregisterSignalHandlers()}catch{}try{killTrackedDetachedChildren()}catch{}try{this.ui.stop()}catch{}console.error(`${APP_NAME} exiting due to uncaughtException:`),console.error(error);let extensionHint=this.getCrashExtensionHint(error);extensionHint&&console.error(`
|
|
1382
1382
|
${extensionHint}`),this.recordCrash("uncaught_exception",error)&&console.error(`
|
|
1383
1383
|
${this.crashReportInstructions()}`),process.exit(1)}async checkShutdownRequested(){this.shutdownRequested&&await this.shutdown()}registerSignalHandlers(){this.unregisterSignalHandlers();let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),this.shutdown({fromSignal:!0})};process.prependListener(signal,handler),this.signalCleanupHandlers.push(()=>process.off(signal,handler))}let terminalErrorHandler=error=>{throw isDeadTerminalError(error)&&this.emergencyTerminalExit(),error};process.stdout.on("error",terminalErrorHandler),process.stderr.on("error",terminalErrorHandler),this.signalCleanupHandlers.push(()=>process.stdout.off("error",terminalErrorHandler)),this.signalCleanupHandlers.push(()=>process.stderr.off("error",terminalErrorHandler));let uncaughtExceptionHandler=error=>this.uncaughtCrash(error);process.prependListener("uncaughtException",uncaughtExceptionHandler),this.signalCleanupHandlers.push(()=>process.off("uncaughtException",uncaughtExceptionHandler))}unregisterSignalHandlers(){for(let cleanup of this.signalCleanupHandlers)cleanup();this.signalCleanupHandlers=[]}handleCtrlZ(){if(process.platform==="win32"){this.showStatus("Suspend to background is not supported on Windows");return}let suspendKeepAlive=setInterval(()=>{},2**30),ignoreSigint=()=>{};process.on("SIGINT",ignoreSigint),process.once("SIGCONT",()=>{clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),this.ui.start(),this.ui.requestRender(!0)});try{this.ui.stop(),process.kill(0,"SIGTSTP")}catch(error){throw clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),error}}async handleFollowUp(){let text2=(this.editor.getExpandedText?.()??this.editor.getText()).trim();if(text2&&!this.editorHost.intercept(text2,"followUp")){if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"followUp");return}this.session.isStreaming?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"followUp"}),this.updatePendingMessagesDisplay(),this.ui.requestRender()):this.editor.onSubmit&&(this.editor.setText(""),this.editor.onSubmit(text2))}}handleDequeue(){let restored=this.restoreQueuedMessagesToEditor();restored===0?this.showStatus("No queued messages to restore"):this.showStatus(`Restored ${restored} queued message${restored>1?"s":""} to editor`)}updateEditorBorderColor(){if(this.isBashMode)this.editor.borderColor=theme.getBashModeBorderColor();else{let level=this.session.thinkingLevel||"off";this.editor.borderColor=theme.getThinkingBorderColor(level)}this.activeStatusIndicator?.invalidate(),this.ui.requestRender()}cycleThinkingLevel(){let newLevel=this.session.cycleThinkingLevel();newLevel===void 0?this.showStatus("Current model does not support thinking"):(this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Thinking level: ${newLevel}`))}async cycleModel(direction){try{let result2=await this.session.cycleModel(direction);if(result2===void 0){let msg=this.session.scopedModels.length>0?"Only one model in scope":"Only one model available";this.showStatus(msg)}else{this.footer.invalidate(),this.updateEditorBorderColor();let thinkingStr=result2.model.reasoning&&result2.thinkingLevel!=="off"?` (thinking: ${result2.thinkingLevel})`:"";this.showStatus(`Switched to ${result2.model.name||result2.model.id}${thinkingStr}`),this.maybeWarnAboutAnthropicSubscriptionAuth(result2.model)}}catch(error){this.showError(error instanceof Error?error.message:String(error))}}toggleToolOutputExpansion(){this.setToolsExpanded(!this.toolOutputExpanded)}setToolsExpanded(expanded){if(expanded===this.toolOutputExpanded)return;this.toolOutputExpanded=expanded;let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(expanded);for(let container of[this.loadedResourcesContainer,this.chatContainer])for(let child of container.children)isExpandable(child)&&child.setExpanded(expanded);this.showStatus(`Tool output: ${expanded?"expanded":"collapsed"}`)}updateThinkingBlockVisibility(){for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHideThinkingBlock(this.hideThinkingBlock);this.ui.requestRender()}toggleThinkingBlockVisibility(){this.hideThinkingBlock=!this.hideThinkingBlock,this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock),this.updateThinkingBlockVisibility(),this.showStatus(`Thinking blocks: ${this.hideThinkingBlock?"hidden":"visible"}`)}async handleOpenExternalEditor(){let editorCmd=this.settingsManager.getExternalEditorCommand(),content=this.editor.getExpandedText?.()??this.editor.getText();this.ui.stop();try{let result2=await editInExternalEditor({command:editorCmd,content});result2.status==="complete"&&this.editor.setText(result2.content)}finally{this.ui.start(),this.ui.requestRender(!0)}}clearEditor(){this.editor.setText(""),this.ui.requestRender()}showError(errorMessage6){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("error",`Error: ${errorMessage6}`),this.outputPad,0)),this.ui.requestRender()}showWarning(warningMessage){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("warning",`Warning: ${warningMessage}`),1,0)),this.ui.requestRender()}showNewVersionNotification(release2){let action=theme.fg("accent",`${APP_NAME} update`),updateInstruction=theme.fg("muted",`New version ${release2.version} is available. Run `)+action,changelogUrl="https://pi.dev/changelog",changelogLink=getCapabilities().hyperlinks?hyperlink(theme.fg("accent",changelogUrl),changelogUrl):theme.fg("accent",changelogUrl),changelogLine=UPDATE_CHANGELOG_HINT?theme.fg("muted",UPDATE_CHANGELOG_HINT):theme.fg("muted","Changelog: ")+changelogLink,note=release2.note?.trim();this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder(text2=>theme.fg("warning",text2))),this.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning","Update Available"))}
|
|
@@ -1389,7 +1389,7 @@ ${packageLines}`,1,0)),this.chatContainer.addChild(new DynamicBorder(text2=>them
|
|
|
1389
1389
|
|
|
1390
1390
|
`),currentText=options?.currentText??this.editor.getText(),combinedText=[queuedText,currentText].filter(t=>t.trim()).join(`
|
|
1391
1391
|
|
|
1392
|
-
`);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.session.abort(),allQueued.length}queueCompactionMessage(text2,mode){this.compactionQueuedMessages.push({text:text2,mode}),this.editor.addToHistory?.(text2),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text2){if(!text2.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);return!!extensionRunner.getCommand(commandName)}async flushCompactionQueue(options){if(this.compactionQueuedMessages.length===0)return;let queuedMessages=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let restoreQueue=error=>{this.session.clearQueue(),this.compactionQueuedMessages=queuedMessages,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${queuedMessages.length>1?"s":""}: ${error instanceof Error?error.message:String(error)}`)};try{if(options?.willRetry){for(let message of queuedMessages)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay();return}let firstPromptIndex=queuedMessages.findIndex(message=>!this.isExtensionCommand(message.text));if(firstPromptIndex===-1){for(let message of queuedMessages)await this.session.prompt(message.text);return}let preCommands=queuedMessages.slice(0,firstPromptIndex),firstPrompt=queuedMessages[firstPromptIndex],rest=queuedMessages.slice(firstPromptIndex+1);for(let message of preCommands)await this.session.prompt(message.text);let promptPromise=this.session.prompt(firstPrompt.text,{streamingBehavior:firstPrompt.mode}).catch(error=>{restoreQueue(error)});for(let message of rest)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay()}catch(error){restoreQueue(error)}}flushPendingBashComponents(){for(let component of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(component),this.chatContainer.addChild(component);this.pendingBashComponents=[]}disposeActiveSelector(){let dispose=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,dispose?.()}showSelector(create){let token={},dispose,created=create(()=>{dispose?.(),this.activeSelectorToken===token&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))}),release2=created.dispose,released=!1;dispose=()=>{released||(released=!0,release2?.())},this.disposeActiveSelector(),this.activeSelectorToken=token,this.activeSelectorDispose=dispose,this.editorContainer.clear(),this.editorContainer.addChild(created.component),this.ui.setFocus(created.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(done=>{let selector,defaultProvider=this.settingsManager.getDefaultProvider(),defaultModelId=this.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:"not set";return selector=new SettingsSelectorComponent({autoCompact:this.session.autoCompactionEnabled,defaultModel,currentModel:this.session.model,availableDefaultModels:this.session.modelRuntime.getAvailableSnapshot(),showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),cacheWarmingMode:this.settingsManager.getCacheWarmingMode(),thinkingLevel:this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:this.settingsManager.getAllModelThinkingLevels(),currentTheme:this.themeController.getThemeSelection()||"dark",terminalTheme:this.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:enabled=>{this.session.setAutoCompactionEnabled(enabled),this.footer.setAutoCompactEnabled(enabled)},onShowImagesChange:enabled=>{this.settingsManager.setShowImages(enabled);for(let child of this.chatContainer.children)isToolChatComponent(child)&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{this.settingsManager.setImageWidthCells(width);for(let child of this.chatContainer.children)isToolChatComponent(child)&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{this.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{this.settingsManager.setBlockImages(blocked)},onEnableSkillCommandsChange:enabled=>{this.settingsManager.setEnableSkillCommands(enabled),this.setupAutocompleteProvider()},onSteeringModeChange:mode=>{this.session.setSteeringMode(mode)},onFollowUpModeChange:mode=>{this.session.setFollowUpMode(mode)},onTransportChange:transport=>{this.settingsManager.setTransport(transport),this.session.agent.transport=transport},onHttpIdleTimeoutMsChange:timeoutMs=>{this.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`)},onCacheWarmingModeChange:mode=>{this.session.setCacheWarmingMode(mode),this.showStatus(`Cache warming: ${mode}`)},onModelThinkingLevelChange:(provider,modelId2,level)=>{this.settingsManager.setModelThinkingLevel(provider,modelId2,level);let current=this.session.model;current&¤t.provider===provider&¤t.id===modelId2&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId2)=>{this.settingsManager.removeModelThinkingLevel(provider,modelId2);let current=this.session.model;if(current&¤t.provider===provider&¤t.id===modelId2){let globalDefault=this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;this.session.setThinkingLevel(globalDefault),this.footer.invalidate(),this.updateEditorBorderColor()}},onThemeChange:themeSetting=>{this.settingsManager.setTheme(themeSetting),this.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>this.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{this.hideThinkingBlock=hidden,this.settingsManager.setHideThinkingBlock(hidden),this.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{this.settingsManager.setMermaidRenderingMode(mode),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{this.settingsManager.setShowCacheMissNotices(shown),this.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{this.settingsManager.setCollapseChangelog(collapsed)},onEnableInstallTelemetryChange:enabled=>{this.settingsManager.setEnableInstallTelemetry(enabled)},onQuietStartupChange:enabled=>{this.settingsManager.setQuietStartup(enabled)},onDefaultProjectTrustChange:defaultProjectTrust=>{this.settingsManager.setDefaultProjectTrust(defaultProjectTrust)},onDoubleEscapeActionChange:action=>{this.settingsManager.setDoubleEscapeAction(action)},onTreeFilterModeChange:mode=>{this.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{this.settingsManager.setShowHardwareCursor(enabled),this.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{this.settingsManager.setEditorPaddingX(padding),this.defaultEditor.setPaddingX(padding),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(padding)},onOutputPadChange:padding=>{if(this.settingsManager.setOutputPad(padding),this.outputPad=padding,this.streamingComponent||this.session.isStreaming){for(let child of this.chatContainer.children)(child instanceof AssistantMessageComponent||child instanceof CustomMessageComponent||child instanceof UserMessageComponent)&&child.setOutputPad(padding);this.streamingComponent&&this.streamingComponent.setOutputPad(padding),this.ui.requestRender();return}this.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:maxVisible=>{this.settingsManager.setAutocompleteMaxVisible(maxVisible),this.defaultEditor.setAutocompleteMaxVisible(maxVisible),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{this.settingsManager.setClearOnShrink(enabled),this.ui.setClearOnShrink(enabled),!enabled&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{this.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!this.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(mode),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${mode}`)},onFullscreenExitOutputChange:output=>{this.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{this.settingsManager.setFullscreenScrollbar(mode),this.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{this.settingsManager.setFullscreenCopyOnSelect(enabled),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(enabled)},onWarningsChange:warnings=>{this.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),this.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}handleThinkingCommand(searchTerm){let availableLevels=this.session.getAvailableThinkingLevels();if(!searchTerm){this.showThinkingSelector();return}let normalized=searchTerm.trim().toLowerCase(),level=availableLevels.find(candidate=>candidate.toLowerCase()===normalized);if(!level){this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);return}this.selectThinkingLevel(level,!1)}selectThinkingLevel(level,persist){try{this.session.setThinkingLevel(level,{persist}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(persist?`Default thinking level: ${level}`:`Thinking level: ${level}`)}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showThinkingSelector(){this.showSelector(done=>{let selectLevel=(level,persist)=>{this.selectThinkingLevel(level,persist),done()},selector=new ThinkingSelectorComponent(this.session.thinkingLevel??DEFAULT_THINKING_LEVEL,this.session.getAvailableThinkingLevels(),level=>selectLevel(level,!1),()=>{done(),this.ui.requestRender()},level=>selectLevel(level,!0),this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL);return{component:selector,focus:selector}})}async handleModelCommand(searchTerm){if(!searchTerm){this.showModelSelector();return}let model=await this.findExactModelMatch(searchTerm);if(model){try{await this.session.setModel(model,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model),this.checkDaxnutsEasterEgg(model)}catch(error){this.showError(error instanceof Error?error.message:String(error))}return}this.showModelSelector(searchTerm)}async findExactModelMatch(searchTerm){let cachedModels=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):[...this.session.modelRuntime.getAvailableSnapshot()],cachedMatch=findExactModelReferenceMatch(searchTerm,cachedModels);if(cachedMatch||this.session.scopedModels.length>0)return cachedMatch;this.showStatus("Refreshing model catalogs\u2026");let controller=new AbortController,timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3);try{let result2=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result2.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result2.errors.size>0&&this.showWarning(`Could not refresh ${[...result2.errors.keys()].join(", ")}; searching cached models.`)}catch(error){this.showWarning(timedOut?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`)}finally{clearTimeout(timeout)}return findExactModelReferenceMatch(searchTerm,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let models=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):this.session.modelRuntime.getAvailableSnapshot(),uniqueProviders=new Set(models.map(model=>model.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model||model.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);return}let apiKey=(await this.session.modelRuntime.getAuth(model.provider))?.auth.apiKey;if(!isAnthropicSubscriptionAuthKey(apiKey))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let cwd=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==cwd||!this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(cwd))return!1;let trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir);try{return trustStore.get(cwd)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(trustStore.set(cwd,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(error){return this.showWarning(`Could not save project trust after reload: ${error instanceof Error?error.message:String(error)}`),!1}}showTrustSelector(){let cwd=this.sessionManager.getCwd(),trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir),savedDecision=trustStore.getEntry(cwd);this.showSelector(done=>{let selector=new TrustSelectorComponent({cwd,savedDecision,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:selection=>{trustStore.setMany(selection.updates),done(),this.showStatus(`Saved trust decision: ${selection.trusted?"trusted":"untrusted"}. Restart ${APP_NAME} for this to take effect.`)},onCancel:()=>{done(),this.ui.requestRender()}});return{component:selector,focus:selector}})}showModelSelector(initialSearchInput){this.showSelector(done=>{let selectModel=async(model,persist)=>{try{await this.session.setModel(model,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model.provider}/${model.id}`:`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model),this.checkDaxnutsEasterEgg(model)}catch(error){done(),this.showError(error instanceof Error?error.message:String(error))}},defaultProvider=this.settingsManager.getDefaultProvider(),defaultModel=this.settingsManager.getDefaultModel(),selector=new ModelSelectorComponent(this.ui,this.session.model,this.session.modelRuntime,this.session.scopedModels,model=>selectModel(model,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model=>selectModel(model,!0),defaultProvider&&defaultModel?{provider:defaultProvider,id:defaultModel}:void 0);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showModelsSelector(){let availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),configuredPatterns=this.settingsManager.getEnabledModels(),sessionScopedModels=this.session.scopedModels,configuredEnabledIds=models=>{if(!configuredPatterns?.length)return null;let resolved=resolveModelScopeFromModels(configuredPatterns,models),ids=resolved.scopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`);for(let diagnostic of resolved.diagnostics)diagnostic.code==="no-match"&&!ids.includes(diagnostic.pattern)&&ids.push(diagnostic.pattern);return ids},currentEnabledIds=sessionScopedModels.length>0?sessionScopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`):configuredEnabledIds(availableModels),selectionChanged=!1,updateSessionModels=enabledIds=>{currentEnabledIds=enabledIds===null?null:[...enabledIds];let hasEnabledAvailableModel=enabledIds?.some(id=>availableModelIds.has(id))??!1,allAvailableModelsEnabled=enabledIds!==null&&[...availableModelIds].every(id=>enabledIds.includes(id));if(enabledIds&&hasEnabledAvailableModel&&!allAvailableModelsEnabled){let newScopedModels=resolveModelScopeFromModels(enabledIds,availableModels).scopedModels;this.session.setScopedModels(newScopedModels.map(scoped=>({model:scoped.model,thinkingLevel:scoped.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(done=>{let disposed=!1,timedOut=!1,controller=new AbortController,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3),selector=new ScopedModelsSelectorComponent({allModels:availableModels,enabledModelIds:currentEnabledIds,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:enabledIds=>{selectionChanged=!0,updateSessionModels(enabledIds)},onPersist:enabledIds=>{let allEnabled=enabledIds!==null&&enabledIds.length===availableModels.length&&enabledIds.every(id=>availableModelIds.has(id)),newPatterns=enabledIds===null||allEnabled?void 0:enabledIds;this.settingsManager.setEnabledModels(newPatterns?[...newPatterns]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{done(),this.ui.requestRender()}});return refreshModelCatalogs(this.session.modelRuntime,controller.signal).then(result2=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result2.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result2.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result2.errors.keys()].join(", ")}; showing cached models.`,"warning"):selector.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(error=>{disposed||(selector.setRefreshStatus(timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(timeout)),{component:selector,focus:selector,dispose:()=>{disposed=!0,clearTimeout(timeout),controller.abort()}}})}showUserMessageSelector(){let userMessages=this.session.getUserMessagesForForking();if(userMessages.length===0){this.showStatus("No messages to fork from");return}let initialSelectedId=userMessages[userMessages.length-1]?.entryId;this.showSelector(done=>{let selector=new UserMessageSelectorComponent(userMessages.map(m2=>({id:m2.entryId,text:m2.text})),async entryId=>{done();try{let result2=await this.runtimeHost.fork(entryId);if(result2.cancelled){this.ui.requestRender();return}this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},()=>{done(),this.ui.requestRender()},initialSelectedId);return{component:selector,focus:selector.getMessageList()}})}async handleCloneCommand(){let leafId=this.sessionManager.getLeafId();if(!leafId){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(leafId,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showTreeSelector(initialSelectedId){let tree=this.sessionManager.getTree(),realLeafId=this.sessionManager.getLeafId(),initialFilterMode=this.settingsManager.getTreeFilterMode();if(tree.length===0){this.showStatus("No entries in session");return}this.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,this.ui.terminal.rows,async entryId=>{if(entryId===this.sessionManager.getLeafId()){done(),this.showStatus("Already at this point");return}done();let wantsSummary=!1,customInstructions;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(summaryChoice===void 0){this.showTreeSelector(entryId);return}if(wantsSummary=summaryChoice!=="No summary",!(summaryChoice==="Summarize with custom prompt"&&(customInstructions=await this.showExtensionEditor("Custom summarization instructions"),customInstructions===void 0)))break}if(this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort()),this.session.isCompacting){this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");return}let showingSummaryIndicator=!1,originalOnEscape=this.defaultEditor.onEscape;wantsSummary&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new Spacer(1)),this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)),showingSummaryIndicator=!0,this.ui.requestRender());try{let result2=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result2.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result2.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(error){this.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=originalOnEscape}},()=>{done(),this.ui.requestRender()},(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label),this.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text2=>{if(!text2){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text2),this.showStatus("Copied selected message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}showSessionSelector(){this.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress,signal),(onProgress,signal)=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress,signal):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress,signal),async sessionPath=>{done(),await this.handleResumeSession(sessionPath)},()=>{done(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:selector,focus:selector}})}async handleResumeSession(sessionPath,options){this.clearStatusIndicator();try{let result2=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session"),result2}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result2=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session in current cwd"),result2}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0;(!authType||authType==="oauth")&&provider.auth.oauth&&options.push({id:provider.id,name:provider.name,authType:"oauth",method:provider.auth.oauth,status}),(!authType||authType==="api_key")&&provider.auth.apiKey&&options.push({id:provider.id,name:provider.name,authType:"api_key",method:provider.auth.apiKey,status})}return options.sort((a,b2)=>a.name.localeCompare(b2.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId,type})=>({id:providerId,name:this.session.modelRuntime.getProvider(providerId)?.name??providerId,authType:type,status:{type,source:"stored credential"}})).sort((a,b2)=>a.name.localeCompare(b2.name))}findLoginProviderOptions(providerRef){let normalizedProviderRef=providerRef.trim().toLowerCase();return normalizedProviderRef?this.getLoginProviderOptions().filter(provider=>provider.id.toLowerCase()===normalizedProviderRef||provider.name.toLowerCase()===normalizedProviderRef):[]}async handleLoginCommand(providerRef){if(!providerRef){this.showLoginAuthTypeSelector();return}let providerOptions=this.findLoginProviderOptions(providerRef);if(providerOptions.length===1){await this.startProviderLogin(providerOptions[0]);return}if(providerOptions.length>1&&new Set(providerOptions.map(provider=>provider.id)).size===1){this.showLoginAuthTypeSelector(providerOptions);return}this.showLoginProviderSelector(void 0,providerRef)}async startProviderLogin(providerOption){providerOption.authType==="oauth"?await this.showLoginDialog(providerOption.id,providerOption.name):providerOption.method?.login?await this.showApiKeyLoginDialog(providerOption.id,providerOption.name):this.showAmbientAuthDialog(providerOption)}showLoginAuthTypeSelector(providerOptions){let oauthProvider=providerOptions?.find(provider=>provider.authType==="oauth"),subscriptionLabel=(oauthProvider?.method&&"loginLabel"in oauthProvider.method?oauthProvider.method.loginLabel:void 0)??"Sign in with an account",apiKeyLabel="Sign in with an API key",availableAuthTypes=providerOptions?new Set(providerOptions.map(provider=>provider.authType)):new Set(["oauth","api_key"]),options=[];if(availableAuthTypes.has("oauth")&&options.push(subscriptionLabel),availableAuthTypes.has("api_key")&&options.push(apiKeyLabel),options.length===0){this.showStatus("No login methods available.");return}if(providerOptions&&options.length===1){let providerOption=providerOptions[0];providerOption&&this.startProviderLogin(providerOption);return}let title=providerOptions?.[0]?`Select authentication method for ${providerOptions[0].name}:`:"Select authentication method:";this.showSelector(done=>{let selector=new ExtensionSelectorComponent(title,options,option=>{done();let authType=option===subscriptionLabel?"oauth":"api_key";if(providerOptions){let providerOption=providerOptions.find(provider=>provider.authType===authType);providerOption&&this.startProviderLogin(providerOption);return}this.showLoginProviderSelector(authType)},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}showLoginProviderSelector(authType,initialSearchInput){let providerOptions=this.getLoginProviderOptions(authType);if(providerOptions.length===0){let message=authType==="oauth"?"No subscription providers available.":authType==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(message);return}this.showSelector(done=>{let selector=new OAuthSelectorComponent("login",providerOptions,async(providerId,selectedAuthType)=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId&&provider.authType===selectedAuthType);providerOption&&await this.startProviderLogin(providerOption)},()=>{done(),authType?this.showLoginAuthTypeSelector():this.ui.requestRender()},initialSearchInput);return{component:selector,focus:selector}})}async showOAuthSelector(mode){if(mode==="login"){this.showLoginAuthTypeSelector();return}let providerOptions;try{providerOptions=await this.getLogoutProviderOptions()}catch(error){this.showError(`Could not read stored credentials: ${error instanceof Error?error.message:String(error)}`);return}if(providerOptions.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(done=>{let selector=new OAuthSelectorComponent(mode,providerOptions,async providerId=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId);if(providerOption)try{await this.session.modelRuntime.logout(providerOption.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let message=providerOption.authType==="oauth"?`Logged out of ${providerOption.name}`:`Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;this.showStatus(message)}catch(error){let message=error instanceof Error?error.message:String(error);this.showError(error instanceof CredentialSynchronizationError?`Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`:`Logout failed: ${message}`)}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async completeProviderAuthentication(providerId,providerName,authType,previousModel){let actionLabel=authType==="oauth"?`Logged in to ${providerName}`:`Saved API key for ${providerName}`,session=this.session,deferSelection=isUnknownModel(previousModel)&&hasDefaultModelProvider(providerId)&&!session.modelRuntime.getAvailableSnapshot().some(model=>model.provider===providerId&&model.id===defaultModelPerProvider[providerId]),finishAuthentication=async()=>{let selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model=>model.provider===providerId);if(providerId==="llama.cpp")selectionError=llamaCppPostLoginGuidance(actionLabel,providerModels.length);else if(!hasDefaultModelProvider(providerId))selectionError=`${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;else if(providerModels.length===0)selectionError=`${actionLabel}, but no models are available for that provider. Use /model to select a model.`;else{let defaultModelId=defaultModelPerProvider[providerId];if(selectedModel=providerModels.find(model=>model.id===defaultModelId)??(providerId==="radius"?providerModels[0]:void 0),!selectedModel)selectionError=`${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;else try{await this.session.setModel(selectedModel,{persist:!0})}catch(error){selectedModel=void 0;let errorMessage6=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage6}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),selectedModel?(this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel),this.checkDaxnutsEasterEgg(selectedModel)):(this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`),selectionError?this.showError(selectionError):this.maybeWarnAboutAnthropicSubscriptionAuth())};deferSelection?this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog\u2026`):await finishAuthentication();let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(async result2=>{result2.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result2.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),deferSelection&&this.session===session&&session.model===previousModel&&await finishAuthentication(),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(error=>{this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error?error.message:String(error)}`)}).finally(()=>clearTimeout(timeout))}showAmbientAuthDialog(providerOption){let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>restoreEditor3(),providerOption.name,`${providerOption.name} setup`);dialog.showInfo(`${providerOption.method?.name??"Authentication"} is configured outside ${APP_NAME}.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()}async showApiKeyLoginDialog(providerId,providerName){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);providerId==="amazon-bedrock"&&dialog.showDetails([theme.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),theme.fg("muted","See:"),theme.fg("accent",` ${path13.join(getDocsPath(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"api_key"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg!=="Login cancelled"&&this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`)}}showAuthSelect(dialog,prompt){return new Promise((resolve17,reject)=>{let restoreDialog=()=>{this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()},labels=prompt.options.map(option=>option.label),selector=new ExtensionSelectorComponent(prompt.message,labels,optionLabel=>{restoreDialog();let id=prompt.options.find(option=>option.label===optionLabel)?.id;id?resolve17(id):reject(new Error("Login cancelled"))},()=>{restoreDialog(),reject(new Error("Login cancelled"))});this.editorContainer.clear(),this.editorContainer.addChild(selector),this.ui.setFocus(selector),this.ui.requestRender()})}async showAuthPrompt(dialog,prompt){let response;if(prompt.type==="select"?response=this.showAuthSelect(dialog,prompt):prompt.type==="manual_code"?response=dialog.showManualInput(prompt.message):response=dialog.showPrompt(prompt.message,prompt.placeholder),!prompt.signal)return response;if(prompt.signal.aborted)throw new Error("Login cancelled");let signal=prompt.signal,onAbort,aborted=new Promise((_resolve,reject)=>{onAbort=()=>reject(new Error("Login cancelled")),signal.addEventListener("abort",onAbort,{once:!0})});try{return await Promise.race([response,aborted])}finally{onAbort&&signal.removeEventListener("abort",onAbort)}}notifyAuthDialog(dialog,event){event.type==="auth_url"?dialog.showAuth(event.url,event.instructions):event.type==="device_code"?(dialog.showDeviceCode(event),dialog.showWaiting("Waiting for authentication...")):event.type==="info"?dialog.showInfo(event.message,event.links):dialog.showProgress(event.message)}async loginProvider(dialog,providerId,method){await this.session.modelRuntime.login(providerId,method,{signal:dialog.signal,prompt:prompt=>this.showAuthPrompt(dialog,prompt),notify:event=>this.notifyAuthDialog(dialog,event)})}async showLoginDialog(providerId,providerName){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"oauth"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg!=="Login cancelled"&&this.showError(`Failed to login to ${providerName}: ${errorMsg}`)}}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let reloadBox=new Container,borderColor=s=>theme.fg("border",s);reloadBox.addChild(new DynamicBorder(borderColor)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new Text(theme.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new DynamicBorder(borderColor));let previousEditor=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(reloadBox),this.ui.setFocus(reloadBox),this.ui.requestRender(!0),await new Promise(resolve17=>process.nextTick(resolve17));let dismissReloadBox=editor=>{this.editorContainer.clear(),this.editorContainer.addChild(editor),this.ui.setFocus(editor),this.ui.requestRender()},chatRestoredBeforeSessionStart=!1,reloadBoxDismissed=!1,restoreChatBeforeSessionStart=()=>{chatRestoredBeforeSessionStart||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),chatRestoredBeforeSessionStart=!0)};try{await this.session.reload({beforeSessionStart:restoreChatBeforeSessionStart}),restoreChatBeforeSessionStart(),this.keybindings.reload();let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(this.toolOutputExpanded),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.applyRuntimeSettings(),await this.themeController.applyFromSettings(),this.setupAutocompleteProvider();let runner=this.session.extensionRunner;this.setupExtensionShortcuts(runner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let savedImplicitProjectTrust=this.maybeSaveImplicitProjectTrustAfterReload(),modelsJsonError=this.session.modelRuntime.getError();modelsJsonError&&this.showError(`models.json error: ${modelsJsonError}`),this.showStatus(savedImplicitProjectTrust?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),dismissReloadBox(this.editor),reloadBoxDismissed=!0}catch(error){reloadBoxDismissed||dismissReloadBox(previousEditor),this.showError(`Reload failed: ${error instanceof Error?error.message:String(error)}`)}}async handleExportCommand(text2){let outputPath=this.getPathCommandArgument(text2,"/export");try{if(outputPath?.endsWith(".jsonl")){let filePath=this.session.exportToJsonl(outputPath);this.showStatus(`Session exported to: ${filePath}`)}else{let filePath=await this.session.exportToHtml(outputPath,{themeName:theme.name});this.showStatus(`Session exported to: ${filePath}`)}}catch(error){this.showError(`Failed to export session: ${error instanceof Error?error.message:"Unknown error"}`)}}getPathCommandArgument(text2,command){if(text2===command||!text2.startsWith(`${command} `))return;let argsString=text2.slice(command.length+1).trimStart();if(!argsString)return;let firstChar=argsString[0];if(firstChar==='"'||firstChar==="'"){let closingQuoteIndex=argsString.indexOf(firstChar,1);return closingQuoteIndex<0?void 0:argsString.slice(1,closingQuoteIndex)}let firstWhitespaceIndex=argsString.search(/\s/);return firstWhitespaceIndex<0?argsString:argsString.slice(0,firstWhitespaceIndex)}async handleImportCommand(text2){let inputPath=this.getPathCommandArgument(text2,"/import");if(!inputPath){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${inputPath}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(inputPath)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`)}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(inputPath,selectedCwd)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`);return}if(error instanceof SessionImportFileNotFoundError){this.showError(`Failed to import session: ${error.message}`);return}await this.handleFatalRuntimeError("Failed to import session",error)}}async handleShareCommand(){await shareSession({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)})}async handleBugCommand(hint2){await reportBug({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,keybindings:this.keybindings,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)},hint2)}async handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text2=this.session.getLastAssistantText();if(!text2){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text2),options.flashConfirmation&&this.ui instanceof TuiAltScreen?this.ui.flash("Copied!"):this.showStatus("Copied last agent message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}handleNameCommand(text2){let name=text2.replace(/^\/name\s*/,"").trim();if(!name){let currentName=this.sessionManager.getSessionName();currentName?(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name: ${currentName}`),1,0))):this.showWarning("Usage: /name <name>"),this.ui.requestRender();return}this.session.setSessionName(name);let sessionName2=this.sessionManager.getSessionName();sessionName2!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName2)}`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name set: ${sessionName2??name}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName2=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),info=`${theme.bold("Session Info")}
|
|
1392
|
+
`);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.session.abort(),allQueued.length}queueCompactionMessage(text2,mode){this.compactionQueuedMessages.push({text:text2,mode}),this.editor.addToHistory?.(text2),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text2){if(!text2.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);return!!extensionRunner.getCommand(commandName)}async flushCompactionQueue(options){if(this.compactionQueuedMessages.length===0)return;let queuedMessages=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let restoreQueue=error=>{this.session.clearQueue(),this.compactionQueuedMessages=queuedMessages,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${queuedMessages.length>1?"s":""}: ${error instanceof Error?error.message:String(error)}`)};try{if(options?.willRetry){for(let message of queuedMessages)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay();return}let firstPromptIndex=queuedMessages.findIndex(message=>!this.isExtensionCommand(message.text));if(firstPromptIndex===-1){for(let message of queuedMessages)await this.session.prompt(message.text);return}let preCommands=queuedMessages.slice(0,firstPromptIndex),firstPrompt=queuedMessages[firstPromptIndex],rest=queuedMessages.slice(firstPromptIndex+1);for(let message of preCommands)await this.session.prompt(message.text);let promptPromise=this.session.prompt(firstPrompt.text,{streamingBehavior:firstPrompt.mode}).catch(error=>{restoreQueue(error)});for(let message of rest)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay()}catch(error){restoreQueue(error)}}flushPendingBashComponents(){for(let component of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(component),this.chatContainer.addChild(component);this.pendingBashComponents=[]}disposeActiveSelector(){let dispose=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,dispose?.()}showSelector(create){let token={},dispose,created=create(()=>{dispose?.(),this.activeSelectorToken===token&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))}),release2=created.dispose,released=!1;dispose=()=>{released||(released=!0,release2?.())},this.disposeActiveSelector(),this.activeSelectorToken=token,this.activeSelectorDispose=dispose,this.editorContainer.clear(),this.editorContainer.addChild(created.component),this.ui.setFocus(created.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(done=>{let selector,defaultProvider=this.settingsManager.getDefaultProvider(),defaultModelId=this.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:"not set";return selector=new SettingsSelectorComponent({autoCompact:this.session.autoCompactionEnabled,defaultModel,currentModel:this.session.model,availableDefaultModels:this.session.modelRuntime.getAvailableSnapshot(),showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),cacheWarmingMode:this.settingsManager.getCacheWarmingMode(),thinkingLevel:this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:this.settingsManager.getAllModelThinkingLevels(),currentTheme:this.themeController.getThemeSelection()||"dark",terminalTheme:this.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:enabled=>{this.session.setAutoCompactionEnabled(enabled),this.footer.setAutoCompactEnabled(enabled)},onShowImagesChange:enabled=>{this.settingsManager.setShowImages(enabled);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{this.settingsManager.setImageWidthCells(width);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{this.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{this.settingsManager.setBlockImages(blocked)},onEnableSkillCommandsChange:enabled=>{this.settingsManager.setEnableSkillCommands(enabled),this.setupAutocompleteProvider()},onSteeringModeChange:mode=>{this.session.setSteeringMode(mode)},onFollowUpModeChange:mode=>{this.session.setFollowUpMode(mode)},onTransportChange:transport=>{this.settingsManager.setTransport(transport),this.session.agent.transport=transport},onHttpIdleTimeoutMsChange:timeoutMs=>{this.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`)},onCacheWarmingModeChange:mode=>{this.session.setCacheWarmingMode(mode),this.showStatus(`Cache warming: ${mode}`)},onModelThinkingLevelChange:(provider,modelId2,level)=>{this.settingsManager.setModelThinkingLevel(provider,modelId2,level);let current=this.session.model;current&¤t.provider===provider&¤t.id===modelId2&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId2)=>{this.settingsManager.removeModelThinkingLevel(provider,modelId2);let current=this.session.model;if(current&¤t.provider===provider&¤t.id===modelId2){let globalDefault=this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;this.session.setThinkingLevel(globalDefault),this.footer.invalidate(),this.updateEditorBorderColor()}},onThemeChange:themeSetting=>{this.settingsManager.setTheme(themeSetting),this.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>this.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{this.hideThinkingBlock=hidden,this.settingsManager.setHideThinkingBlock(hidden),this.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{this.settingsManager.setMermaidRenderingMode(mode),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{this.settingsManager.setShowCacheMissNotices(shown),this.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{this.settingsManager.setCollapseChangelog(collapsed)},onEnableInstallTelemetryChange:enabled=>{this.settingsManager.setEnableInstallTelemetry(enabled)},onQuietStartupChange:enabled=>{this.settingsManager.setQuietStartup(enabled)},onDefaultProjectTrustChange:defaultProjectTrust=>{this.settingsManager.setDefaultProjectTrust(defaultProjectTrust)},onDoubleEscapeActionChange:action=>{this.settingsManager.setDoubleEscapeAction(action)},onTreeFilterModeChange:mode=>{this.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{this.settingsManager.setShowHardwareCursor(enabled),this.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{this.settingsManager.setEditorPaddingX(padding),this.defaultEditor.setPaddingX(padding),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(padding)},onOutputPadChange:padding=>{if(this.settingsManager.setOutputPad(padding),this.outputPad=padding,this.streamingComponent||this.session.isStreaming){for(let child of this.chatContainer.children)(child instanceof AssistantMessageComponent||child instanceof CustomMessageComponent||child instanceof UserMessageComponent)&&child.setOutputPad(padding);this.streamingComponent&&this.streamingComponent.setOutputPad(padding),this.ui.requestRender();return}this.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:maxVisible=>{this.settingsManager.setAutocompleteMaxVisible(maxVisible),this.defaultEditor.setAutocompleteMaxVisible(maxVisible),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{this.settingsManager.setClearOnShrink(enabled),this.ui.setClearOnShrink(enabled),!enabled&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{this.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!this.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(mode),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${mode}`)},onFullscreenExitOutputChange:output=>{this.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{this.settingsManager.setFullscreenScrollbar(mode),this.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{this.settingsManager.setFullscreenCopyOnSelect(enabled),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(enabled)},onWarningsChange:warnings=>{this.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),this.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}handleThinkingCommand(searchTerm){let availableLevels=this.session.getAvailableThinkingLevels();if(!searchTerm){this.showThinkingSelector();return}let normalized=searchTerm.trim().toLowerCase(),level=availableLevels.find(candidate=>candidate.toLowerCase()===normalized);if(!level){this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);return}this.selectThinkingLevel(level,!1)}selectThinkingLevel(level,persist){try{this.session.setThinkingLevel(level,{persist}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(persist?`Default thinking level: ${level}`:`Thinking level: ${level}`)}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showThinkingSelector(){this.showSelector(done=>{let selectLevel=(level,persist)=>{this.selectThinkingLevel(level,persist),done()},selector=new ThinkingSelectorComponent(this.session.thinkingLevel??DEFAULT_THINKING_LEVEL,this.session.getAvailableThinkingLevels(),level=>selectLevel(level,!1),()=>{done(),this.ui.requestRender()},level=>selectLevel(level,!0),this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL);return{component:selector,focus:selector}})}async handleModelCommand(searchTerm){if(!searchTerm){this.showModelSelector();return}let model=await this.findExactModelMatch(searchTerm);if(model){try{await this.session.setModel(model,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model),this.checkDaxnutsEasterEgg(model)}catch(error){this.showError(error instanceof Error?error.message:String(error))}return}this.showModelSelector(searchTerm)}async findExactModelMatch(searchTerm){let cachedModels=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):[...this.session.modelRuntime.getAvailableSnapshot()],cachedMatch=findExactModelReferenceMatch(searchTerm,cachedModels);if(cachedMatch||this.session.scopedModels.length>0)return cachedMatch;this.showStatus("Refreshing model catalogs\u2026");let controller=new AbortController,timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3);try{let result2=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result2.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result2.errors.size>0&&this.showWarning(`Could not refresh ${[...result2.errors.keys()].join(", ")}; searching cached models.`)}catch(error){this.showWarning(timedOut?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`)}finally{clearTimeout(timeout)}return findExactModelReferenceMatch(searchTerm,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let models=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):this.session.modelRuntime.getAvailableSnapshot(),uniqueProviders=new Set(models.map(model=>model.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model||model.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);return}let apiKey=(await this.session.modelRuntime.getAuth(model.provider))?.auth.apiKey;if(!isAnthropicSubscriptionAuthKey(apiKey))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let cwd=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==cwd||!this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(cwd))return!1;let trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir);try{return trustStore.get(cwd)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(trustStore.set(cwd,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(error){return this.showWarning(`Could not save project trust after reload: ${error instanceof Error?error.message:String(error)}`),!1}}showTrustSelector(){let cwd=this.sessionManager.getCwd(),trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir),savedDecision=trustStore.getEntry(cwd);this.showSelector(done=>{let selector=new TrustSelectorComponent({cwd,savedDecision,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:selection=>{trustStore.setMany(selection.updates),done(),this.showStatus(`Saved trust decision: ${selection.trusted?"trusted":"untrusted"}. Restart ${APP_NAME} for this to take effect.`)},onCancel:()=>{done(),this.ui.requestRender()}});return{component:selector,focus:selector}})}showModelSelector(initialSearchInput){this.showSelector(done=>{let selectModel=async(model,persist)=>{try{await this.session.setModel(model,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model.provider}/${model.id}`:`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model),this.checkDaxnutsEasterEgg(model)}catch(error){done(),this.showError(error instanceof Error?error.message:String(error))}},defaultProvider=this.settingsManager.getDefaultProvider(),defaultModel=this.settingsManager.getDefaultModel(),selector=new ModelSelectorComponent(this.ui,this.session.model,this.session.modelRuntime,this.session.scopedModels,model=>selectModel(model,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model=>selectModel(model,!0),defaultProvider&&defaultModel?{provider:defaultProvider,id:defaultModel}:void 0);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showModelsSelector(){let availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),configuredPatterns=this.settingsManager.getEnabledModels(),sessionScopedModels=this.session.scopedModels,configuredEnabledIds=models=>{if(!configuredPatterns?.length)return null;let resolved=resolveModelScopeFromModels(configuredPatterns,models),ids=resolved.scopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`);for(let diagnostic of resolved.diagnostics)diagnostic.code==="no-match"&&!ids.includes(diagnostic.pattern)&&ids.push(diagnostic.pattern);return ids},currentEnabledIds=sessionScopedModels.length>0?sessionScopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`):configuredEnabledIds(availableModels),selectionChanged=!1,updateSessionModels=enabledIds=>{currentEnabledIds=enabledIds===null?null:[...enabledIds];let hasEnabledAvailableModel=enabledIds?.some(id=>availableModelIds.has(id))??!1,allAvailableModelsEnabled=enabledIds!==null&&[...availableModelIds].every(id=>enabledIds.includes(id));if(enabledIds&&hasEnabledAvailableModel&&!allAvailableModelsEnabled){let newScopedModels=resolveModelScopeFromModels(enabledIds,availableModels).scopedModels;this.session.setScopedModels(newScopedModels.map(scoped=>({model:scoped.model,thinkingLevel:scoped.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(done=>{let disposed=!1,timedOut=!1,controller=new AbortController,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3),selector=new ScopedModelsSelectorComponent({allModels:availableModels,enabledModelIds:currentEnabledIds,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:enabledIds=>{selectionChanged=!0,updateSessionModels(enabledIds)},onPersist:enabledIds=>{let allEnabled=enabledIds!==null&&enabledIds.length===availableModels.length&&enabledIds.every(id=>availableModelIds.has(id)),newPatterns=enabledIds===null||allEnabled?void 0:enabledIds;this.settingsManager.setEnabledModels(newPatterns?[...newPatterns]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{done(),this.ui.requestRender()}});return refreshModelCatalogs(this.session.modelRuntime,controller.signal).then(result2=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result2.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result2.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result2.errors.keys()].join(", ")}; showing cached models.`,"warning"):selector.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(error=>{disposed||(selector.setRefreshStatus(timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(timeout)),{component:selector,focus:selector,dispose:()=>{disposed=!0,clearTimeout(timeout),controller.abort()}}})}showUserMessageSelector(){let userMessages=this.session.getUserMessagesForForking();if(userMessages.length===0){this.showStatus("No messages to fork from");return}let initialSelectedId=userMessages[userMessages.length-1]?.entryId;this.showSelector(done=>{let selector=new UserMessageSelectorComponent(userMessages.map(m2=>({id:m2.entryId,text:m2.text})),async entryId=>{done();try{let result2=await this.runtimeHost.fork(entryId);if(result2.cancelled){this.ui.requestRender();return}this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},()=>{done(),this.ui.requestRender()},initialSelectedId);return{component:selector,focus:selector.getMessageList()}})}async handleCloneCommand(){let leafId=this.sessionManager.getLeafId();if(!leafId){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(leafId,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showTreeSelector(initialSelectedId){let tree=this.sessionManager.getTree(),realLeafId=this.sessionManager.getLeafId(),initialFilterMode=this.settingsManager.getTreeFilterMode();if(tree.length===0){this.showStatus("No entries in session");return}this.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,this.ui.terminal.rows,async entryId=>{if(entryId===this.sessionManager.getLeafId()){done(),this.showStatus("Already at this point");return}done();let wantsSummary=!1,customInstructions;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(summaryChoice===void 0){this.showTreeSelector(entryId);return}if(wantsSummary=summaryChoice!=="No summary",!(summaryChoice==="Summarize with custom prompt"&&(customInstructions=await this.showExtensionEditor("Custom summarization instructions"),customInstructions===void 0)))break}if(this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort()),this.session.isCompacting){this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");return}let showingSummaryIndicator=!1,originalOnEscape=this.defaultEditor.onEscape;wantsSummary&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new Spacer(1)),this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)),showingSummaryIndicator=!0,this.ui.requestRender());try{let result2=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result2.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result2.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(error){this.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=originalOnEscape}},()=>{done(),this.ui.requestRender()},(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label),this.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text2=>{if(!text2){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text2),this.showStatus("Copied selected message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}showSessionSelector(){this.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress,signal),(onProgress,signal)=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress,signal):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress,signal),async sessionPath=>{done(),await this.handleResumeSession(sessionPath)},()=>{done(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:selector,focus:selector}})}async handleResumeSession(sessionPath,options){this.clearStatusIndicator();try{let result2=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session"),result2}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result2=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session in current cwd"),result2}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0;(!authType||authType==="oauth")&&provider.auth.oauth&&options.push({id:provider.id,name:provider.name,authType:"oauth",method:provider.auth.oauth,status}),(!authType||authType==="api_key")&&provider.auth.apiKey&&options.push({id:provider.id,name:provider.name,authType:"api_key",method:provider.auth.apiKey,status})}return options.sort((a,b2)=>a.name.localeCompare(b2.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId,type})=>({id:providerId,name:this.session.modelRuntime.getProvider(providerId)?.name??providerId,authType:type,status:{type,source:"stored credential"}})).sort((a,b2)=>a.name.localeCompare(b2.name))}findLoginProviderOptions(providerRef){let normalizedProviderRef=providerRef.trim().toLowerCase();return normalizedProviderRef?this.getLoginProviderOptions().filter(provider=>provider.id.toLowerCase()===normalizedProviderRef||provider.name.toLowerCase()===normalizedProviderRef):[]}async handleLoginCommand(providerRef){if(!providerRef){this.showLoginAuthTypeSelector();return}let providerOptions=this.findLoginProviderOptions(providerRef);if(providerOptions.length===1){await this.startProviderLogin(providerOptions[0]);return}if(providerOptions.length>1&&new Set(providerOptions.map(provider=>provider.id)).size===1){this.showLoginAuthTypeSelector(providerOptions);return}this.showLoginProviderSelector(void 0,providerRef)}async startProviderLogin(providerOption){providerOption.authType==="oauth"?await this.showLoginDialog(providerOption.id,providerOption.name):providerOption.method?.login?await this.showApiKeyLoginDialog(providerOption.id,providerOption.name):this.showAmbientAuthDialog(providerOption)}showLoginAuthTypeSelector(providerOptions){let oauthProvider=providerOptions?.find(provider=>provider.authType==="oauth"),subscriptionLabel=(oauthProvider?.method&&"loginLabel"in oauthProvider.method?oauthProvider.method.loginLabel:void 0)??"Sign in with an account",apiKeyLabel="Sign in with an API key",availableAuthTypes=providerOptions?new Set(providerOptions.map(provider=>provider.authType)):new Set(["oauth","api_key"]),options=[];if(availableAuthTypes.has("oauth")&&options.push(subscriptionLabel),availableAuthTypes.has("api_key")&&options.push(apiKeyLabel),options.length===0){this.showStatus("No login methods available.");return}if(providerOptions&&options.length===1){let providerOption=providerOptions[0];providerOption&&this.startProviderLogin(providerOption);return}let title=providerOptions?.[0]?`Select authentication method for ${providerOptions[0].name}:`:"Select authentication method:";this.showSelector(done=>{let selector=new ExtensionSelectorComponent(title,options,option=>{done();let authType=option===subscriptionLabel?"oauth":"api_key";if(providerOptions){let providerOption=providerOptions.find(provider=>provider.authType===authType);providerOption&&this.startProviderLogin(providerOption);return}this.showLoginProviderSelector(authType)},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}showLoginProviderSelector(authType,initialSearchInput){let providerOptions=this.getLoginProviderOptions(authType);if(providerOptions.length===0){let message=authType==="oauth"?"No subscription providers available.":authType==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(message);return}this.showSelector(done=>{let selector=new OAuthSelectorComponent("login",providerOptions,async(providerId,selectedAuthType)=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId&&provider.authType===selectedAuthType);providerOption&&await this.startProviderLogin(providerOption)},()=>{done(),authType?this.showLoginAuthTypeSelector():this.ui.requestRender()},initialSearchInput);return{component:selector,focus:selector}})}async showOAuthSelector(mode){if(mode==="login"){this.showLoginAuthTypeSelector();return}let providerOptions;try{providerOptions=await this.getLogoutProviderOptions()}catch(error){this.showError(`Could not read stored credentials: ${error instanceof Error?error.message:String(error)}`);return}if(providerOptions.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(done=>{let selector=new OAuthSelectorComponent(mode,providerOptions,async providerId=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId);if(providerOption)try{await this.session.modelRuntime.logout(providerOption.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let message=providerOption.authType==="oauth"?`Logged out of ${providerOption.name}`:`Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;this.showStatus(message)}catch(error){let message=error instanceof Error?error.message:String(error);this.showError(error instanceof CredentialSynchronizationError?`Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`:`Logout failed: ${message}`)}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async completeProviderAuthentication(providerId,providerName,authType,previousModel){let actionLabel=authType==="oauth"?`Logged in to ${providerName}`:`Saved API key for ${providerName}`,session=this.session,deferSelection=isUnknownModel(previousModel)&&hasDefaultModelProvider(providerId)&&!session.modelRuntime.getAvailableSnapshot().some(model=>model.provider===providerId&&model.id===defaultModelPerProvider[providerId]),finishAuthentication=async()=>{let selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model=>model.provider===providerId);if(providerId==="llama.cpp")selectionError=llamaCppPostLoginGuidance(actionLabel,providerModels.length);else if(!hasDefaultModelProvider(providerId))selectionError=`${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;else if(providerModels.length===0)selectionError=`${actionLabel}, but no models are available for that provider. Use /model to select a model.`;else{let defaultModelId=defaultModelPerProvider[providerId];if(selectedModel=providerModels.find(model=>model.id===defaultModelId)??(providerId==="radius"?providerModels[0]:void 0),!selectedModel)selectionError=`${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;else try{await this.session.setModel(selectedModel,{persist:!0})}catch(error){selectedModel=void 0;let errorMessage6=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage6}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),selectedModel?(this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel),this.checkDaxnutsEasterEgg(selectedModel)):(this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`),selectionError?this.showError(selectionError):this.maybeWarnAboutAnthropicSubscriptionAuth())};deferSelection?this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog\u2026`):await finishAuthentication();let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(async result2=>{result2.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result2.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),deferSelection&&this.session===session&&session.model===previousModel&&await finishAuthentication(),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(error=>{this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error?error.message:String(error)}`)}).finally(()=>clearTimeout(timeout))}showAmbientAuthDialog(providerOption){let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>restoreEditor3(),providerOption.name,`${providerOption.name} setup`);dialog.showInfo(`${providerOption.method?.name??"Authentication"} is configured outside ${APP_NAME}.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()}async showApiKeyLoginDialog(providerId,providerName){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);providerId==="amazon-bedrock"&&dialog.showDetails([theme.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),theme.fg("muted","See:"),theme.fg("accent",` ${path13.join(getDocsPath(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"api_key"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg!=="Login cancelled"&&this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`)}}showAuthSelect(dialog,prompt){return new Promise((resolve17,reject)=>{let restoreDialog=()=>{this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()},labels=prompt.options.map(option=>option.label),selector=new ExtensionSelectorComponent(prompt.message,labels,optionLabel=>{restoreDialog();let id=prompt.options.find(option=>option.label===optionLabel)?.id;id?resolve17(id):reject(new Error("Login cancelled"))},()=>{restoreDialog(),reject(new Error("Login cancelled"))});this.editorContainer.clear(),this.editorContainer.addChild(selector),this.ui.setFocus(selector),this.ui.requestRender()})}async showAuthPrompt(dialog,prompt){let response;if(prompt.type==="select"?response=this.showAuthSelect(dialog,prompt):prompt.type==="manual_code"?response=dialog.showManualInput(prompt.message):response=dialog.showPrompt(prompt.message,prompt.placeholder),!prompt.signal)return response;if(prompt.signal.aborted)throw new Error("Login cancelled");let signal=prompt.signal,onAbort,aborted=new Promise((_resolve,reject)=>{onAbort=()=>reject(new Error("Login cancelled")),signal.addEventListener("abort",onAbort,{once:!0})});try{return await Promise.race([response,aborted])}finally{onAbort&&signal.removeEventListener("abort",onAbort)}}notifyAuthDialog(dialog,event){event.type==="auth_url"?dialog.showAuth(event.url,event.instructions):event.type==="device_code"?(dialog.showDeviceCode(event),dialog.showWaiting("Waiting for authentication...")):event.type==="info"?dialog.showInfo(event.message,event.links):dialog.showProgress(event.message)}async loginProvider(dialog,providerId,method){await this.session.modelRuntime.login(providerId,method,{signal:dialog.signal,prompt:prompt=>this.showAuthPrompt(dialog,prompt),notify:event=>this.notifyAuthDialog(dialog,event)})}async showLoginDialog(providerId,providerName){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"oauth"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg!=="Login cancelled"&&this.showError(`Failed to login to ${providerName}: ${errorMsg}`)}}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let reloadBox=new Container,borderColor=s=>theme.fg("border",s);reloadBox.addChild(new DynamicBorder(borderColor)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new Text(theme.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new DynamicBorder(borderColor));let previousEditor=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(reloadBox),this.ui.setFocus(reloadBox),this.ui.requestRender(!0),await new Promise(resolve17=>process.nextTick(resolve17));let dismissReloadBox=editor=>{this.editorContainer.clear(),this.editorContainer.addChild(editor),this.ui.setFocus(editor),this.ui.requestRender()},chatRestoredBeforeSessionStart=!1,reloadBoxDismissed=!1,restoreChatBeforeSessionStart=()=>{chatRestoredBeforeSessionStart||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),chatRestoredBeforeSessionStart=!0)};try{await this.session.reload({beforeSessionStart:restoreChatBeforeSessionStart}),restoreChatBeforeSessionStart(),this.keybindings.reload();let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(this.toolOutputExpanded),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.applyRuntimeSettings(),await this.themeController.applyFromSettings(),this.setupAutocompleteProvider();let runner=this.session.extensionRunner;this.setupExtensionShortcuts(runner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let savedImplicitProjectTrust=this.maybeSaveImplicitProjectTrustAfterReload(),modelsJsonError=this.session.modelRuntime.getError();modelsJsonError&&this.showError(`models.json error: ${modelsJsonError}`),this.showStatus(savedImplicitProjectTrust?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),dismissReloadBox(this.editor),reloadBoxDismissed=!0}catch(error){reloadBoxDismissed||dismissReloadBox(previousEditor),this.showError(`Reload failed: ${error instanceof Error?error.message:String(error)}`)}}async handleExportCommand(text2){let outputPath=this.getPathCommandArgument(text2,"/export");try{if(outputPath?.endsWith(".jsonl")){let filePath=this.session.exportToJsonl(outputPath);this.showStatus(`Session exported to: ${filePath}`)}else{let filePath=await this.session.exportToHtml(outputPath,{themeName:theme.name});this.showStatus(`Session exported to: ${filePath}`)}}catch(error){this.showError(`Failed to export session: ${error instanceof Error?error.message:"Unknown error"}`)}}getPathCommandArgument(text2,command){if(text2===command||!text2.startsWith(`${command} `))return;let argsString=text2.slice(command.length+1).trimStart();if(!argsString)return;let firstChar=argsString[0];if(firstChar==='"'||firstChar==="'"){let closingQuoteIndex=argsString.indexOf(firstChar,1);return closingQuoteIndex<0?void 0:argsString.slice(1,closingQuoteIndex)}let firstWhitespaceIndex=argsString.search(/\s/);return firstWhitespaceIndex<0?argsString:argsString.slice(0,firstWhitespaceIndex)}async handleImportCommand(text2){let inputPath=this.getPathCommandArgument(text2,"/import");if(!inputPath){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${inputPath}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(inputPath)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`)}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(inputPath,selectedCwd)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`);return}if(error instanceof SessionImportFileNotFoundError){this.showError(`Failed to import session: ${error.message}`);return}await this.handleFatalRuntimeError("Failed to import session",error)}}async handleShareCommand(){await shareSession({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)})}async handleBugCommand(hint2){await reportBug({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,keybindings:this.keybindings,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)},hint2)}async handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text2=this.session.getLastAssistantText();if(!text2){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text2),options.flashConfirmation&&this.ui instanceof TuiAltScreen?this.ui.flash("Copied!"):this.showStatus("Copied last agent message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}handleNameCommand(text2){let name=text2.replace(/^\/name\s*/,"").trim();if(!name){let currentName=this.sessionManager.getSessionName();currentName?(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name: ${currentName}`),1,0))):this.showWarning("Usage: /name <name>"),this.ui.requestRender();return}this.session.setSessionName(name);let sessionName2=this.sessionManager.getSessionName();sessionName2!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName2)}`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name set: ${sessionName2??name}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName2=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),info=`${theme.bold("Session Info")}
|
|
1393
1393
|
|
|
1394
1394
|
`;sessionName2&&(info+=`${theme.fg("dim","Name:")} ${sessionName2}
|
|
1395
1395
|
`),info+=`${theme.fg("dim","File:")} ${stats.sessionFile??"In-memory"}
|
|
@@ -1495,7 +1495,7 @@ changes anytime in settings.json.`),1,0)),this.addChild(new Spacer(1)),this.addO
|
|
|
1495
1495
|
${message}`,[{label:"Yes",value:!0},{label:"No",value:!1}])??!1,input:async(title,placeholder)=>{if(options.hasUI&&options.mode==="interactive")return showStartupInput(options.settingsManager,title,placeholder)},notify:(message,type="info")=>{if(options.mode!=="interactive"){let color2=type==="error"?source_default.red:type==="warning"?source_default.yellow:source_default.cyan;console.error(color2(message))}}}}}async function selectSession(currentSessionsLoader,allSessionsLoader,settingsManager){let ui=await createStartupTui(settingsManager);return new Promise(resolve17=>{let keybindings=KeybindingsManager2.create();setKeybindings(keybindings);let resolved=!1,selector=new SessionSelectorComponent(currentSessionsLoader,allSessionsLoader,path14=>{resolved||(resolved=!0,ui.stop(),resolve17(path14))},()=>{resolved||(resolved=!0,ui.stop(),resolve17(null))},()=>{ui.stop(),process.exit(0)},()=>ui.requestRender(),{showRenameHint:!1,keybindings});ui.addChild(selector),ui.setFocus(selector.getSessionList()),startStartupTui(ui,settingsManager)})}function formatProjectTrustPrompt(cwd){return`Trust project folder?
|
|
1496
1496
|
${cwd}
|
|
1497
1497
|
|
|
1498
|
-
This allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`}async function selectProjectTrustOption(cwd,ctx){let options=getProjectTrustOptions(cwd,{includeSessionOnly:!0}),selected=await ctx.ui.select(formatProjectTrustPrompt(cwd),options.map(option=>option.label));return options.find(option=>option.label===selected)}function saveProjectTrustPromptResult(trustStore,result2){result2.updates.length>0&&trustStore.setMany(result2.updates)}async function resolveProjectTrusted(options){if(options.trustOverride!==void 0)return options.trustOverride;if(!hasTrustRequiringProjectResources(options.cwd))return!0;if(options.extensionsResult){let{result:result2,errors}=await emitProjectTrustEvent(options.extensionsResult,{type:"project_trust",cwd:options.cwd},options.projectTrustContext);for(let error of errors)options.onExtensionError?.(`Extension "${error.extensionPath}" project_trust error: ${error.error}`);if(result2){let trusted=result2.trusted==="yes";return result2.remember===!0&&options.trustStore.set(options.cwd,trusted),trusted}}let decision=options.trustStore.get(options.cwd);if(decision!==null)return decision;switch(options.defaultProjectTrust??"ask"){case"always":return!0;case"never":return!1;case"ask":break}if(!options.projectTrustContext.hasUI)return!1;let selected=await selectProjectTrustOption(options.cwd,options.projectTrustContext);return selected!==void 0?(saveProjectTrustPromptResult(options.trustStore,selected),selected.trusted):!1}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path14,error})=>({type:"warning",message:path14?`Invalid settings file ${path14}: ${error.message}`:`Invalid ${scope} settings: ${error.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic=>{let key=`${diagnostic.type}\0${diagnostic.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}registerKeybindings({"app.backgroundTasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground Bash and Subagent executions to the background"},"app.backgroundTasks.focusList":{defaultKeys:"left",description:"Focus the background task list"},"app.backgroundTasks.focusPreview":{defaultKeys:"right",description:"Focus the background task preview"},"app.backgroundTasks.kill":{defaultKeys:"k",description:"Kill selected background task"},"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"}});var BG_NOTIFICATION_TYPE="background-task",BG_COMPLETION_TYPE="background-completion";var bgSchema=typebox_exports.Object({action:StringEnum(["read","wait","kill","list"],{description:"Which background-task operation to perform"}),taskId:typebox_exports.Optional(typebox_exports.String({description:"Bash task or Subagent group id (read/wait/kill)"})),mode:typebox_exports.Optional(StringEnum(["tail","head"],{description:"Read from the end (default) or the start of the output (read)"})),bytes:typebox_exports.Optional(typebox_exports.Number({description:`Max bytes to return (read, default ${formatSize(8192)}, max ${formatSize(51200)})`})),waitMs:typebox_exports.Optional(typebox_exports.Number({description:`Max time to wait in ms, default ${2e4}, max ${6e4} (wait)`})),sinceBytes:typebox_exports.Optional(typebox_exports.Number({description:"Only return output written after this byte offset \u2014 take it from a previous read/wait result (wait)"}))});function requireTaskId(input2){let taskId=input2.taskId;if(!taskId||taskId.trim().length===0)throw new Error(`action '${input2.action}' requires 'taskId' \u2014 use action list to find the execution id.`);return taskId}function clampReadBytes(bytes){let value2=bytes!==void 0&&Number.isFinite(bytes)?bytes:8192;return Math.min(51200,Math.max(256,Math.floor(value2)))}function clampWaitMs(waitMs){let value2=waitMs!==void 0&&Number.isFinite(waitMs)?waitMs:2e4;return Math.min(6e4,Math.max(1e3,Math.floor(value2)))}function clampSinceBytes(sinceBytes){return sinceBytes===void 0||!Number.isFinite(sinceBytes)?void 0:Math.max(0,Math.floor(sinceBytes))}var BG_TOOL_DESCRIPTION="Inspect and control backgrounded work: Bash tasks and Subagent groups started with background: true. Completion is delivered to you automatically as a notification \u2014 never poll. list: bounded activity/history listing; find task IDs here. read: bounded output or report slice (head/tail). wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. kill: request cancellation of a task or a whole Subagent group, never an individual worker. bg cannot start work; pass background: true to bash or subagent. Output is capped at 50KB per response.",BG_PROMPT_SNIPPET="Manage Bash tasks and Subagent groups (list, read, wait, kill)",BG_PROMPT_GUIDELINES=["Start background work through bash or subagent with background: true; continue independent work while it runs.","A finished background task delivers its result automatically as a notification; use bg wait only when your next step is blocked on it, and never sleep-poll with repeated reads."];var SPINNER_BLOOM=["\xB7","\u2722","\u273C","\u2736","\u273B","\u273D"],STATUS_SPINNER_FRAMES=[...SPINNER_BLOOM,...[...SPINNER_BLOOM].reverse()],STATUS_SPINNER_INTERVAL_MS=120;function statusSpinnerFrame(now){let frame2=Math.floor(now/STATUS_SPINNER_INTERVAL_MS)%STATUS_SPINNER_FRAMES.length;return STATUS_SPINNER_FRAMES[frame2]??STATUS_SPINNER_FRAMES[0]??"\xB7"}function statusMarker(status,opts){if(opts?.stalled)return{glyph:"!",color:"warning"};switch(status){case"running":return{glyph:opts?.now!==void 0?statusSpinnerFrame(opts.now):"\u203A",color:"accent"};case"completed":return{glyph:"\u2713",color:"success"};case"failed":return{glyph:"\xD7",color:"error"};case"timeout":return{glyph:"\xD7",color:"warning"};case"cancelled":case"killed":case"stopping":case"partial":case"aborted":return{glyph:"\u25CB",color:"warning"};case"queued":return{glyph:"\u25CB",color:"muted"};default:return{glyph:"\u2022",color:"muted"}}}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function
|
|
1498
|
+
This allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`}async function selectProjectTrustOption(cwd,ctx){let options=getProjectTrustOptions(cwd,{includeSessionOnly:!0}),selected=await ctx.ui.select(formatProjectTrustPrompt(cwd),options.map(option=>option.label));return options.find(option=>option.label===selected)}function saveProjectTrustPromptResult(trustStore,result2){result2.updates.length>0&&trustStore.setMany(result2.updates)}async function resolveProjectTrusted(options){if(options.trustOverride!==void 0)return options.trustOverride;if(!hasTrustRequiringProjectResources(options.cwd))return!0;if(options.extensionsResult){let{result:result2,errors}=await emitProjectTrustEvent(options.extensionsResult,{type:"project_trust",cwd:options.cwd},options.projectTrustContext);for(let error of errors)options.onExtensionError?.(`Extension "${error.extensionPath}" project_trust error: ${error.error}`);if(result2){let trusted=result2.trusted==="yes";return result2.remember===!0&&options.trustStore.set(options.cwd,trusted),trusted}}let decision=options.trustStore.get(options.cwd);if(decision!==null)return decision;switch(options.defaultProjectTrust??"ask"){case"always":return!0;case"never":return!1;case"ask":break}if(!options.projectTrustContext.hasUI)return!1;let selected=await selectProjectTrustOption(options.cwd,options.projectTrustContext);return selected!==void 0?(saveProjectTrustPromptResult(options.trustStore,selected),selected.trusted):!1}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path14,error})=>({type:"warning",message:path14?`Invalid settings file ${path14}: ${error.message}`:`Invalid ${scope} settings: ${error.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic=>{let key=`${diagnostic.type}\0${diagnostic.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}registerKeybindings({"app.backgroundTasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground Bash and Subagent executions to the background"},"app.backgroundTasks.focusList":{defaultKeys:"left",description:"Focus the background task list"},"app.backgroundTasks.focusPreview":{defaultKeys:"right",description:"Focus the background task preview"},"app.backgroundTasks.kill":{defaultKeys:"k",description:"Kill selected background task"},"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"}});var BG_NOTIFICATION_TYPE="background-task",BG_COMPLETION_TYPE="background-completion";var bgSchema=typebox_exports.Object({action:StringEnum(["read","wait","kill","list"],{description:"Which background-task operation to perform"}),taskId:typebox_exports.Optional(typebox_exports.String({description:"Bash task or Subagent group id (read/wait/kill)"})),mode:typebox_exports.Optional(StringEnum(["tail","head"],{description:"Read from the end (default) or the start of the output (read)"})),bytes:typebox_exports.Optional(typebox_exports.Number({description:`Max bytes to return (read, default ${formatSize(8192)}, max ${formatSize(51200)})`})),waitMs:typebox_exports.Optional(typebox_exports.Number({description:`Max time to wait in ms, default ${2e4}, max ${6e4} (wait)`})),sinceBytes:typebox_exports.Optional(typebox_exports.Number({description:"Only return output written after this byte offset \u2014 take it from a previous read/wait result (wait)"}))});function requireTaskId(input2){let taskId=input2.taskId;if(!taskId||taskId.trim().length===0)throw new Error(`action '${input2.action}' requires 'taskId' \u2014 use action list to find the execution id.`);return taskId}function clampReadBytes(bytes){let value2=bytes!==void 0&&Number.isFinite(bytes)?bytes:8192;return Math.min(51200,Math.max(256,Math.floor(value2)))}function clampWaitMs(waitMs){let value2=waitMs!==void 0&&Number.isFinite(waitMs)?waitMs:2e4;return Math.min(6e4,Math.max(1e3,Math.floor(value2)))}function clampSinceBytes(sinceBytes){return sinceBytes===void 0||!Number.isFinite(sinceBytes)?void 0:Math.max(0,Math.floor(sinceBytes))}var BG_TOOL_DESCRIPTION="Inspect and control backgrounded work: Bash tasks and Subagent groups started with background: true. Completion is delivered to you automatically as a notification \u2014 never poll. list: bounded activity/history listing; find task IDs here. read: bounded output or report slice (head/tail). wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. kill: request cancellation of a task or a whole Subagent group, never an individual worker. bg cannot start work; pass background: true to bash or subagent. Output is capped at 50KB per response.",BG_PROMPT_SNIPPET="Manage Bash tasks and Subagent groups (list, read, wait, kill)",BG_PROMPT_GUIDELINES=["Start background work through bash or subagent with background: true; continue independent work while it runs.","A finished background task delivers its result automatically as a notification; use bg wait only when your next step is blocked on it, and never sleep-poll with repeated reads."];var SPINNER_BLOOM=["\xB7","\u2722","\u273C","\u2736","\u273B","\u273D"],STATUS_SPINNER_FRAMES=[...SPINNER_BLOOM,...[...SPINNER_BLOOM].reverse()],STATUS_SPINNER_INTERVAL_MS=120;function statusSpinnerFrame(now){let frame2=Math.floor(now/STATUS_SPINNER_INTERVAL_MS)%STATUS_SPINNER_FRAMES.length;return STATUS_SPINNER_FRAMES[frame2]??STATUS_SPINNER_FRAMES[0]??"\xB7"}function statusMarker(status,opts){if(opts?.stalled)return{glyph:"!",color:"warning"};switch(status){case"running":return{glyph:opts?.now!==void 0?statusSpinnerFrame(opts.now):"\u203A",color:"accent"};case"completed":return{glyph:"\u2713",color:"success"};case"failed":return{glyph:"\xD7",color:"error"};case"timeout":return{glyph:"\xD7",color:"warning"};case"cancelled":case"killed":case"stopping":case"partial":case"aborted":return{glyph:"\u25CB",color:"warning"};case"queued":return{glyph:"\u25CB",color:"muted"};default:return{glyph:"\u2022",color:"muted"}}}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function formatDuration2(ms){let totalSeconds=Math.max(0,Math.round(ms/1e3));if(totalSeconds<60)return`${totalSeconds}s`;let minutes=Math.floor(totalSeconds/60),seconds=totalSeconds%60;return minutes<60?`${minutes}m${String(seconds).padStart(2,"0")}s`:`${Math.floor(minutes/60)}h${String(minutes%60).padStart(2,"0")}m`}function fileNameOf(path14){return path14.replace(/\\/g,"/").split("/").at(-1)??path14}function formatAge(endedAt,now=Date.now()){let seconds=Math.max(0,Math.round((now-endedAt)/1e3));if(seconds<60)return`${seconds}s ago`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ago`;let hours=Math.floor(minutes/60);return hours<24?`${hours}h ago`:`${Math.floor(hours/24)}d ago`}function runtimeMs(task,now=Date.now()){return(task.endedAt??now)-task.startedAt}function runtimeLabel(task,now=Date.now()){return formatDuration2(runtimeMs(task,now))}function hasExitCode(exitCode){return exitCode!=null}function exitSuffix(exitCode,separator){return hasExitCode(exitCode)?`${separator}exit ${exitCode}`:""}function taskLabel(task){let command=firstCommandLine(task.command);return task.description?`${task.description} \u2014 ${command}`:command}function workerLabel(worker){return worker.description?`${worker.label} \u2014 ${worker.description}`:worker.label}function commandLabel(command,width){return truncateToWidth(firstCommandLine(command),width,"\u2026")}function statusGlyph(status,stalled){return statusMarker(status,{stalled}).glyph}function statusColor(status,stalled){return statusMarker(status,{stalled}).color}function boundedText(text2){return truncateHead(sanitizeBinaryOutput(text2),{maxBytes:50*1024,maxLines:2e3}).content}function result(text2,details){return{content:[{type:"text",text:boundedText(text2)}],details}}function describeTaskLine(task,now=Date.now()){return`${task.id} ${task.kind} ${task.status} (${task.mode}) ${runtimeLabel(task,now)} ${task.title.slice(0,200)}`}var LOOKUP_LIST_LIMIT=10;function recentFinishedFirst(tasks){return tasks.sort((left,right)=>(right.endedAt??0)-(left.endedAt??0))}function listedTasks(background){let all=background.list(),tasks=all.filter(task=>task.mode==="background");return{tasks,foregroundOmitted:all.length-tasks.length}}function foregroundOmissionNote(omitted){return omitted>0?`
|
|
1499
1499
|
${omitted} foreground ${omitted===1?"execution":"executions"} omitted \u2014 foreground work is delivered inline in the transcript.`:""}function lookupFailure(background,id,error){if(!(error instanceof BackgroundLookupError))return error instanceof Error?error:new Error(String(error));if(error.kind==="ambiguous"){let lines2=error.matches.map(task=>describeTaskLine(task)).join(`
|
|
1500
1500
|
`);return new Error(`Ambiguous background task ID "${id}" matches ${error.matches.length} tasks:
|
|
1501
1501
|
${lines2}`)}let{tasks,foregroundOmitted}=listedTasks(background),active=tasks.filter(task=>!isBackgroundTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isBackgroundTerminal(task.status))),shown=[...active,...finished].slice(0,LOOKUP_LIST_LIMIT);if(shown.length===0)return new Error(`No background task "${id}" in this session. No background tasks in this session.`);let lines=shown.map(task=>describeTaskLine(task)).join(`
|
|
@@ -1506,7 +1506,7 @@ ${lines}${foregroundOmissionNote(foregroundOmitted)}`)}function readText(header,
|
|
|
1506
1506
|
`)}${hidden>0?`
|
|
1507
1507
|
${hidden} more records not shown.`:""}${foregroundOmissionNote(foregroundOmitted)}`:`No background tasks. Start work through bash or subagent with background: true.${foregroundOmissionNote(foregroundOmitted)}`,{action:"list",running:active.length,finished:finished.length,shown:shown.length,hidden,...foregroundOmitted>0?{foregroundOmitted}:{}})}var SOURCE_LIMIT=64*1024,CARD_ROWS=128,OUTPUT_ROWS=20,REPORT_ROWS=24;function clean(text2){return sanitizeBinaryOutput(stripTerminalSequences(text2)).replace(/\r\n?/g,`
|
|
1508
1508
|
`)}function savedText(message){let content=message.content,text2="",clipped=!1;if(typeof content=="string")text2=content.slice(0,SOURCE_LIMIT),clipped=content.length>SOURCE_LIMIT;else if(Array.isArray(content)){let visited2=0;for(let block of content){if(++visited2>256){clipped=!0;break}if(!block||block.type!=="text"||typeof block.text!="string")continue;let next=`${text2?`
|
|
1509
|
-
`:""}${block.text.slice(0,SOURCE_LIMIT+1)}`,remaining=SOURCE_LIMIT-text2.length;if(text2+=next.slice(0,remaining),next.length>remaining||block.text.length>SOURCE_LIMIT){clipped=!0;break}}}return{text:clean(text2),clipped}}function completionView(message){let snapshot=readBackgroundCompletion(message.details);if(!snapshot){let{text:text2,clipped}=savedText(message);return{body:text2,truncated:clipped}}let view={kind:snapshot.kind,status:snapshot.status,id:clean(snapshot.taskId),body:"",diagnostic:snapshot.error===void 0?void 0:clean(snapshot.error),truncated:!1};return snapshot.kind==="bash"?(view.shell=snapshot.shell===void 0?void 0:clean(snapshot.shell),view.command=snapshot.command===void 0?void 0:clean(snapshot.command.text),view.cwd=snapshot.cwd===void 0?void 0:clean(snapshot.cwd),view.path=snapshot.outputPath===void 0?void 0:clean(snapshot.outputPath),view.body=clean(snapshot.output.text),view.truncated=snapshot.output.truncated||snapshot.command?.truncated===!0):snapshot.workers.length?view.workers=snapshot.workers.map((worker,index3)=>({index:index3+1,description:clean(worker.description),profile:clean(worker.profile),status:clean(worker.status),report:clean(worker.report.text),error:worker.error===void 0?void 0:clean(worker.error),truncated:worker.report.truncated})):(view.body=clean(snapshot.output?.text??""),view.truncated=snapshot.output?.truncated??!1),view}function failedWorker(worker){return!!worker.error||worker.status==="failed"||worker.status==="aborted"||worker.status==="cancelled"}function color(status){return status===void 0?"muted":statusMarker(status).color}function statusName(status){return status==="timeout"?"Timed out":status?status[0].toUpperCase()+status.slice(1):"Unknown"}function shortId(id){return id.replace(/^(bash|subagent)-(.{8}).+$/,"$1-$2")}var CompletionCard=class{constructor(view,options,theme2){this.view=view,this.options=options,this.theme=theme2}invalidate(){}render(width){
|
|
1509
|
+
`:""}${block.text.slice(0,SOURCE_LIMIT+1)}`,remaining=SOURCE_LIMIT-text2.length;if(text2+=next.slice(0,remaining),next.length>remaining||block.text.length>SOURCE_LIMIT){clipped=!0;break}}}return{text:clean(text2),clipped}}function completionView(message){let snapshot=readBackgroundCompletion(message.details);if(!snapshot){let{text:text2,clipped}=savedText(message);return{body:text2,truncated:clipped}}let view={kind:snapshot.kind,status:snapshot.status,id:clean(snapshot.taskId),body:"",diagnostic:snapshot.error===void 0?void 0:clean(snapshot.error),truncated:!1};return snapshot.kind==="bash"?(view.shell=snapshot.shell===void 0?void 0:clean(snapshot.shell),view.command=snapshot.command===void 0?void 0:clean(snapshot.command.text),view.cwd=snapshot.cwd===void 0?void 0:clean(snapshot.cwd),view.path=snapshot.outputPath===void 0?void 0:clean(snapshot.outputPath),view.body=clean(snapshot.output.text),view.truncated=snapshot.output.truncated||snapshot.command?.truncated===!0):snapshot.workers.length?view.workers=snapshot.workers.map((worker,index3)=>({index:index3+1,description:clean(worker.description),profile:clean(worker.profile),status:clean(worker.status),report:clean(worker.report.text),error:worker.error===void 0?void 0:clean(worker.error),truncated:worker.report.truncated})):(view.body=clean(snapshot.output?.text??""),view.truncated=snapshot.output?.truncated??!1),view}function failedWorker(worker){return!!worker.error||worker.status==="failed"||worker.status==="aborted"||worker.status==="cancelled"}function color(status){return status===void 0?"muted":statusMarker(status).color}function statusName(status){return status==="timeout"?"Timed out":status?status[0].toUpperCase()+status.slice(1):"Unknown"}function shortId(id){return id.replace(/^(bash|subagent)-(.{8}).+$/,"$1-$2")}var CompletionCard=class{constructor(view,options,theme2){this.view=view,this.options=options,this.theme=theme2}invalidate(){}render(width){return width<1?[]:new FramedComponent({render:contentWidth=>this.renderContent(contentWidth),invalidate(){}},"header",()=>color(this.view.status)).render(width).map(line=>truncateToWidth(line,width,""))}renderContent(width){if(!Number.isFinite(width)||width<1)return[];let view=this.view,theme2=this.theme,options=this.options,padding=Math.min(Math.max(0,Math.floor(options.outputPad||0)-1),Math.floor((width-1)/2)),inner=width-padding*2,indent=inner>=3?" ":"",bodyWidth=Math.max(1,inner-indent.length),lines=[],status=view.status?statusName(view.status):"Result received",kind=view.kind==="subagent"?"Subagent":view.kind==="bash"?view.shell==="bash"?"Bash":view.shell||"Shell":"Notification";if(lines.push(`${theme2.fg("toolTitle",theme2.bold(kind))}${theme2.fg("muted",` \xB7 Background ${status.toLowerCase()}`)}${view.id?theme2.fg("dim",` \xB7 ${shortId(view.id)}`):""}`),options.expanded){view.truncated&&lines.push(theme2.fg("warning","The saved result is truncated; this is not the complete original output."));let section=(title,text2,limit,markdown=!1,tail=!1,error=!1)=>{lines.push("",theme2.fg("muted",theme2.bold(title)));let rendered=markdown?new Markdown(text2,0,0,getMarkdownTheme()).render(bodyWidth):wrapTextWithAnsi(text2,bodyWidth).map(line=>theme2.fg(error?"error":"toolOutput",line)),omitted=Math.max(0,rendered.length-limit),selected=tail?rendered.slice(-limit):rendered.slice(0,limit);tail&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} earlier display lines omitted`));for(let line of selected)lines.push(indent+line);!tail&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} more display lines omitted`))};if(view.kind==="subagent"&&view.diagnostic&§ion("Group result",view.diagnostic,4,!1,!1,view.status==="failed"),view.kind==="bash")view.command&§ion("Command",view.command,8),view.cwd&§ion("Directory",view.cwd,2),section(view.status==="failed"||view.status==="timeout"?"Error":"Result",view.diagnostic??status,4,!1,!1,view.status==="failed"),section("Output",view.body.trim()?view.body:"No output.",OUTPUT_ROWS,!1,!0),view.path&§ion("Log",view.path,4);else if(view.workers){let reportBudget=Math.min(REPORT_ROWS,Math.max(6,Math.floor(72/view.workers.length)));for(let worker of view.workers){let marker=statusMarker(worker.status);lines.push("",`${theme2.fg(marker.color,`${marker.glyph} #${worker.index} ${statusName(worker.profile)}`)}${theme2.fg("muted",` \xB7 ${statusName(worker.status)}`)}`),lines.push(theme2.fg("muted",`Task: ${worker.description}`)),failedWorker(worker)?(section("Reason",worker.error||statusName(worker.status),2,!1,!1,worker.status==="failed"),worker.report&§ion("Partial report",worker.report,Math.max(3,reportBudget-6),!0)):section("Report",worker.report||"No report returned.",reportBudget,!0),worker.truncated&&lines.push(theme2.fg("warning"," Saved report truncated."))}}else section("Details",view.body||"No text result.",36,!0);view.id&&lines.push("",...wrapTextWithAnsi(`Task ID: ${view.id}`,inner).map(line=>theme2.fg("dim",line))),lines.push(theme2.fg("dim","Preview of the saved result \xB7 /bg has task details while retained."))}else{view.command?lines.push(theme2.fg("toolOutput",`$ ${view.command.split(`
|
|
1510
1510
|
`)[0]}`)):view.workers&&lines.push(theme2.fg("muted",`${view.workers.length} worker${view.workers.length===1?"":"s"} \xB7 reports available`)),view.diagnostic&&lines.push(theme2.fg(color(view.status),view.diagnostic));let problem=view.workers?.find(failedWorker);problem&&lines.push(theme2.fg(color(problem.status),`#${problem.index}: ${(problem.error||statusName(problem.status)).split(`
|
|
1511
1511
|
`)[0]}`))}return(lines.length>CARD_ROWS?[...lines.slice(0,CARD_ROWS-1),theme2.fg("dim","\u2026 card shortened; inspect retained details in /bg")]:lines).map(line=>" ".repeat(padding)+truncateToWidth(line,inner,"\u2026")+" ".repeat(padding))}};function renderBackgroundCompletion(message,options,theme2){let view;try{view=completionView(message)}catch{view={body:"The saved notification could not be interpreted. Its original message remains in session history.",truncated:!1}}return new CompletionCard(view,options,theme2)}import{homedir as homedir10}from"node:os";var WIDE_MIN_WIDTH=100,LIST_MIN_WIDTH=28,LIST_MAX_WIDTH=44,NARROW_LIST_MAX_ROWS=7,MIN_RENDER_WIDTH=60,MIN_RENDER_HEIGHT=12,KILL_CONFIRM_TIMEOUT_MS=5e3,DETAIL_LABEL_WIDTH=10,DETAIL_MAX_ROWS=9,COMMAND_MAX_ROWS=3,ERROR_MAX_ROWS=2,DETAIL_VALUE_MAX_ROWS=2,RENDER_CACHE_MAX=8,clean2=text2=>sanitizeBinaryOutput(stripTerminalSequences(text2)),pad=(text2,width)=>truncateToWidth(text2,width,"\u2026",!0),padEnd=(text2,width)=>text2+" ".repeat(Math.max(0,width-visibleWidth(text2))),oneLine=text2=>clean2(text2).replace(/\s+/g," ");function headChars(text2,width){let out="",used=0;for(let char of text2){let charWidth=visibleWidth(char);if(used+charWidth>width)break;out+=char,used+=charWidth}return out}function tailChars(text2,width){let out="",used=0,chars=[...text2];for(let i=chars.length-1;i>=0;i--){let charWidth=visibleWidth(chars[i]);if(used+charWidth>width)break;out=chars[i]+out,used+=charWidth}return out}function ellipsizeMiddle(text2,width){if(visibleWidth(text2)<=width)return text2;if(width<=1)return truncateToWidth(text2,Math.max(1,width),"\u2026");let head=Math.ceil((width-1)/2),tail=width-1-head;return`${headChars(text2,head)}\u2026${tailChars(text2,tail)}`}function displayPath(path14,width){let home=homedir10(),shortened=home&&path14.startsWith(home)?`~${path14.slice(home.length)}`:path14;return ellipsizeMiddle(shortened,width)}var BackgroundTasksMenu=class{constructor(options){this.focused=!1,this.rows=[],this.runningCount=0,this.finishedCount=0,this.completedCount=0,this.failedCount=0,this.hiddenFinished=0,this.disposed=!1,this.focus="list",this.positions=new Map,this.renderCache=new Map,this.busy=!1,this.lastFrame="",this.options=options,this.width=options.tui.terminal.columns,this.sync(),this.unsubscribe=options.host.subscribe(()=>{this.sync()}),this.pollTimer=setInterval(()=>this.queueTick(),options.pollIntervalMs??1e3),this.pollTimer.unref?.(),this.queueTick()}queueTick(){this.tick().catch(()=>{})}invalidate(){this.lastFrame="",this.renderCache.clear()}dispose(){this.disposed||(this.disposed=!0,clearInterval(this.pollTimer),clearInterval(this.animationTimer),this.animationTimer=void 0,this.clearPendingKill(),this.unsubscribe(),this.releasePin?.(),this.positions.clear())}clearPendingKill(){this.pendingKill=void 0,this.pendingKillTimer&&(clearTimeout(this.pendingKillTimer),this.pendingKillTimer=void 0)}current(){return this.rows.find(row=>row.key===this.selected)}wide(){return this.width>=WIDE_MIN_WIDTH}bodyHeight(){return Math.max(6,this.options.tui.terminal.rows-5)}sync(){if(this.disposed)return;let tasks=this.options.host.list(),running=tasks.filter(task=>!isBackgroundTerminal(task.status)).sort((a,b2)=>b2.startedAt-a.startedAt),selectedTask=this.selected?.split("/")[0],settled=tasks.filter(task=>isBackgroundTerminal(task.status)).sort((a,b2)=>(b2.endedAt??b2.startedAt)-(a.endedAt??a.startedAt)),finished=settled.filter(task=>!isForegroundShellTask(task)||task.id===selectedTask);this.runningCount=running.length,this.finishedCount=finished.length,this.completedCount=finished.filter(task=>task.status==="completed").length,this.failedCount=this.finishedCount-this.completedCount,this.hiddenFinished=settled.length-finished.length,this.rows=[...running,...finished].flatMap(task=>[{key:task.id,task},...(task.projection?.workers??[]).map(worker=>({key:`${task.id}/${worker.id}`,task,worker}))]),this.current()||(this.selected=this.rows[0]?.key);let keys=new Set(this.rows.map(row=>row.key));for(let key of this.positions.keys())keys.has(key)||this.positions.delete(key);let id=this.current()?.task.id;if(id!==this.pinned){let release2=id?this.options.host.pin(id):void 0,previous=this.releasePin;this.pinned=id,this.releasePin=release2,previous?.()}this.rows.some(row=>(row.worker?.status??row.task.status)==="running")?this.animationTimer||(this.animationTimer=setInterval(()=>this.options.tui.requestRender(),STATUS_SPINNER_INTERVAL_MS),this.animationTimer.unref?.()):(clearInterval(this.animationTimer),this.animationTimer=void 0)}async tick(){if(this.disposed||(this.sync(),(this.wide()||this.focus==="preview")&&await this.refresh(),this.disposed))return;let frame2=this.render(this.width).join(`
|
|
1512
1512
|
`);frame2!==this.lastFrame&&(this.lastFrame=frame2,this.options.tui.requestRender())}async refresh(){let row=this.current();if(!row||row.worker||row.task.kind!=="bash"||this.busy)return;let position=this.position();if(!(position.output&&(!position.follow||position.output.settled))){this.busy=!0;try{let slice=await this.options.host.read(row.task.id,{mode:"tail",bytes:131072});if(this.disposed||this.selected!==row.key||!position.follow&&position.output)return;position.output={text:clean2(slice.text).split(`
|
|
@@ -1514,10 +1514,10 @@ ${hidden} more records not shown.`:""}${foregroundOmissionNote(foregroundOmitted
|
|
|
1514
1514
|
`),readError:slice.readError?clean2(slice.readError).slice(0,4096):void 0,settled:isBackgroundTerminal(slice.task.status)}}catch(error){!this.disposed&&this.selected===row.key&&(position.follow||!position.output)&&(position.output={text:"",readError:`Cannot read output: ${clean2(String(error)).slice(0,1e3)}`,settled:!1})}finally{this.busy=!1}}}handleInput(data){if(this.disposed)return;let kb=this.options.keybindings;if(this.feedback=void 0,this.pendingKill){let id=this.pendingKill;if(this.clearPendingKill(),data==="y"||data==="Y")try{this.feedback=this.options.host.kill(id)?`stopping ${id}\u2026 (whole group)`:`${id}: no new cancellation requested`}catch(error){this.feedback=oneLine(String(error))}this.options.tui.requestRender();return}if(kb.matches(data,"tui.select.cancel"))if(this.focus==="preview")this.focus="list";else{this.dispose(),this.options.onClose();return}else if(kb.matches(data,"app.backgroundTasks.kill")){let row=this.current();row&&(this.clearPendingKill(),this.pendingKill=row.task.id,this.pendingKillTimer=setTimeout(()=>{this.pendingKill=void 0,this.pendingKillTimer=void 0,this.disposed||this.options.tui.requestRender()},KILL_CONFIRM_TIMEOUT_MS),this.pendingKillTimer.unref?.())}else if(kb.matches(data,"app.backgroundTasks.focusList"))this.focus="list";else if(kb.matches(data,"app.backgroundTasks.focusPreview")||kb.matches(data,"tui.select.confirm"))this.focus="preview",this.queueTick();else{let pageUp=kb.matches(data,this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp"),pageDown=kb.matches(data,this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown"),direction=pageUp||kb.matches(data,"tui.select.up")?-1:pageDown||kb.matches(data,"tui.select.down")?1:0,layout=this.layout(),delta=direction*(pageUp||pageDown?this.focus==="preview"?layout.contentHeight:layout.listVisible:1);if(delta&&this.focus==="preview")this.scrollPreview(delta);else if(delta&&this.rows.length){let index3=this.rows.findIndex(row=>row.key===this.selected),next=pageUp||pageDown?Math.max(0,Math.min(this.rows.length-1,index3+delta)):(index3+delta+this.rows.length)%this.rows.length;this.selected=this.rows[next]?.key,this.sync(),this.queueTick()}}this.options.tui.requestRender()}position(){let key=this.selected??"",position=this.positions.get(key);return position||(position={scroll:0,follow:this.current()?.task.kind==="bash"&&!this.current()?.worker},this.selected&&this.positions.set(key,position)),position}listItems(){let items=[],section="";for(let row of this.rows){let next=isBackgroundTerminal(row.task.status)?"Finished":"Running";next!==section&&(section=next,items.push({header:next})),items.push({row})}return items}cacheSet(key,lines){if(this.renderCache.size>=RENDER_CACHE_MAX){let oldest=this.renderCache.keys().next().value;oldest!==void 0&&this.renderCache.delete(oldest)}this.renderCache.set(key,lines)}commandLines(task,width,maxRows){let first=firstCommandLine(task.command??""),key=`command|${task.id}|${width}|${first.length}`,lines=this.renderCache.get(key);return lines||(lines=wrapTextWithAnsi(highlightCode(first,"bash")[0]??"",Math.max(1,width)),this.cacheSet(key,lines)),lines.slice(0,maxRows)}markdownLines(rowKey,section,text2,width){let key=`${section}|${rowKey}|${width}|${text2.length}`,cached=this.renderCache.get(key);if(cached)return cached;let lines=new Markdown(text2,0,0,getMarkdownTheme(),{color:value2=>this.options.theme.fg("toolOutput",value2)}).render(Math.max(1,width));return this.cacheSet(key,lines),lines}detailLines(row,valueWidth,compact3){if(!row)return[];let{theme:theme2}=this.options,{task,worker}=row,now=Date.now(),marker=statusMarker(worker?.status??task.status,{now}),glyph=theme2.fg(marker.color,marker.glyph),time2=isBackgroundTerminal(task.status)&&task.endedAt?formatAge(task.endedAt,now):runtimeLabel(task,now),field3=(label,values)=>values.map((value2,index3)=>`${theme2.fg("dim",padEnd(index3===0?label:"",DETAIL_LABEL_WIDTH))}${value2}`),status=worker?`${glyph} ${worker.status}`:`${glyph} ${task.status} \xB7 ${task.mode} \xB7 ${time2}${exitSuffix(task.exitCode," \xB7 ")}`;if(compact3){let second=worker?field3("Worker",[truncateToWidth(clean2(worker.label),valueWidth,"\u2026")]):task.command?field3("Command",this.commandLines(task,valueWidth,1)):field3("Task",[truncateToWidth(task.id,valueWidth,"\u2026")]);return[...field3("Status",[status]),...second]}if(worker){let wrap=value2=>wrapTextWithAnsi(value2,Math.max(1,valueWidth)).slice(0,DETAIL_VALUE_MAX_ROWS);return[...field3("Status",[status]),...field3("Worker",[truncateToWidth(clean2(worker.label),valueWidth,"\u2026")]),...field3("Group",[truncateToWidth(task.id,valueWidth,"\u2026")]),...field3("Model",wrap(worker.model??"\u2014")),...field3("Usage",wrap(worker.usage??"\u2014"))]}let readError=this.positions.get(row.key)?.output?.readError,lines=[...field3("Status",[status]),...field3("Task",[truncateToWidth(task.id,valueWidth,"\u2026")]),...field3("Error",[task.error?`Task error: ${oneLine(task.error)}`:"",readError?`Output read error: ${oneLine(readError)}`:""].filter(Boolean).flatMap(error=>wrapTextWithAnsi(theme2.fg("error",error),Math.max(1,valueWidth))).slice(0,ERROR_MAX_ROWS))];return task.kind==="bash"&&(task.command&&lines.push(...field3("Command",this.commandLines(task,valueWidth,COMMAND_MAX_ROWS))),task.cwd&&lines.push(...field3("Directory",[truncateToWidth(displayPath(task.cwd,valueWidth),valueWidth,"\u2026")])),task.outputPath&&lines.push(...field3("Output",[displayPath(task.outputPath,valueWidth)]))),lines.slice(0,DETAIL_MAX_ROWS)}workerLines(row,width){let worker=row.worker;if(!worker)return[];let{theme:theme2}=this.options,heading=text2=>theme2.fg("dim",theme2.bold(text2)),lines=[heading("Prompt"),...this.markdownLines(row.key,"prompt",worker.prompt,width),"",heading("Activity")];for(let line of worker.activity?clean2(worker.activity).split(`
|
|
1515
1515
|
`):["\u2014"])lines.push(theme2.fg("toolOutput",line));return lines.push(""),worker.error&&lines.push(...wrapTextWithAnsi(theme2.fg("error",oneLine(worker.error)),Math.max(1,width)).slice(0,ERROR_MAX_ROWS)),lines.push(heading("Outcome")),worker.report.text?lines.push(...this.markdownLines(row.key,"outcome",worker.report.text,width)):worker.status==="queued"||worker.status==="running"?lines.push(theme2.fg("muted","Still running\u2026")):lines.push(theme2.fg("muted","No report returned.")),worker.report.truncated&&lines.push(theme2.fg("warning","[Saved report truncated.]")),lines}contentLines(row,width){if(!row)return[];let{theme:theme2}=this.options,{task,worker}=row;if(worker)return this.workerLines(row,width);if(task.kind!=="bash"){let workers2=task.projection?.workers??[],now=Date.now();if(workers2.length)return workers2.map(w=>{let marker=statusMarker(w.status,{now}),summary=oneLine(`${w.label} \xB7 ${w.status}${w.description?` \u2014 ${w.description}`:""}`);return`${theme2.fg(marker.color,marker.glyph)} ${theme2.fg("toolOutput",truncateToWidth(summary,Math.max(1,width),"\u2026"))}`});let fallback=task.projection?.text;return fallback?clean2(fallback).split(`
|
|
1516
1516
|
`).map(line=>theme2.fg("toolOutput",line)):[theme2.fg("muted","No workers.")]}let text2=this.positions.get(row.key)?.output?.text??task.projection?.text??"Loading\u2026";return clean2(text2).split(`
|
|
1517
|
-
`).map(line=>theme2.fg("toolOutput",line))}layout(){let wide=this.wide(),listWidth=wide?Math.min(LIST_MAX_WIDTH,Math.max(LIST_MIN_WIDTH,Math.floor((this.width-1)*.36))):this.width,previewWidth=wide?this.width-listWidth-1:this.width,bodyHeight=this.bodyHeight(),items=this.listItems(),selectedIndex=items.findIndex(item=>"row"in item&&item.row.key===this.selected),listVisible=wide?bodyHeight:Math.min(NARROW_LIST_MAX_ROWS,Math.max(1,bodyHeight-4)),listFirst=Math.max(0,selectedIndex-listVisible+1),visibleItems=items.slice(listFirst,listFirst+listVisible),row=this.current(),detail=this.detailLines(row,Math.max(1,previewWidth-DETAIL_LABEL_WIDTH),!wide).slice(0,wide?Math.max(1,Math.min(DETAIL_MAX_ROWS,bodyHeight-2)):2),contentHeight=wide?Math.max(1,bodyHeight-detail.length-1):Math.max(1,bodyHeight-visibleItems.length-detail.length-1),wrapped=this.contentLines(row,previewWidth).flatMap((line,lineIndex)=>{let column=0;return wrapTextWithAnsi(line,Math.max(1,previewWidth)).map(text2=>{let entry={text:text2,line:lineIndex,column};return column+=visibleWidth(text2),entry})}),entries=row?.task.kind==="bash"&&!row.worker?wrapped.slice(-2e3):wrapped.slice(0,2e3),content=entries.map(entry=>entry.text),max=Math.max(0,content.length-contentHeight),position=this.position(),offset=position.scroll;if(position.anchor){let anchor=position.anchor,first=entries.findIndex(entry=>entry.line===anchor.line);if(first>=0)for(offset=first;offset+1<entries.length&&entries[offset+1].line===anchor.line&&entries[offset+1].column<=anchor.column;)offset++}let start=position.follow?max:Math.min(offset,max);return{wide,listWidth,previewWidth,bodyHeight,visibleItems,listVisible,detail,content,contentHeight,start,max,total:content.length,entries}}scrollPreview(delta){let{start,max,entries}=this.layout(),position=this.position(),wasFollowing=position.follow;position.scroll=Math.min(max,Math.max(0,start+delta));let entry=entries[position.scroll];position.anchor=entry?{line:entry.line,column:entry.column}:void 0,position.follow=delta>0&&position.scroll===max&&this.current()?.task.kind==="bash"&&!this.current()?.worker,position.follow&&!wasFollowing&&this.queueTick()}listRowLine(row,width){let{theme:theme2}=this.options,selected=row.key===this.selected,now=Date.now(),marker=statusMarker(row.worker?.status??row.task.status,{now}),glyph=theme2.fg(marker.color,marker.glyph),cursor=selected?theme2.fg(this.focus==="list"?"accent":"muted","\u2192 "):" ",indent=row.worker?" ":"",terminal=isBackgroundTerminal(row.task.status),time2="";if(!row.worker){time2=terminal?formatAge(row.task.endedAt??row.task.startedAt,now):runtimeLabel(row.task,now);let workers2=row.task.projection?.workers;workers2&&workers2.length>0&&(time2=`${workers2.filter(w=>w.status!=="queued"&&w.status!=="running").length}/${workers2.length} \xB7 ${time2}`),row.task.mode==="foreground"&&(time2=`fg \xB7 ${time2}`)}let timeWidth=time2?visibleWidth(time2)+1:0,labelWidth=Math.max(1,width-2-indent.length-visibleWidth(glyph)-1-timeWidth),labelColor=selected&&this.focus==="list"?"accent":"text",label=theme2.fg(labelColor,truncateToWidth(clean2(row.worker?workerLabel(row.worker):taskLabel({command:row.task.command??row.task.title})),labelWidth,"\u2026")),line=`${cursor}${indent}${glyph} ${label}`;return time2&&(line+=" ".repeat(Math.max(1,width-visibleWidth(line)-visibleWidth(time2)))+theme2.fg("dim",time2)),pad(line,width)}emptyLine(width){return this.centered(width,"No background tasks.")}renderTooSmall(width,rows){let{theme:theme2,keybindings}=this.options,rule=()=>new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",message=`Terminal too small for /bg \u2014 resize to at least ${MIN_RENDER_WIDTH}\xD7${MIN_RENDER_HEIGHT}.`,bodyHeight=Math.max(1,rows-4),body=Array.from({length:bodyHeight},()=>pad("",width));body[Math.floor(bodyHeight/2)]=this.centered(width,message);let closeHint=pad(theme2.fg("dim",`${keyLabel("tui.select.cancel",{keybindings})} close`),width);return[rule(),...body,rule(),closeHint,rule()]}centered(width,message){let leftPad=Math.max(0,Math.floor((width-visibleWidth(message))/2));return pad(this.options.theme.fg("muted",`${" ".repeat(leftPad)}${message}`),width)}dividerLine(layout){let{theme:theme2}=this.options,row=this.current(),label=row?row.worker?"Worker":row.task.kind==="bash"?"Output":"Workers":"Output",styledLabel=theme2.fg(this.focus==="preview"?"accent":"muted",label),suffix=row!==void 0&&row.task.kind==="bash"&&!row.worker?theme2.fg("muted",` \xB7 tail \xB7 ${this.position().follow?"following":"browsing"}`):"",range2=theme2.fg("muted",`${layout.total?layout.start+1:0}\u2013${Math.min(layout.start+layout.contentHeight,layout.total)}/${layout.total}`),rule=count=>theme2.fg("borderMuted","\u2500".repeat(Math.max(0,count))),left=`${rule(1)} ${styledLabel}${suffix} `,right=` ${range2} ${rule(1)}`,fill=layout.previewWidth-visibleWidth(left)-visibleWidth(right);return pad(`${left}${rule(fill)}${right}`,layout.previewWidth)}render(width){if(width<1)return[];let terminalRows=this.options.tui.terminal.rows;if(width<MIN_RENDER_WIDTH||terminalRows<MIN_RENDER_HEIGHT)return this.renderTooSmall(width,terminalRows);let wasWide=this.wide();this.width=width,!wasWide&&this.wide()&&this.queueTick();let{theme:theme2,keybindings}=this.options,layout=this.layout(),rule=()=>new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",title=theme2.fg("accent",theme2.bold("Background tasks")),segments=[];this.runningCount>0&&segments.push(theme2.fg("accent",`${this.runningCount} running`)),this.completedCount>0&&segments.push(theme2.fg("muted",`${this.completedCount} completed`)),this.failedCount>0&&segments.push(theme2.fg("error",`${this.failedCount} failed`)),this.hiddenFinished>0&&segments.push(theme2.fg("muted",`${this.hiddenFinished} foreground shell${this.hiddenFinished===1?"":"s"} hidden`));let stats=segments.join(theme2.fg("muted"," \xB7 ")),gap=width-visibleWidth(title)-visibleWidth(stats),titleLine=pad(stats&&gap>=1?`${title}${" ".repeat(gap)}${stats}`:title,width),hint2=id=>keyLabel(id,{keybindings}),pageUp=this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp",pageDown=this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown",hints=[`${hint2("tui.select.up")}/${hint2("tui.select.down")} select`,`${hint2("app.backgroundTasks.focusList")} list`,`${hint2("app.backgroundTasks.focusPreview")}/${hint2("tui.select.confirm")} output`,`${hint2(pageUp)}/${hint2(pageDown)} page`,`${hint2("app.backgroundTasks.kill")} stop`,`${hint2("tui.select.cancel")} close`].join(" \xB7 "),hintLine=pad(this.pendingKill?theme2.fg("warning",`Stop ${this.pendingKill} (whole group)? y/N`):theme2.fg(this.feedback?"muted":"dim",this.feedback??hints),width),leftLines=layout.visibleItems.length?layout.visibleItems.map(item=>"header"in item?pad(theme2.fg("dim",item.header),layout.listWidth):this.listRowLine(item.row,layout.listWidth)):[this.emptyLine(layout.listWidth)],contentWindow=layout.content.slice(layout.start,layout.start+layout.contentHeight),divider=this.dividerLine(layout),body=[];if(layout.wide){let right=[...layout.detail,divider,...contentWindow];for(let i=0;i<layout.bodyHeight;i++)body.push(pad(`${pad(leftLines[i]??"",layout.listWidth)}${theme2.fg("borderMuted","\u2502")}${pad(right[i]??"",layout.previewWidth)}`,width))}else for(body.push(...[...leftLines,...layout.detail,divider,...contentWindow].map(line=>pad(line,width)));body.length<layout.bodyHeight;)body.push(pad("",width));return[rule(),titleLine,...body.slice(0,layout.bodyHeight),rule(),hintLine,rule()].map(line=>pad(line,width))}};var COMMAND_PREVIEW_LIMIT=120,LABELLED_COMMAND_LIMIT=40,NOTIFY_TAIL_LIMIT=4e3,RESULT_EXPAND_LIMIT=4e3,WAIT_REFRESH_MS=1e3;function scheduleWaitRefresh(context,pending){let state2=context.state;if(state2!==void 0){if(pending){state2.dispose=()=>scheduleWaitRefresh(context,!1),state2.refreshTimer===void 0&&(state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,context.invalidate()},WAIT_REFRESH_MS),state2.refreshTimer.unref?.());return}state2.refreshTimer!==void 0&&(clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0),state2.waitStartedAt=void 0}}function bgPrompt(theme2){return theme2.fg("toolTitle",theme2.bold("$ "))}function timeoutSuffix(timeout,theme2){return timeout?theme2.fg("muted",` (timeout ${timeout}s)`):""}function capForTranscript(text2,limit){return text2.length>limit?`\u2026${text2.slice(-limit)}`:text2}function renderBgCall(args,theme2,context){switch(args.action){case"create":{let command=args.command;return typeof command=="string"?renderCreateCall(command,args,theme2,context):new Text(theme2.fg("toolTitle",theme2.bold("bg create")),0,0)}case"read":{let mode=args.mode??"tail",size=args.bytes!==void 0?` ${formatSize(args.bytes)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg read "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",` ${mode}${size}`)}`,0,0)}case"wait":return renderWaitCall(args,theme2,context);case"kill":return new Text(`${theme2.fg("toolTitle",theme2.bold("bg kill "))}${theme2.fg("accent",args.taskId??"")}`,0,0);case"list":return new Text(theme2.fg("toolTitle",theme2.bold("bg list")),0,0);default:{let action=typeof args.action=="string"?` ${theme2.fg("dim",args.action)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg"))}${action}`,0,0)}}}function renderWaitCall(args,theme2,context){let taskId=typeof args.taskId=="string"?args.taskId.trim():"",pending=context.executionStarted===!0&&context.isPartial===!0&&context.state!==void 0&&taskId.length>0;if(scheduleWaitRefresh(context,pending),!pending){let ms=args.waitMs!==void 0?` ${formatDuration(clampWaitMs(args.waitMs))}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg wait "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",ms)}`,0,0)}let state2=context.state;state2.waitStartedAt===void 0&&(state2.waitStartedAt=Date.now());let elapsed2=`waiting ${formatDuration(Date.now()-state2.waitStartedAt)}/${formatDuration(clampWaitMs(args.waitMs))}`;return new Text(`${theme2.fg("toolTitle",theme2.bold("bg wait "))}${theme2.fg("accent",taskId)} ${theme2.fg("muted",elapsed2)}`,0,0)}function renderCreateCall(command,args,theme2,context){let lines=command.split(/\r?\n/).filter(line=>line.trim().length>0),label=args.description?theme2.fg("muted",` \xB7 ${args.description}`):"",suffix=theme2.fg("muted"," &")+timeoutSuffix(args.timeout,theme2)+label;if(context.expanded&&lines.length>1){let body2=highlightCode(command,"bash").join(`
|
|
1517
|
+
`).map(line=>theme2.fg("toolOutput",line))}layout(){let wide=this.wide(),listWidth=wide?Math.min(LIST_MAX_WIDTH,Math.max(LIST_MIN_WIDTH,Math.floor((this.width-1)*.36))):this.width,previewWidth=wide?this.width-listWidth-1:this.width,bodyHeight=this.bodyHeight(),items=this.listItems(),selectedIndex=items.findIndex(item=>"row"in item&&item.row.key===this.selected),listVisible=wide?bodyHeight:Math.min(NARROW_LIST_MAX_ROWS,Math.max(1,bodyHeight-4)),listFirst=Math.max(0,selectedIndex-listVisible+1),visibleItems=items.slice(listFirst,listFirst+listVisible),row=this.current(),detail=this.detailLines(row,Math.max(1,previewWidth-DETAIL_LABEL_WIDTH),!wide).slice(0,wide?Math.max(1,Math.min(DETAIL_MAX_ROWS,bodyHeight-2)):2),contentHeight=wide?Math.max(1,bodyHeight-detail.length-1):Math.max(1,bodyHeight-visibleItems.length-detail.length-1),wrapped=this.contentLines(row,previewWidth).flatMap((line,lineIndex)=>{let column=0;return wrapTextWithAnsi(line,Math.max(1,previewWidth)).map(text2=>{let entry={text:text2,line:lineIndex,column};return column+=visibleWidth(text2),entry})}),entries=row?.task.kind==="bash"&&!row.worker?wrapped.slice(-2e3):wrapped.slice(0,2e3),content=entries.map(entry=>entry.text),max=Math.max(0,content.length-contentHeight),position=this.position(),offset=position.scroll;if(position.anchor){let anchor=position.anchor,first=entries.findIndex(entry=>entry.line===anchor.line);if(first>=0)for(offset=first;offset+1<entries.length&&entries[offset+1].line===anchor.line&&entries[offset+1].column<=anchor.column;)offset++}let start=position.follow?max:Math.min(offset,max);return{wide,listWidth,previewWidth,bodyHeight,visibleItems,listVisible,detail,content,contentHeight,start,max,total:content.length,entries}}scrollPreview(delta){let{start,max,entries}=this.layout(),position=this.position(),wasFollowing=position.follow;position.scroll=Math.min(max,Math.max(0,start+delta));let entry=entries[position.scroll];position.anchor=entry?{line:entry.line,column:entry.column}:void 0,position.follow=delta>0&&position.scroll===max&&this.current()?.task.kind==="bash"&&!this.current()?.worker,position.follow&&!wasFollowing&&this.queueTick()}listRowLine(row,width){let{theme:theme2}=this.options,selected=row.key===this.selected,now=Date.now(),marker=statusMarker(row.worker?.status??row.task.status,{now}),glyph=theme2.fg(marker.color,marker.glyph),cursor=selected?theme2.fg(this.focus==="list"?"accent":"muted","\u2192 "):" ",indent=row.worker?" ":"",terminal=isBackgroundTerminal(row.task.status),time2="";if(!row.worker){time2=terminal?formatAge(row.task.endedAt??row.task.startedAt,now):runtimeLabel(row.task,now);let workers2=row.task.projection?.workers;workers2&&workers2.length>0&&(time2=`${workers2.filter(w=>w.status!=="queued"&&w.status!=="running").length}/${workers2.length} \xB7 ${time2}`),row.task.mode==="foreground"&&(time2=`fg \xB7 ${time2}`)}let timeWidth=time2?visibleWidth(time2)+1:0,labelWidth=Math.max(1,width-2-indent.length-visibleWidth(glyph)-1-timeWidth),labelColor=selected&&this.focus==="list"?"accent":"text",label=theme2.fg(labelColor,truncateToWidth(clean2(row.worker?workerLabel(row.worker):taskLabel({command:row.task.command??row.task.title})),labelWidth,"\u2026")),line=`${cursor}${indent}${glyph} ${label}`;return time2&&(line+=" ".repeat(Math.max(1,width-visibleWidth(line)-visibleWidth(time2)))+theme2.fg("dim",time2)),pad(line,width)}emptyLine(width){return this.centered(width,"No background tasks.")}renderTooSmall(width,rows){let{theme:theme2,keybindings}=this.options,rule=()=>new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",message=`Terminal too small for /bg \u2014 resize to at least ${MIN_RENDER_WIDTH}\xD7${MIN_RENDER_HEIGHT}.`,bodyHeight=Math.max(1,rows-4),body=Array.from({length:bodyHeight},()=>pad("",width));body[Math.floor(bodyHeight/2)]=this.centered(width,message);let closeHint=pad(theme2.fg("dim",`${keyLabel("tui.select.cancel",{keybindings})} close`),width);return[rule(),...body,rule(),closeHint,rule()]}centered(width,message){let leftPad=Math.max(0,Math.floor((width-visibleWidth(message))/2));return pad(this.options.theme.fg("muted",`${" ".repeat(leftPad)}${message}`),width)}dividerLine(layout){let{theme:theme2}=this.options,row=this.current(),label=row?row.worker?"Worker":row.task.kind==="bash"?"Output":"Workers":"Output",styledLabel=theme2.fg(this.focus==="preview"?"accent":"muted",label),suffix=row!==void 0&&row.task.kind==="bash"&&!row.worker?theme2.fg("muted",` \xB7 tail \xB7 ${this.position().follow?"following":"browsing"}`):"",range2=theme2.fg("muted",`${layout.total?layout.start+1:0}\u2013${Math.min(layout.start+layout.contentHeight,layout.total)}/${layout.total}`),rule=count=>theme2.fg("borderMuted","\u2500".repeat(Math.max(0,count))),left=`${rule(1)} ${styledLabel}${suffix} `,right=` ${range2} ${rule(1)}`,fill=layout.previewWidth-visibleWidth(left)-visibleWidth(right);return pad(`${left}${rule(fill)}${right}`,layout.previewWidth)}render(width){if(width<1)return[];let terminalRows=this.options.tui.terminal.rows;if(width<MIN_RENDER_WIDTH||terminalRows<MIN_RENDER_HEIGHT)return this.renderTooSmall(width,terminalRows);let wasWide=this.wide();this.width=width,!wasWide&&this.wide()&&this.queueTick();let{theme:theme2,keybindings}=this.options,layout=this.layout(),rule=()=>new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",title=theme2.fg("accent",theme2.bold("Background tasks")),segments=[];this.runningCount>0&&segments.push(theme2.fg("accent",`${this.runningCount} running`)),this.completedCount>0&&segments.push(theme2.fg("muted",`${this.completedCount} completed`)),this.failedCount>0&&segments.push(theme2.fg("error",`${this.failedCount} failed`)),this.hiddenFinished>0&&segments.push(theme2.fg("muted",`${this.hiddenFinished} foreground shell${this.hiddenFinished===1?"":"s"} hidden`));let stats=segments.join(theme2.fg("muted"," \xB7 ")),gap=width-visibleWidth(title)-visibleWidth(stats),titleLine=pad(stats&&gap>=1?`${title}${" ".repeat(gap)}${stats}`:title,width),hint2=id=>keyLabel(id,{keybindings}),pageUp=this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp",pageDown=this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown",hints=[`${hint2("tui.select.up")}/${hint2("tui.select.down")} select`,`${hint2("app.backgroundTasks.focusList")} list`,`${hint2("app.backgroundTasks.focusPreview")}/${hint2("tui.select.confirm")} output`,`${hint2(pageUp)}/${hint2(pageDown)} page`,`${hint2("app.backgroundTasks.kill")} stop`,`${hint2("tui.select.cancel")} close`].join(" \xB7 "),hintLine=pad(this.pendingKill?theme2.fg("warning",`Stop ${this.pendingKill} (whole group)? y/N`):theme2.fg(this.feedback?"muted":"dim",this.feedback??hints),width),leftLines=layout.visibleItems.length?layout.visibleItems.map(item=>"header"in item?pad(theme2.fg("dim",item.header),layout.listWidth):this.listRowLine(item.row,layout.listWidth)):[this.emptyLine(layout.listWidth)],contentWindow=layout.content.slice(layout.start,layout.start+layout.contentHeight),divider=this.dividerLine(layout),body=[];if(layout.wide){let right=[...layout.detail,divider,...contentWindow];for(let i=0;i<layout.bodyHeight;i++)body.push(pad(`${pad(leftLines[i]??"",layout.listWidth)}${theme2.fg("borderMuted","\u2502")}${pad(right[i]??"",layout.previewWidth)}`,width))}else for(body.push(...[...leftLines,...layout.detail,divider,...contentWindow].map(line=>pad(line,width)));body.length<layout.bodyHeight;)body.push(pad("",width));return[rule(),titleLine,...body.slice(0,layout.bodyHeight),rule(),hintLine,rule()].map(line=>pad(line,width))}};var COMMAND_PREVIEW_LIMIT=120,LABELLED_COMMAND_LIMIT=40,NOTIFY_TAIL_LIMIT=4e3,RESULT_EXPAND_LIMIT=4e3,WAIT_REFRESH_MS=1e3;function scheduleWaitRefresh(context,pending){let state2=context.state;if(state2!==void 0){if(pending){state2.dispose=()=>scheduleWaitRefresh(context,!1),state2.refreshTimer===void 0&&(state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,context.invalidate()},WAIT_REFRESH_MS),state2.refreshTimer.unref?.());return}state2.refreshTimer!==void 0&&(clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0),state2.waitStartedAt=void 0}}function bgPrompt(theme2){return theme2.fg("toolTitle",theme2.bold("$ "))}function timeoutSuffix(timeout,theme2){return timeout?theme2.fg("muted",` (timeout ${timeout}s)`):""}function capForTranscript(text2,limit){return text2.length>limit?`\u2026${text2.slice(-limit)}`:text2}function renderBgCall(args,theme2,context){switch(args.action){case"create":{let command=args.command;return typeof command=="string"?renderCreateCall(command,args,theme2,context):new Text(theme2.fg("toolTitle",theme2.bold("bg create")),0,0)}case"read":{let mode=args.mode??"tail",size=args.bytes!==void 0?` ${formatSize(args.bytes)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg read "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",` ${mode}${size}`)}`,0,0)}case"wait":return renderWaitCall(args,theme2,context);case"kill":return new Text(`${theme2.fg("toolTitle",theme2.bold("bg kill "))}${theme2.fg("accent",args.taskId??"")}`,0,0);case"list":return new Text(theme2.fg("toolTitle",theme2.bold("bg list")),0,0);default:{let action=typeof args.action=="string"?` ${theme2.fg("dim",args.action)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg"))}${action}`,0,0)}}}function renderWaitCall(args,theme2,context){let taskId=typeof args.taskId=="string"?args.taskId.trim():"",pending=context.executionStarted===!0&&context.isPartial===!0&&context.state!==void 0&&taskId.length>0;if(scheduleWaitRefresh(context,pending),!pending){let ms=args.waitMs!==void 0?` ${formatDuration2(clampWaitMs(args.waitMs))}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("bg wait "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",ms)}`,0,0)}let state2=context.state;state2.waitStartedAt===void 0&&(state2.waitStartedAt=Date.now());let elapsed2=`waiting ${formatDuration2(Date.now()-state2.waitStartedAt)}/${formatDuration2(clampWaitMs(args.waitMs))}`;return new Text(`${theme2.fg("toolTitle",theme2.bold("bg wait "))}${theme2.fg("accent",taskId)} ${theme2.fg("muted",elapsed2)}`,0,0)}function renderCreateCall(command,args,theme2,context){let lines=command.split(/\r?\n/).filter(line=>line.trim().length>0),label=args.description?theme2.fg("muted",` \xB7 ${args.description}`):"",suffix=theme2.fg("muted"," &")+timeoutSuffix(args.timeout,theme2)+label;if(context.expanded&&lines.length>1){let body2=highlightCode(command,"bash").join(`
|
|
1518
1518
|
`);return new Text(`${bgPrompt(theme2)}${body2}${suffix}`,0,0)}let body=highlightCode(firstCommandLine(command),"bash").join(`
|
|
1519
|
-
`);if(lines.length>1){let hidden=lines.length-1,more=theme2.fg("muted",` (+${hidden} line${hidden===1?"":"s"})`);return new Text(`${bgPrompt(theme2)}${body}${suffix}${more}`,0,0)}return new Text(`${bgPrompt(theme2)}${body}${suffix}`,0,0)}function renderBgResult(result2,options,theme2,context){context.args?.action==="wait"&&!options.isPartial&&scheduleWaitRefresh(context,!1);let details=result2.details;if(context.isError||!details){let text2=result2.content.find(part=>part.type==="text")?.text??"";return new Text(theme2.fg("toolOutput",text2.trimEnd()),0,0)}let container=new Container;if(container.addChild(new TruncatedText(resultSummaryLine(details,theme2,options.expanded),1,0)),options.expanded){let text2=result2.content.find(part=>part.type==="text")?.text??"";container.addChild(new Text("",0,0)),container.addChild(new Text(theme2.fg("toolOutput",capForTranscript(text2,RESULT_EXPAND_LIMIT).trimEnd()),1,0))}return container}function resultSummaryLine(details,theme2,expanded){let shownPath=path14=>expanded?path14:fileNameOf(path14);switch(details.action){case"create":{let label=details.description?` (${details.description})`:"";return`${theme2.fg("muted","\u2192 task ")}${theme2.fg("accent",`${details.taskId}${label}`)}${theme2.fg("muted",` started \xB7 ${shownPath(details.outputPath)}`)}`}case"read":{let size=details.sliceBytes!==details.totalBytes?`${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`:formatSize(details.totalBytes);return`${theme2.fg("muted","\u2192 ")}${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` ${size} \xB7 ${shownPath(details.outputPath)}`)}`}case"wait":{if(details.timedOut)return`${theme2.fg(statusColor(details.status),statusGlyph(details.status))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` still running \xB7 waited ${
|
|
1520
|
-
[showing tail of ${formatSize(details.totalBytes)} bytes; full output: ${details.outputPath}]`:"";container.addChild(new Text(`${theme2.fg("toolOutput",tail.trimEnd())}${theme2.fg("muted",truncatedNote)}`,1,0))}return details.stalled&&options.expanded&&container.addChild(new Text(theme2.fg("warning","Blocked on interactive input \u2014 kill (bg action kill) and re-run with piped input or a non-interactive flag."),1,0)),container}function createBackgroundExtension(){return pi=>{let unsubscribe,unsubscribeDetachKey,closeMenu;pi.on("session_start",(_event,ctx)=>{unsubscribe?.(),unsubscribeDetachKey?.();let update=()=>{let
|
|
1519
|
+
`);if(lines.length>1){let hidden=lines.length-1,more=theme2.fg("muted",` (+${hidden} line${hidden===1?"":"s"})`);return new Text(`${bgPrompt(theme2)}${body}${suffix}${more}`,0,0)}return new Text(`${bgPrompt(theme2)}${body}${suffix}`,0,0)}function renderBgResult(result2,options,theme2,context){context.args?.action==="wait"&&!options.isPartial&&scheduleWaitRefresh(context,!1);let details=result2.details;if(context.isError||!details){let text2=result2.content.find(part=>part.type==="text")?.text??"";return new Text(theme2.fg("toolOutput",text2.trimEnd()),0,0)}let container=new Container;if(container.addChild(new TruncatedText(resultSummaryLine(details,theme2,options.expanded),1,0)),options.expanded){let text2=result2.content.find(part=>part.type==="text")?.text??"";container.addChild(new Text("",0,0)),container.addChild(new Text(theme2.fg("toolOutput",capForTranscript(text2,RESULT_EXPAND_LIMIT).trimEnd()),1,0))}return container}function resultSummaryLine(details,theme2,expanded){let shownPath=path14=>expanded?path14:fileNameOf(path14);switch(details.action){case"create":{let label=details.description?` (${details.description})`:"";return`${theme2.fg("muted","\u2192 task ")}${theme2.fg("accent",`${details.taskId}${label}`)}${theme2.fg("muted",` started \xB7 ${shownPath(details.outputPath)}`)}`}case"read":{let size=details.sliceBytes!==details.totalBytes?`${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`:formatSize(details.totalBytes);return`${theme2.fg("muted","\u2192 ")}${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` ${size} \xB7 ${shownPath(details.outputPath)}`)}`}case"wait":{if(details.timedOut)return`${theme2.fg(statusColor(details.status),statusGlyph(details.status))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` still running \xB7 waited ${formatDuration2(details.waitedMs)} \xB7 ${formatSize(details.totalBytes)}`)}`;let exit=exitSuffix(details.exitCode,", ");return`${theme2.fg(statusColor(details.status),statusGlyph(details.status))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` ${details.status}${exit} \xB7 waited ${formatDuration2(details.waitedMs)} \xB7 +${formatSize(details.deltaBytes)}`)}`}case"kill":return`${theme2.fg(statusColor("killed"),statusGlyph("killed"))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",details.requested===void 0?" stopped":details.requested?" cancellation requested":` ${details.status??"unchanged"}`)}`;case"list":{let hidden=details.hidden>0?` \xB7 ${details.hidden} more finished`:"",omitted=details.foregroundOmitted?` \xB7 ${details.foregroundOmitted} foreground omitted`:"";return theme2.fg("muted",`${details.running} running \xB7 ${details.finished} finished${hidden}${omitted}`)}}}function taskSummaryLine(details,theme2){let runtime=formatDuration2(details.runtimeMs),label=details.description?`${details.description} (${commandLabel(details.command,LABELLED_COMMAND_LIMIT)})`:commandLabel(details.command,COMMAND_PREVIEW_LIMIT);if(details.stalled)return`${theme2.fg("warning",statusGlyph(details.status,!0))} ${theme2.fg("accent",details.taskId)} ${label} ${theme2.fg("muted",`\u2014 waiting for input (${runtime})`)}`;let outcome=theme2.fg(statusColor(details.status),`${details.status}${exitSuffix(details.exitCode,", ")} in ${runtime}`);return`${theme2.fg(statusColor(details.status),statusGlyph(details.status))} ${theme2.fg("accent",details.taskId)} ${label} ${theme2.fg("muted",`\u2014 ${outcome}`)}`}function renderBackgroundNotification(message,options,theme2){let details=message.details;if(!details||typeof details.taskId!="string")return;let container=new Container;container.addChild(new TruncatedText(taskSummaryLine(details,theme2),1,0));let shownPath=options.expanded?details.outputPath:fileNameOf(details.outputPath);if(container.addChild(new Text(theme2.fg("muted",shownPath),1,0)),details.tailError)container.addChild(new Text(theme2.fg("error",`Output unavailable: ${details.tailError}`),1,0));else if(options.expanded&&details.tailText){container.addChild(new Text("",0,0));let tail=capForTranscript(details.tailText,NOTIFY_TAIL_LIMIT),truncatedNote=details.tailTruncated?`
|
|
1520
|
+
[showing tail of ${formatSize(details.totalBytes)} bytes; full output: ${details.outputPath}]`:"";container.addChild(new Text(`${theme2.fg("toolOutput",tail.trimEnd())}${theme2.fg("muted",truncatedNote)}`,1,0))}return details.stalled&&options.expanded&&container.addChild(new Text(theme2.fg("warning","Blocked on interactive input \u2014 kill (bg action kill) and re-run with piped input or a non-interactive flag."),1,0)),container}function createBackgroundExtension(){return pi=>{let unsubscribe,unsubscribeDetachKey,closeMenu,hintTimer;pi.on("session_start",(_event,ctx)=>{unsubscribe?.(),unsubscribeDetachKey?.();let update=()=>{clearTimeout(hintTimer),hintTimer=void 0;let all=ctx.background.list(),tasks=all.filter(task=>task.mode==="background"),running=tasks.filter(task=>!isBackgroundTerminal(task.status)).length,parts=[];tasks.length&&parts.push(`bg ${running} active \xB7 ${tasks.length-running} finished`);let detachKey=keyLabel("app.backgroundTasks.detach"),now=Date.now(),movable=all.filter(task=>task.mode==="foreground"&&(task.status==="running"||task.status==="queued")),waits=movable.map(task=>task.startedAt+1e4-now).filter(wait=>wait>0);detachKey&&movable.length>waits.length&&parts.push(`${detachKey} to background`),detachKey&&waits.length>0&&(hintTimer=setTimeout(update,Math.min(...waits)),hintTimer.unref?.()),ctx.ui.setStatus("background",parts.length?parts.join(" \xB7 "):void 0)};unsubscribe=ctx.background.subscribe(update),unsubscribeDetachKey=ctx.ui.onTerminalInput(data=>{if(!getKeybindings().matches(data,"app.backgroundTasks.detach"))return;let count=ctx.background.detachForeground();if(count!==0)return ctx.ui.notify(`Moved ${count} execution${count===1?"":"s"} to the background. Use /bg to manage tasks.`),{consume:!0}}),update()}),pi.on("session_shutdown",(_event,ctx)=>{unsubscribe?.(),unsubscribe=void 0,unsubscribeDetachKey?.(),unsubscribeDetachKey=void 0,clearTimeout(hintTimer),hintTimer=void 0,closeMenu?.(),closeMenu=void 0,ctx.ui.setStatus("background",void 0)}),pi.registerTool({name:"bg",label:"bg",description:BG_TOOL_DESCRIPTION,promptSnippet:BG_PROMPT_SNIPPET,promptGuidelines:BG_PROMPT_GUIDELINES,parameters:bgSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_id,params,signal,_onUpdate,ctx){try{switch(params.action){case"read":return await runRead(ctx.background,params);case"wait":return await runWait(ctx.background,params,signal);case"kill":return runKill(ctx.background,params);case"list":return runList(ctx.background)}}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(boundedText(message))}},renderCall:renderBgCall,renderResult:renderBgResult}),pi.registerMessageRenderer(BG_NOTIFICATION_TYPE,renderBackgroundNotification),pi.registerMessageRenderer(BG_COMPLETION_TYPE,renderBackgroundCompletion),pi.registerCommand("bg",{description:"View and manage Bash tasks and Subagent groups",handler:async(_args,ctx)=>{if(ctx.mode!=="tui"){ctx.ui.notify(boundedText(ctx.background.list().filter(task=>task.mode==="background").slice(0,10).map(task=>describeTaskLine(task)).join(`
|
|
1521
1521
|
`))||"No background tasks.","info");return}closeMenu?.(),await ctx.ui.custom((tui,theme2,keybindings,done)=>{let close=()=>{closeMenu===close&&(closeMenu=void 0),done()};return closeMenu=close,new BackgroundTasksMenu({tui,theme:theme2,keybindings,host:ctx.background,onClose:close})},{overlay:!0,overlayOptions:{anchor:"center",width:"100%",maxHeight:"100%"}})}})}}var background_default=createBackgroundExtension();registerKeybindings({"app.btw.close":{defaultKeys:"escape",description:"Close the BTW conversation"},"app.btw.cancel":{defaultKeys:"ctrl+c",description:"Stop the BTW answer, or close when idle"},"app.btw.scrollUp":{defaultKeys:"up",description:"Scroll BTW up when the editor is empty"},"app.btw.scrollDown":{defaultKeys:"down",description:"Scroll BTW down when the editor is empty"}});var TOOL_DENIAL="Tools are unavailable in this BTW conversation. Answer using the inherited context only.",UNKNOWN_TOOL_RESULT="This tool had not returned a result when the BTW context snapshot was captured. Its outcome is unknown here; the original task may still be running.",BTW_REMINDER=`<btw-reminder>
|
|
1522
1522
|
This is a separate side conversation about the preceding context. Answer the user's side questions without continuing or changing the original task. The original task may still be running; later activity is not part of this snapshot.
|
|
1523
1523
|
Tool definitions are retained for prompt-cache reuse, but tools cannot be executed here. Use only the available context, and say when it does not contain the answer.
|
|
@@ -1563,7 +1563,7 @@ File: ${normalized}`}}if(disk.exists){let validationError=(await ModelConfig.loa
|
|
|
1563
1563
|
`;await writeFile2(tempPath,candidate,{encoding:"utf8",mode:384});let validationError=(await ModelConfig.load(tempPath)).getError();if(validationError)return{kind:"invalid",error:validationError};let latest=await readDocument(this.path);if(latest.exists!==disk.exists||latest.rawText!==disk.rawText)throw new Error("models.json changed while saving; the edits were kept for retry.");return!this.backedUp&&disk.exists&&disk.rawText!==void 0&&(await writeFile2(`${this.path}.bak`,disk.rawText,{encoding:"utf8",mode:384}),this.backedUp=!0),assertLock(),await rename(tempPath,this.path),this.baseline=working,settle(),{kind:"saved",applied:batch.length}}finally{await rm(tempPath,{force:!0}).catch(()=>{})}}};function ensureProvider(doc,providerId){let existing=Object.hasOwn(doc.providers,providerId)?doc.providers[providerId]:void 0;if(existing)return existing;let created={};return Object.defineProperty(doc.providers,providerId,{value:created,writable:!0,enumerable:!0,configurable:!0}),created}function applyOp(doc,op){switch(op.kind){case"set":{let provider=ensureProvider(doc,op.providerId);if(op.modelId===void 0){setPath(provider,op.path,op.value);return}let model=(Array.isArray(provider.models)?provider.models:[]).find(entry=>entry.id===op.modelId);model&&setPath(model,op.path,op.value);return}case"addModel":{let provider=ensureProvider(doc,op.providerId),models=Array.isArray(provider.models)?provider.models:[],index3=models.findIndex(entry=>entry.id===op.model.id),clone=structuredClone(op.model);index3>=0?models[index3]=clone:models.push(clone),provider.models=models;return}case"removeModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!provider||!models)return;provider.models=models.filter(entry=>entry.id!==op.modelId);return}case"renameModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!models)return;let model=models.find(entry=>entry.id===op.oldId);model&&!models.some(entry=>entry.id===op.newId)&&(model.id=op.newId);return}case"removeProvider":{delete doc.providers[op.providerId];return}}}function pruneEmptyNewProviders(working,disk){for(let[providerId,provider]of Object.entries(working.providers))Object.hasOwn(disk.providers,providerId)||isPlainObject(provider)&&Object.keys(provider).length===0&&delete working.providers[providerId]}var RefreshCoordinator=class{constructor(runtime){this.pending=new Map,this.changed=new Set,this.revision=0,this.runtime=runtime}touch(providerId){this.pending.set(providerId,++this.revision),this.changed.add(providerId)}get touchedProviders(){return[...this.changed]}async refreshNow(providerId,signal){return this.run([providerId],signal)}async flush(signal){let providers=[...this.pending.keys()];return providers.length===0?{ok:!0,aborted:!1,errors:[]}:this.run(providers,signal)}async run(providers,signal){let revisions=new Map(providers.map(id=>[id,this.pending.get(id)])),combined=AbortSignal.any([...signal?[signal]:[],AbortSignal.timeout(REFRESH_TIMEOUT_MS)]),errors=[];try{let result2=await this.runtime.refresh({allowNetwork:!1,providers,signal:combined});for(let[providerId,error]of result2.errors)errors.push(`${providerId}: ${formatError(error)}`);let configError=this.runtime.getError();configError&&errors.push(configError);let aborted=result2.aborted||combined.aborted;aborted&&errors.length===0&&errors.push("Refresh was cancelled or timed out.");let ok2=errors.length===0&&!aborted;if(ok2)for(let id of providers)this.pending.get(id)===revisions.get(id)&&this.pending.delete(id);return{ok:ok2,aborted,errors}}catch(error){return errors.push(formatError(error)),{ok:!1,aborted:combined.aborted,errors}}}};function registerListKeybindings(){registerKeybindings({"app.list.toggle":{defaultKeys:"space",description:"Toggle selected list item"}})}registerListKeybindings();registerKeybindings({"app.provider.switchPaneLeft":{defaultKeys:"left",description:"/provider: focus the left pane"},"app.provider.switchPaneRight":{defaultKeys:"right",description:"/provider: focus the right pane"},"app.provider.removeEntry":{defaultKeys:"ctrl+x",description:"/provider: remove the selected compat or dictionary entry"}});async function probeProviderModels(opts){let baseUrl;try{baseUrl=new URL(opts.baseUrl)}catch{return{ok:!1,error:"Base URL is not a valid URL."}}if(baseUrl.protocol!=="http:"&&baseUrl.protocol!=="https:")return{ok:!1,error:`Unsupported protocol: ${baseUrl.protocol}`};if(baseUrl.username||baseUrl.password||baseUrl.hash)return{ok:!1,error:"Base URL must not contain credentials or a fragment."};if(opts.signal?.aborted)return{ok:!1,error:"Cancelled."};let controller=new AbortController,timeoutMs=opts.timeoutMs??PROBE_LIMITS.timeoutMs,timer=setTimeout(()=>controller.abort(),timeoutMs),onOuterAbort=()=>controller.abort();opts.signal?.addEventListener("abort",onOuterAbort,{once:!0});let doFetch=opts.fetch??globalThis.fetch,getPage=async(url,headers)=>{let response=await doFetch(url,{method:"GET",headers,signal:controller.signal});if(!response.ok){let body=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxErrorBytes,signal:controller.signal});return{ok:!1,status:response.status,error:`HTTP ${response.status}${body?`: ${safeErrorText(body,opts.auth).slice(0,PROBE_LIMITS.maxErrorChars)}`:""}`}}let text2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxBodyBytes,overflowMessage:`Response exceeds ${PROBE_LIMITS.maxBodyBytes} bytes.`,signal:controller.signal});try{return{ok:!0,json:JSON.parse(text2)}}catch{return{ok:!1,error:"Model catalog response is not JSON."}}};try{let url=modelCatalogUrl(baseUrl,opts.api),headers=buildHeaders(opts.auth,opts.api),page=await getPage(url,headers),retry=page.ok?void 0:openAIStyleRetry(baseUrl,opts.auth,opts.api,{url,headers,status:page.status});if(!page.ok&&retry){let retried=await getPage(retry.url,retry.headers);if(!retried.ok)return{ok:!1,error:safeErrorText(`${url.href} \u2192 HTTP ${page.status}; OpenAI-style retry ${retry.url.href} \u2192 ${retried.error}`,opts.auth)};({url,headers}=retry),page=retried}if(!page.ok)return{ok:!1,error:page.error};let models=parseCatalogModels(page.json);if(models===null)return{ok:!1,error:"JSON has no supported OpenAI-style data[] or models[] catalog with model ids. Add models manually if this endpoint uses another catalog format."};let json=page.json;for(let pages=1;opts.api==="anthropic-messages"&&pages<PROBE_LIMITS.maxPages&&models.length<PROBE_LIMITS.maxModels;pages++){let cursor=nextPageCursor(json);if(!cursor)break;let nextUrl=new URL(url.href);nextUrl.searchParams.set("after_id",cursor),nextUrl.searchParams.set("limit","1000");let next=await getPage(nextUrl,headers),more=next.ok?parseCatalogModels(next.json):null;if(!next.ok||!more||(models.push(...more),nextPageCursor(next.json)===cursor))break;json=next.json}let sorted=dedupeSort(models),truncated=sorted.length>PROBE_LIMITS.maxModels||declaresMorePages(json);return{ok:!0,models:sorted.slice(0,PROBE_LIMITS.maxModels),truncated}}catch(error){return controller.signal.aborted?{ok:!1,error:opts.signal?.aborted?"Cancelled.":`Timed out after ${timeoutMs}ms.`}:{ok:!1,error:safeErrorText(formatError(error),opts.auth)}}finally{clearTimeout(timer),opts.signal?.removeEventListener("abort",onOuterAbort)}}function modelCatalogUrl(base,api){let url=new URL(base.href),path14=url.pathname.replace(/\/+$/,"");return url.pathname=api==="anthropic-messages"&&!path14.endsWith("/v1")?`${path14}/v1/models`:`${path14}/models`,url}function openAIStyleRetry(base,auth,api,first){if(api!=="anthropic-messages"||![401,403,404].includes(first.status??0)||Object.keys(auth?.headers??{}).some(key=>key.toLowerCase()==="authorization"))return;let root=new URL(base.href);root.pathname=root.pathname.replace(/\/+$/,"").replace(/\/anthropic$/i,"");let url=modelCatalogUrl(root,api),headers=buildHeaders(auth,void 0);return url.href===first.url.href&&headers.get("authorization")===first.headers.get("authorization")?void 0:{url,headers}}function safeErrorText(text2,auth){for(let value2 of[auth?.apiKey,...Object.values(auth?.headers??{})]){if(typeof value2!="string"||!value2)continue;text2=text2.replaceAll(value2,"[redacted]");let token=value2.replace(/^Bearer\s+/i,"");token!==value2&&token&&(text2=text2.replaceAll(token,"[redacted]"))}return stripTerminalSequences(text2)}function buildHeaders(auth,api){let headers=new Headers;headers.set("accept","application/json");let configured=auth?.headers??{};api==="anthropic-messages"&&headers.set("anthropic-version","2023-06-01");let hasAuthorization=!1;for(let[key,value2]of Object.entries(configured))key.toLowerCase()==="authorization"&&(hasAuthorization=!0),typeof value2=="string"?headers.set(key,value2):value2===null&&headers.delete(key);if(!auth?.apiKey||hasAuthorization)return headers;let lower=name=>Object.keys(configured).some(key=>key.toLowerCase()===name);return api==="anthropic-messages"?(auth.apiKey.includes("sk-ant-oat")?headers.set("authorization",`Bearer ${auth.apiKey}`):(lower("x-api-key")||headers.set("x-api-key",auth.apiKey),lower("anthropic-version")||headers.set("anthropic-version","2023-06-01")),headers):api==="google-generative-ai"||api==="google-vertex"?(lower("x-goog-api-key")||headers.set("x-goog-api-key",auth.apiKey),headers):(headers.set("authorization",`Bearer ${auth.apiKey}`),headers)}function declaresMorePages(json){return typeof json=="object"&&json!==null&&"has_more"in json&&json.has_more===!0}function nextPageCursor(json){if(!declaresMorePages(json))return;let lastId=json.last_id;return typeof lastId=="string"&&lastId?lastId:void 0}var CONTEXT_WINDOW_FIELDS=["context_window","context_window.tokens","context_length","top_provider.context_length","max_input_tokens","max_context_length","max_model_len","context_size","metadata.context_length"],MAX_TOKENS_FIELDS=["max_output_tokens","max_completion_tokens","top_provider.max_completion_tokens","max_tokens","max_output_length"],INPUT_MODALITY_FIELDS=["input_modalities","architecture.input_modalities","modalities.input"],IMAGE_FLAG_FIELDS=["supports_vision","enable_vision_input","capabilities.vision","capabilities.image_input.supported"],REASONING_FLAG_FIELDS=["reasoning","supports_reasoning","enable_reason","capabilities.reasoning","capabilities.thinking.supported"],REASONING_LEVEL_FIELDS=["effort.supported_levels","reasoning_effort_support_list"],CAPABILITY_LIST_FIELDS=["supported_parameters","tags","features","supported_features","metadata.tags"];function fieldAt(record,path14){let value2=record;for(let key of path14.split(".")){if(!value2||typeof value2!="object"||Array.isArray(value2))return;value2=value2[key]}return value2}function listAt(record,path14){let value2=fieldAt(record,path14);return Array.isArray(value2)?value2.filter(entry=>typeof entry=="string").map(entry=>entry.toLowerCase()):[]}function declaredLimit(record,paths){let limit;for(let path14 of paths){let value2=fieldAt(record,path14);typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>0&&(limit=Math.min(limit??value2,value2))}return limit}function declaresImageInput(record){return INPUT_MODALITY_FIELDS.some(path14=>listAt(record,path14).includes("image"))||IMAGE_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("vision"))}function declaresReasoning(record){return REASONING_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||REASONING_LEVEL_FIELDS.some(path14=>listAt(record,path14).length>0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("reasoning"))}function parseCatalogModels(json){if(!json||typeof json!="object")return null;let payload=json,data=Array.isArray(json)?json:Array.isArray(payload.models)?payload.models:payload.data;if(!Array.isArray(data))return null;let models=[];for(let item of data){if(!item||typeof item!="object")continue;let record=item,id=(typeof record.id=="string"?record.id.trim():"")||(typeof record.slug=="string"?record.slug.trim():"");if(!id)continue;let displayName=typeof record.name=="string"&&record.name.trim()?record.name.trim():void 0,anthropicName=typeof record.display_name=="string"&&record.display_name.trim()?record.display_name.trim():typeof record.displayName=="string"?record.displayName.trim():void 0,name=(displayName??anthropicName)!==id?displayName??anthropicName:void 0,model=name?{id,name}:{id},contextWindow=declaredLimit(record,CONTEXT_WINDOW_FIELDS);contextWindow&&(model.contextWindow=contextWindow);let maxTokens=declaredLimit(record,MAX_TOKENS_FIELDS);maxTokens&&(model.maxTokens=maxTokens),declaresImageInput(record)&&(model.input=["text","image"]),declaresReasoning(record)&&(model.reasoning=!0),models.push(model)}return data.length>0&&models.length===0?null:models}function dedupeSort(models){let map=new Map;for(let model of models)map.has(model.id)||map.set(model.id,model);return[...map.values()].sort((a,b2)=>a.id.localeCompare(b2.id))}async function fetchProviderModels(options,signal){let{store,refresher,runtime,providerId}=options,deadline=AbortSignal.any([signal,AbortSignal.timeout(PROBE_LIMITS.timeoutMs)]);try{await raceWithAbortSignal(store.flush(),deadline);let unsaved=store.getPendingError(providerId);if(unsaved)return{ok:!1,error:`Save the provider changes before fetching: ${unsaved}`};let provider=store.getProvider(providerId),settings2=effectiveModelSettings(providerId,provider);if(!settings2.baseUrl)return{ok:!1,error:"Set a baseUrl under API Auth first."};let sync=await refresher.refreshNow(providerId,deadline);if(deadline.throwIfAborted(),!sync.ok)return{ok:!1,error:`The provider did not reload: ${sync.errors.join("; ")}`};let resolved=await raceWithAbortSignal(runtime.getAuth(providerId,{signal:deadline}),deadline),configured=provider?.apiKey!==void 0||provider?.authHeader===!0||Object.keys(provider?.headers??{}).length>0||runtime.getProviderAuthStatus(providerId).configured;if(!resolved&&configured)return{ok:!1,error:"Configured credentials or headers did not resolve; check the provider authentication."};let result2=await probeProviderModels({baseUrl:resolved?.auth.baseUrl??settings2.baseUrl,auth:resolved?.auth,api:settings2.api,signal:deadline});return deadline.throwIfAborted(),result2}catch(error){return deadline.aborted?{ok:!1,error:signal.aborted?"Cancelled.":"Timed out while preparing or fetching the model catalog."}:{ok:!1,error:formatError(error)}}}async function importProviderModels(options,models,signal){let{store,refresher,providerId}=options;await raceWithAbortSignal(store.flush(),signal);let unsaved=store.getPendingError(providerId);if(unsaved)return unsaved;let settings2=effectiveModelSettings(providerId,store.getProvider(providerId));if(!settings2.api||!settings2.baseUrl)return"Set baseUrl and API Type under API Auth before importing models.";let existing=new Set(store.getModels(providerId).map(model=>model.id)),fresh=models.filter(model=>existing.has(model.id)?!1:(existing.add(model.id),!0));if(fresh.length===0)return;signal.throwIfAborted(),store.batch(()=>{for(let model of fresh)store.addModel(providerId,model)}),refresher.touch(providerId),await store.flush();let saveError=store.getPendingError(providerId);if(saveError)return saveError;let outcome=await refresher.refreshNow(providerId,signal);if(!outcome.ok)return`Models were saved, but refresh failed: ${outcome.errors.join("; ")}`}var CURSOR="\u203A",PASTE_START="\x1B[200~",PASTE_END="\x1B[201~",ValueEditor=class{constructor(callbacks){this.input=new Input({prompt:""}),this.input.onSubmit=callbacks.onCommit,this.input.onEscape=callbacks.onCancel}beginOverwrite(firstData){this.input.setValue(""),firstData&&this.input.handleInput(firstData)}reset(value2){this.beginTweak(value2)}beginTweak(current){this.input.setValue(""),this.input.handleInput(PASTE_START+current+PASTE_END),this.input.setValue(current)}get value(){return this.input.getValue()}handleInput(data){this.input.handleInput(data)}renderLine(width){return this.input.render(Math.max(1,width))[0]??""}get focused(){return this.input.focused}set focused(value2){this.input.focused=value2}};function renderKeyValueLine(theme2,opts){let lit=opts.active&&opts.paneFocused,marker=lit?theme2.fg("accent",`${CURSOR} `):" ",keyPrefix=opts.keyLabel===void 0?"":`${opts.keyLabel}: `,keyColor=lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"";if(opts.editing){let body=opts.editing.renderLine(Math.max(1,opts.width-visibleWidth(marker)-visibleWidth(keyPrefix)));return truncateToWidth(marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(keyColor,body)+note,opts.width)}let valueColor=opts.unset?"dim":keyColor,line=marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(valueColor,opts.valueText??"")+note;return truncateToWidth(line,opts.width)}function renderPlainLine(theme2,text2,opts){let lit=(opts.active??!1)&&(opts.paneFocused??!1),marker=lit?theme2.fg("accent",`${CURSOR} `):" ",check=opts.checked===void 0?"":opts.checked?"[x] ":"[ ] ",color2=opts.dim?"dim":lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"",line=marker+theme2.fg(color2,check+text2)+note;return truncateToWidth(line,opts.width)}function renderInfoLine(theme2,text2,width){return truncateToWidth(theme2.fg("dim",text2),width)}function windowLines(theme2,lines,height,scroll,indicator){let top=Math.max(0,Math.min(scroll?.top??0,lines.length)),bottom=Math.max(0,Math.min(scroll?.bottom??0,lines.length-top)),head=lines.slice(0,top),tail=bottom>0?lines.slice(lines.length-bottom):[],middle=lines.slice(top,lines.length-bottom),cursor=Math.max(0,Math.min((scroll?.cursor??0)-top,Math.max(0,middle.length-1))),padToHeight=rows=>{let out=rows.slice(0,height);for(;out.length<height;)out.push("");return out},avail=height-head.length-tail.length;if(middle.length<=avail)return padToHeight([...head,...middle,...tail]);let slots=Math.max(1,avail-1),start=Math.max(0,Math.min(cursor-Math.floor(slots/2),middle.length-slots)),note=indicator?.(cursor+1,middle.length)??theme2.fg("dim",` (${cursor+1}/${middle.length})`);return padToHeight([...head,...middle.slice(start,start+slots),note,...tail])}function isPrintableInput(data){if(!data)return!1;if(data.startsWith(PASTE_START)||decodeKittyPrintable(data)!==void 0)return!0;if(data.includes("\x1B")||data.includes("\r")||data.includes(`
|
|
1564
1564
|
`))return!1;for(let char of data){let code=char.codePointAt(0);if(code<32||code===127)return!1}return!0}function truncateMiddle(text2,maxWidth){if(visibleWidth(text2)<=maxWidth)return text2;if(maxWidth<=4)return truncateToWidth(text2,maxWidth);let headWidth=Math.ceil((maxWidth-1)/2),tailWidth=maxWidth-1-headWidth,head="",headUsed=0;for(let char of text2){let charWidth=visibleWidth(char);if(headUsed+charWidth>headWidth)break;head+=char,headUsed+=charWidth}let tail="",tailUsed=0;for(let char of[...text2].reverse()){let charWidth=visibleWidth(char);if(tailUsed+charWidth>tailWidth)break;tail=char+tail,tailUsed+=charWidth}return`${head}\u2026${tail}`}var InfoPane=class{constructor(host,lines,onConfirm){this.focused=!1,this.host=host,this.lines=lines,this.onConfirm=onConfirm}render(width){return this.focused&&this.onConfirm?this.lines.map((line,index3)=>index3>0?renderInfoLine(this.host.theme,line,width):truncateToWidth(this.host.theme.fg("accent",`${CURSOR} `)+this.host.theme.fg("text",line),width)):this.lines.map(line=>renderInfoLine(this.host.theme,line,width))}handleInput(data){if(this.host.keybindings.matches(data,"tui.select.cancel")){this.host.popPane();return}this.onConfirm&&this.host.keybindings.matches(data,"tui.select.confirm")&&this.onConfirm()}setFocused(focused){this.focused=focused}hints(){let hints=[];return this.onConfirm&&hints.push(keyHint("tui.select.confirm","proceed")),hints.push(keyHint("tui.select.cancel","back")),hints.join(" ")}},ConfirmPane=class{constructor(host,message,actionLabel,action){this.crumb="Confirm",this.index=1,this.focused=!1,this.host=host,this.message=message,this.actionLabel=actionLabel,this.action=action}render(width){let theme2=this.host.theme;return[truncateToWidth(theme2.fg("warning",this.message),width),renderPlainLine(theme2,this.actionLabel,{active:this.index===0,paneFocused:this.focused,width}),renderPlainLine(theme2,"Cancel",{active:this.index===1,paneFocused:this.focused,width})]}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")){this.index=this.index===0?1:0,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}kb.matches(data,"tui.select.confirm")&&(this.index===0?this.action():this.host.popPane())}setFocused(focused){this.focused=focused}hints(){return[keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}};function formatTokens2(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function metadataNote(model){let parts=[model.contextWindow?`${formatTokens2(model.contextWindow)} ctx`:"",model.maxTokens?`${formatTokens2(model.maxTokens)} out`:"",model.input?.includes("image")?"img":"",model.reasoning?"think":""].filter(Boolean);return parts.length>0?`\xB7 ${parts.join(" \xB7 ")}`:void 0}var FetchModelsPane=class{constructor(host){this.state={type:"idle"},this.query="",this.index=0,this.checked=new Set,this.importing=!1,this.focused=!1,this.disposed=!1,this.host=host,this.search=new ValueEditor({onCommit:()=>this.importChecked(),onCancel:()=>this.exitResults()})}start(){if(this.disposed||this.state.type==="loading"||this.importing||!this.catalogUrl())return;let controller=new AbortController;this.controller=controller,this.state={type:"loading"},this.error=void 0,this.host.refresh(),this.host.runFetch(controller.signal).then(result2=>{if(!(this.disposed||controller.signal.aborted||this.controller!==controller)){if(result2.ok)this.state={type:"results",models:result2.models,truncated:result2.truncated},this.checked=new Set,this.query="",this.search.reset(""),this.index=0,this.search.focused=this.focused,this.host.setFetchStatus(`\xB7 ${result2.models.length} models`);else{if(result2.error==="Cancelled.")return;this.state={type:"error",message:result2.error},this.host.setFetchStatus("\xB7 failed")}this.host.refresh()}}).catch(error=>{controller.signal.aborted||(this.state={type:"error",message:error instanceof Error?error.message:String(error)},this.host.setFetchStatus("\xB7 failed"),this.host.refresh())})}existingIds(){return new Set(this.host.store.getModels(this.host.providerId).map(model=>model.id))}catalogUrl(){let baseUrl=this.host.store.getProvider(this.host.providerId)?.baseUrl;try{return baseUrl?modelCatalogUrl(new URL(baseUrl),this.host.effectiveApi()).href:void 0}catch{return}}rows(){if(this.state.type!=="results")return[];let existing=this.existingIds(),rows=this.state.models.map(model=>({model,added:existing.has(model.id)})),query=this.query.trim().toLowerCase();return query?rows.filter(row=>row.model.id.toLowerCase().includes(query)||row.model.name?.toLowerCase().includes(query)):rows}render(width){let theme2=this.host.theme,catalogUrl=this.catalogUrl();switch(this.state.type){case"idle":return catalogUrl?[renderPlainLine(theme2,"Fetch Models",{active:!0,paneFocused:this.focused,note:`\xB7 from ${truncateMiddle(catalogUrl,Math.max(10,width-22))}`,width})]:[renderInfoLine(theme2,"Set a baseUrl under API Auth first.",width)];case"loading":return[renderInfoLine(theme2,`Fetching ${catalogUrl??""} \u2026`,width),renderInfoLine(theme2,"Esc cancels the request.",width)];case"error":return[theme2.fg("error",truncate2(this.state.message,Math.max(10,width-2))),renderInfoLine(theme2,"Enter retries; Esc goes back.",width)];case"results":{let lines=[];this.state.truncated&&lines.push(renderInfoLine(theme2,"The catalog was truncated; refine manually if a model is missing.",width)),lines.push(this.search.renderLine(width));let rows=this.rows();for(let[rowIndex,row]of rows.entries()){if(row.added){lines.push(renderPlainLine(theme2,row.model.id,{active:rowIndex===this.index,paneFocused:this.focused,dim:!0,note:"\xB7 Added",width}));continue}lines.push(renderPlainLine(theme2,row.model.name?`${row.model.id} \xB7 ${row.model.name}`:row.model.id,{checked:this.checked.has(row.model.id),active:rowIndex===this.index,paneFocused:this.focused,note:metadataNote(row.model),width}))}rows.length===0&&lines.push(renderInfoLine(theme2,"No matching models.",width));let addedCount=rows.filter(row=>row.added).length;return lines.push(renderInfoLine(theme2,`${this.checked.size} selected \xB7 ${rows.length} shown${addedCount?` \xB7 ${addedCount} already added`:""}`,width)),this.importing&&lines.push(renderInfoLine(theme2,"Importing\u2026",width)),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}}}scrollWindow(){if(this.state.type!=="results")return{};let top=(this.state.truncated?1:0)+1,bottom=1+(this.importing?1:0)+(this.error?1:0);return{top,bottom,cursor:top+this.index}}handleInput(data){let kb=this.host.keybindings;switch(this.state.type){case"idle":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"loading":if(kb.matches(data,"tui.select.cancel")){this.controller?.abort(),this.state={type:"idle"},this.host.refresh();return}return;case"error":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"results":this.handleResultsInput(data);return}}handleResultsInput(data){let kb=this.host.keybindings,rows=this.rows();if(kb.matches(data,"tui.select.up")){rows.length>0&&(this.index=this.index===0?rows.length-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){rows.length>0&&(this.index=(this.index+1)%rows.length),this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let row=rows[this.index];if(!row||row.added||this.importing)return;this.checked.has(row.model.id)?this.checked.delete(row.model.id):this.checked.add(row.model.id),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.exitResults();return}if(kb.matches(data,"tui.select.confirm")){this.importChecked();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}importChecked(){if(this.state.type!=="results"||this.importing)return;let chosen;if(this.checked.size===0){let row=this.rows()[this.index];if(!row||row.added)return;chosen=[row.model]}else chosen=this.state.models.filter(model=>this.checked.has(model.id));let controller=new AbortController;this.controller=controller,this.importing=!0,this.error=void 0,this.host.refresh(),this.host.importModels(chosen,controller.signal).then(error=>{if(!(this.disposed||controller.signal.aborted||this.controller!==controller)){if(this.importing=!1,error)return this.error=error,this.host.setFetchStatus("\xB7 import failed"),this.host.refresh();this.host.setFetchStatus(`\xB7 ${this.host.store.getModels(this.host.providerId).length} models`),this.state={type:"idle"},this.host.popPane()}}).catch(error=>{this.disposed||controller.signal.aborted||this.controller!==controller||(this.importing=!1,this.error=error instanceof Error?error.message:String(error),this.host.refresh())})}exitResults(){this.controller?.abort(),this.importing=!1,this.state={type:"idle"},this.checked=new Set,this.host.popPane()}setFocused(focused){this.focused=focused,this.search.focused=focused&&this.state.type==="results"}isEditing(){return this.state.type==="results"}dispose(){this.disposed=!0,this.controller?.abort()}hints(){switch(this.state.type){case"loading":return keyHint("tui.select.cancel","cancel request");case"results":return[rawKeyHint("type","filter"),keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","import"),keyHint("tui.select.cancel","discard")].join(" ");case"error":return[keyHint("tui.select.confirm","retry"),keyHint("tui.select.cancel","back")].join(" ");default:return this.catalogUrl()?[keyHint("tui.select.confirm","fetch"),keyHint("tui.select.cancel","back")].join(" "):keyHint("tui.select.cancel","back")}}};function formatContext(model){let ctx=model.contextWindow>=1e3?`${Math.round(model.contextWindow/1024)}k`:String(model.contextWindow);return`${model.api} \xB7 ${ctx} ctx${model.reasoning?" \xB7 reasoning":""}`}var BuiltinCandidatesPane=class{constructor(host,model){this.crumb="Use Built-in Data",this.index=0,this.focused=!1,this.host=host,this.model=model,this.query=this.model.read().id??"",this.search=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()}),this.search.reset(this.query)}candidates(){return matchBuiltinModels(this.query,this.host.effectiveApi(this.model.read())).map(match2=>match2.entry)}tiers(){return matchBuiltinModels(this.query,this.host.effectiveApi(this.model.read()))}render(width){let theme2=this.host.theme,lines=[this.search.renderLine(width)],matches=this.tiers();matches.length===0&&lines.push(renderInfoLine(theme2,"No builtin candidates \u2014 keep configuring manually.",width));for(let[rowIndex,match2]of matches.entries()){let{providerId,model}=match2.entry,label=`${providerId} / ${model.id}`,note=(match2.tier==="exact"?"exact \xB7 ":"")+`${model.name!==model.id?`${model.name} \xB7 `:""}${formatContext(model)}`;lines.push(renderPlainLine(theme2,label,{active:rowIndex===this.index,paneFocused:this.focused,note,width}))}return lines.push(renderInfoLine(theme2,"Candidates are a reference only; the configured id is never rewritten.",width)),lines}scrollWindow(){return{top:1,bottom:1,cursor:1+this.index}}pickCurrent(){let entry=this.candidates()[this.index];entry&&this.host.pushPane(new BuiltinPreviewPane(this.host,this.model,entry))}handleInput(data){let kb=this.host.keybindings,count=this.candidates().length;if(kb.matches(data,"tui.select.up")){count>0&&(this.index=this.index===0?count-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){count>0&&(this.index=(this.index+1)%count),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.search.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","preview"),keyHint("tui.select.cancel","back")].join(" ")}},BuiltinPreviewPane=class{constructor(host,model,reference){this.crumb="Use Built-in Data \xB7 preview",this.index=0,this.focused=!1,this.host=host,this.model=model,this.reference=reference;let current=model.read();this.snapshot=structuredClone(current),this.snapshotApi=host.effectiveApi(current),this.changes=computeFieldChanges(current,reference.model,host.effectiveApi(current)),this.checked=this.changes.map(change=>change.checked&&change.applicable)}rowCount(){return this.changes.length+1}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,`reference: ${this.reference.providerId} / ${this.reference.model.id}`,width)];for(let[rowIndex,change]of this.changes.entries()){let active=rowIndex===this.index,expandable=change.referenceDetails!==void 0,note=change.applicable?void 0:"\xB7 view only";if(lines.push(renderPlainLine(theme2,`${change.field}: ${change.currentText} \u2192 ${change.referenceText}`,{checked:change.applicable?this.checked[rowIndex]:void 0,active,paneFocused:this.focused,note,width})),this.expanded===rowIndex&&expandable){for(let detail of change.referenceDetails)lines.push(renderInfoLine(theme2,` ${detail}`,width));change.referenceHasTiers&&lines.push(renderInfoLine(theme2," reference has cost tiers \u2014 tiers are never imported.",width))}}return lines.push(renderPlainLine(theme2,"Apply Selected Fields",{active:this.index===this.changes.length,paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}scrollWindow(){let cursor=1+this.index;if(this.expanded!==void 0&&this.expanded<this.index){let change=this.changes[this.expanded];change.referenceDetails&&(cursor+=change.referenceDetails.length+(change.referenceHasTiers?1:0))}return{top:1,bottom:this.error?1:0,cursor}}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){this.index=this.index===0?this.rowCount()-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%this.rowCount(),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.list.toggle")){let change=this.changes[this.index];if(!change)return;if(!change.applicable){this.expanded=this.expanded===this.index?void 0:this.index,this.host.refresh();return}this.checked[this.index]=!this.checked[this.index],this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){if(this.index===this.changes.length){this.apply();return}let change=this.changes[this.index];change.referenceDetails?this.expanded=this.expanded===this.index?void 0:this.index:change.applicable&&(this.checked[this.index]=!this.checked[this.index]),this.host.refresh();return}}apply(){let current=this.model.read();if(this.host.effectiveApi(current)!==this.snapshotApi){this.error="The API changed since this preview opened; reopen to continue.",this.host.refresh();return}if(!current.id||!jsonEquals(current,this.snapshot)){this.error="The model changed since this preview opened; reopen to continue.",this.host.refresh();return}let chosen=this.changes.filter((_2,rowIndex)=>this.checked[rowIndex]&&this.changes[rowIndex].applicable);if(chosen.length===0){this.host.popPane();return}this.host.store.batch(()=>{for(let change of chosen)this.applyChange(change.field)}),this.host.refresher.touch(this.host.providerId),this.host.notify(`Applied ${chosen.length} field${chosen.length===1?"":"s"} from ${this.reference.providerId} / ${this.reference.model.id}.`,"info"),this.host.popPane(),this.host.popPane()}applyChange(field3){let reference=this.reference.model,current=this.model.read();switch(field3){case"name":this.model.setField(["name"],reference.name);return;case"reasoning":this.model.setField(["reasoning"],reference.reasoning);return;case"input":this.model.setField(["input"],[...reference.input]);return;case"contextWindow":this.model.setField(["contextWindow"],reference.contextWindow);return;case"maxTokens":this.model.setField(["maxTokens"],reference.maxTokens);return;case"thinkingLevelMap":for(let[level,target]of Object.entries(reference.thinkingLevelMap??{}))this.model.setField(["thinkingLevelMap",level],target);return;case"compat":for(let[key,value2]of Object.entries(reference.compat??{}))if(["chatTemplateKwargs","chatTemplateArgs","openRouterRouting","vercelGatewayRouting"].includes(key)&&value2!==null&&typeof value2=="object"&&!Array.isArray(value2))for(let[entryKey,entryValue]of Object.entries(value2))this.model.setField(["compat",key,entryKey],structuredClone(entryValue));else this.model.setField(["compat",key],structuredClone(value2));return;case"cost":{let rates={input:reference.cost.input,output:reference.cost.output,cacheRead:reference.cost.cacheRead,cacheWrite:reference.cost.cacheWrite};if(current.cost)for(let[rate,value2]of Object.entries(rates))this.model.setField(["cost",rate],value2);else this.model.setField(["cost"],rates);return}}}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","details / apply"),keyHint("tui.select.cancel","back")].join(" ")}};var THINKING_VARIABLES=["thinking.enabled","thinking.effort","thinking.budget"],SESSION_AFFINITY=["openai","openai-nosession","openrouter"],OPENAI_COMPLETIONS_FIELDS=[{key:"supportsStore",kind:"boolean",note:"Accepts the `store` parameter"},{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"supportsReasoningEffort",kind:"boolean",note:"Accepts `reasoning_effort`"},{key:"supportsUsageInStreaming",kind:"boolean",note:"Streams usage chunks"},{key:"supportsFinishReason",kind:"boolean",note:"Reports finish reasons"},{key:"maxTokensField",kind:"enum",options:["max_completion_tokens","max_tokens"],note:"Token limit field name"},{key:"requiresToolResultName",kind:"boolean",note:"Tool results need a `name`"},{key:"requiresAssistantAfterToolResult",kind:"boolean",note:"Needs assistant message after tool results"},{key:"requiresThinkingAsText",kind:"boolean",note:"Thinking must be plain text"},{key:"requiresReasoningContentOnAssistantMessages",kind:"boolean",note:"Assistant messages must carry reasoning content"},{key:"thinkingFormat",kind:"enum",options:["openai","openrouter","together","baseten","deepseek","zai","qwen","chat-template","qwen-chat-template","string-thinking","ant-ling"],note:"Reasoning payload format"},{key:"chatTemplateKwargs",kind:"stringMap",note:"Extra chat-template kwargs (open dictionary)"},{key:"chatTemplateArgs",kind:"stringMap",note:"Extra chat-template args (open dictionary)"},{key:"cacheControlFormat",kind:"enum",options:["anthropic"],note:"Cache-control payload format"},{key:"openRouterRouting",kind:"json",note:"OpenRouter routing preferences object"},{key:"vercelGatewayRouting",kind:"json",note:"Vercel AI Gateway routing object"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolAdditions",kind:"boolean",note:"System messages can add tools mid-conversation"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"vllmPriority",kind:"number",note:"vLLM scheduling priority"},{key:"zaiToolStream",kind:"boolean",note:"Z.AI streaming tool calls"},{key:"supportsThinkingTokenBudget",kind:"boolean",note:"Enable the thinking-token budget alias"},{key:"thinkingTokenBudgetField",kind:"enum",options:["thinking_token_budget","thinking_budget","thinking_budget_tokens"],note:"Thinking budget field"}],OPENAI_RESPONSES_FIELDS=[{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsAdditionalTools",kind:"boolean",note:"Accepts additional hosted tools"},{key:"supportsToolSearch",kind:"boolean",note:"Tool search support"},{key:"supportsMaxOutputTokens",kind:"boolean",note:"Accepts `max_output_tokens`"},{key:"supportsExplicitPromptCacheMode",kind:"boolean",note:"Explicit prompt caching"}],ANTHROPIC_MESSAGES_FIELDS=[{key:"supportsEagerToolInputStreaming",kind:"boolean",note:"Streams tool input eagerly"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsCacheControlOnTools",kind:"boolean",note:"Cache control on tool definitions"},{key:"supportsTemperature",kind:"boolean",note:"Accepts `temperature`"},{key:"forceAdaptiveThinking",kind:"boolean",note:"Force adaptive thinking mode"},{key:"allowEmptySignature",kind:"boolean",note:"Tolerate empty thinking signatures"},{key:"supportsStrictTools",kind:"boolean",note:"Strict tool schemas"},{key:"supportsMidConvoEffort",kind:"boolean",note:"Effort changes mid-conversation"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolChanges",kind:"boolean",note:"Accepts mid-conversation tool changes"},{key:"allowedFallbackModels",kind:"json",note:"Server-side refusal fallback models"}],BEDROCK_FIELDS=[{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"}];function compatFieldsForApi(api){switch(api){case"openai-completions":return OPENAI_COMPLETIONS_FIELDS;case"openai-responses":return OPENAI_RESPONSES_FIELDS;case"azure-openai-responses":return OPENAI_RESPONSES_FIELDS.filter(field3=>["supportsDeveloperRole","supportsStrictMode","supportsOpenAIGrammarTools"].includes(field3.key));case"openai-codex-responses":return OPENAI_RESPONSES_FIELDS.filter(field3=>["supportsStrictMode","supportsOpenAIGrammarTools","supportsAdditionalTools","supportsToolSearch"].includes(field3.key));case"anthropic-messages":return ANTHROPIC_MESSAGES_FIELDS;case"bedrock-converse-stream":return BEDROCK_FIELDS;default:return[]}}function compatFieldFor(api,key){return compatFieldsForApi(api).find(field3=>field3.key===key)}var completionsCompatValidator=Compile(OpenAICompletionsCompatSchema);function validateCompletionsCompat(value2){if(!completionsCompatValidator.Check(value2))return completionsCompatValidator.Errors(value2).slice(0,5).map(error=>{let path14=error.instancePath.replace(/^\//,"").replace(/\//g,"."),required=error.keyword==="required"?error.params.requiredProperties?.[0]:void 0;return`${required?path14?`${path14}.${required}`:required:path14||"root"}: ${error.message}`}).join("; ")}function validateJsonCompatValue(key,text2){let value2;try{value2=JSON.parse(text2)}catch{return"Value is not valid JSON."}return validateCompletionsCompat({[key]:value2})}function validateChatTemplateKwarg(value2){if(value2!==null&&typeof value2=="object"&&!Array.isArray(value2)&&!Object.keys(value2).every(key=>key==="$var"||key==="omitWhenOff"))return'Only "$var" and "omitWhenOff" are allowed.';let error=validateCompletionsCompat({chatTemplateKwargs:{value:value2}});return error?`Value must be a scalar or valid $var reference: ${error}`:void 0}function compatObject(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText(value2){return value2===null?"null":typeof value2=="string"||typeof value2=="number"||typeof value2=="boolean"?String(value2):JSON.stringify(value2)??String(value2)}var DICT_VALUE_KINDS=["string","number","boolean","null","$var"],VAR_OPTIONS=THINKING_VARIABLES,DictPane=class{constructor(host,model,dictKey){this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model,this.dictKey=dictKey,this.crumb=`compat \xB7 ${dictKey}`}dict(){let value2=compatObject(this.model)[this.dictKey];return typeof value2=="object"&&value2!==null&&!Array.isArray(value2)?value2:{}}entries(){return Object.entries(this.dict())}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,"free-form keys; values: string \xB7 number \xB7 boolean \xB7 null \xB7 $var",width)];if(this.mode.type!=="list")return lines.push(...this.renderMode(width)),this.error&&lines.push(renderInfoLine(theme2,this.error,width)),lines;let entries=this.entries();for(let[rowIndex,[key,value2]]of entries.entries()){let active=rowIndex===this.index;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:scalarText(value2),active,paneFocused:this.focused,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type!=="list"?{top:1,bottom:this.error?1:0}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}renderMode(width){let theme2=this.host.theme,mode=this.mode;switch(mode.type){case"keyEdit":return[renderInfoLine(theme2,"new key:",width),mode.editor.renderLine(width)];case"kindPick":return[renderInfoLine(theme2,`${mode.key} \xB7 value kind`,width),...DICT_VALUE_KINDS.map((kind,kindIndex)=>renderPlainLine(theme2,kind,{active:kindIndex===mode.index,paneFocused:this.focused,width}))];case"valueEdit":return[renderInfoLine(theme2,`${mode.key} \xB7 ${mode.kind}`,width),renderKeyValueLine(theme2,{keyLabel:mode.key,active:!0,paneFocused:this.focused,editing:mode.editor,width})];case"boolPick":return[renderInfoLine(theme2,`${mode.key} \xB7 boolean`,width),...["true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"varPick":return[renderInfoLine(theme2,`${mode.key} \xB7 $var`,width),...VAR_OPTIONS.map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"omitPick":return[renderInfoLine(theme2,`${mode.key} \xB7 omitWhenOff`,width),...["default","true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];default:return[]}}handleInput(data){let kb=this.host.keybindings,mode=this.mode;switch(mode.type){case"keyEdit":case"valueEdit":if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;mode.editor.handleInput(data),this.host.refresh();return;case"kindPick":this.handlePick(data,mode,DICT_VALUE_KINDS.length,index3=>{let key=mode.key,kind=DICT_VALUE_KINDS[index3];this.startValueForKind(key,kind)});return;case"boolPick":this.handlePick(data,mode,2,index3=>{let key=mode.key;this.mode={type:"list"},this.writeEntry(key,index3===0)});return;case"varPick":this.handlePick(data,mode,VAR_OPTIONS.length,index3=>{let key=mode.key;this.mode={type:"omitPick",key,$var:VAR_OPTIONS[index3],index:0},this.host.refresh()});return;case"omitPick":this.handlePick(data,mode,3,index3=>{this.mode={type:"list"},this.writeEntry(mode.key,index3===0?{$var:mode.$var}:{$var:mode.$var,omitWhenOff:index3===1})});return;case"list":this.handleList(data);return}}handlePick(data,mode,count,choose2){let kb=this.host.keybindings,index3=mode.index;if(kb.matches(data,"tui.select.up")){mode.index=index3===0?count-1:index3-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){mode.index=(index3+1)%count,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}kb.matches(data,"tui.select.confirm")&&choose2(index3)}handleList(data){let kb=this.host.keybindings,rowCount=this.entries().length+1;if(kb.matches(data,"tui.select.up")){this.index=this.index===0?rowCount-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%rowCount,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;this.host.mutate(()=>this.model.setField(["compat",this.dictKey,entry[0]],DELETE)),this.index=Math.max(0,Math.min(this.index,this.entries().length-1));return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let entry=this.entries()[this.index];if(!entry){let editor2=new ValueEditor({onCommit:raw=>{let key2=raw.trim();if(!key2)return this.error="Key must be non-empty.",this.host.refresh();if(Object.hasOwn(this.dict(),key2))return this.error=`"${key2}" already exists.`,this.host.refresh();this.error=void 0,this.mode={type:"kindPick",key:key2,index:0},this.host.refresh()},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor2.focused=this.focused,this.mode={type:"keyEdit",editor:editor2},this.host.refresh();return}let[key,value2]=entry;if(typeof value2=="boolean"){this.writeEntry(key,!value2);return}if(value2===null)return;if(typeof value2=="object"){let record=value2;if(record.$var==="thinking.enabled"||record.$var==="thinking.effort"||record.$var==="thinking.budget"){this.mode={type:"omitPick",key,$var:record.$var,index:record.omitWhenOff===void 0?0:record.omitWhenOff?1:2},this.host.refresh();return}return}let kind=typeof value2=="number"?"number":"string",editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.beginTweak(String(value2)),editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}}startValueForKind(key,kind){switch(kind){case"string":case"number":{let editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}case"boolean":this.mode={type:"boolPick",key,index:0},this.host.refresh();return;case"null":this.mode={type:"list"},this.writeEntry(key,null);return;case"$var":this.mode={type:"varPick",key,index:0},this.host.refresh();return}}commitScalar(key,kind,raw){let value2=raw;if(kind==="number"){let parsed=Number(raw.trim());if(!Number.isFinite(parsed)){this.error=`${key} must be a number.`,this.host.refresh();return}value2=parsed}let invalid=validateChatTemplateKwarg(value2);if(invalid){this.error=invalid,this.host.refresh();return}this.error=void 0,this.mode={type:"list"},this.writeEntry(key,value2)}writeEntry(key,value2){let invalid=validateChatTemplateKwarg(value2);if(invalid){this.error=invalid,this.host.refresh();return}this.host.mutate(()=>this.model.setField(["compat",this.dictKey,key],value2))}setFocused(focused){this.focused=focused,(this.mode.type==="keyEdit"||this.mode.type==="valueEdit")&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="keyEdit"||this.mode.type==="valueEdit"}hints(){switch(this.mode.type){case"keyEdit":case"valueEdit":return[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" ");case"list":return[keyHint("tui.select.confirm","edit / add"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ");default:return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}}};function compatObject2(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText2(value2){return value2===null?"null":typeof value2=="string"||typeof value2=="number"||typeof value2=="boolean"?String(value2):JSON.stringify(value2)??String(value2)}var CompatPane=class{constructor(host,model){this.crumb="compat",this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model}entries(){return Object.entries(compatObject2(this.model))}effectiveApi(){return this.host.effectiveApi(this.model.read())}rowCount(){return this.entries().length+1}render(width){let theme2=this.host.theme,api=this.effectiveApi(),lines=[renderInfoLine(theme2,api?`effective api: ${api}`:"effective api: unresolved \u2014 set API Type",width)];if(this.mode.type==="chooseValue"){let mode=this.mode;lines.push(renderKeyValueLine(theme2,{keyLabel:mode.key,valueText:"choose a value",active:!0,paneFocused:this.focused,width}));for(let[index3,option]of mode.options.entries())lines.push(renderPlainLine(theme2,option,{active:index3===mode.index,paneFocused:this.focused,width}));return lines}let known=api?compatFieldsForApi(api):[],entries=this.entries(),editingKey=this.mode.type==="list"?void 0:this.mode.key;editingKey!==void 0&&!entries.some(([key])=>key===editingKey)&&entries.push([editingKey,void 0]),known.length===0&&entries.length===0&&lines.push(renderInfoLine(theme2,`No compat fields are known for ${api??"this api"}.`,width));for(let[rowIndex,[key,value2]]of entries.entries()){let active=rowIndex===this.index,field3=api?compatFieldFor(api,key):void 0,editing=this.mode.type==="editValue"&&this.mode.key===key?this.mode.editor:void 0,note=field3?void 0:`\xB7 not used by ${api??"this api"}`;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:value2===void 0?"not set":scalarText2(value2),active,paneFocused:this.focused,editing,note,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type==="chooseValue"?{top:1,cursor:2+this.mode.index}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="editValue"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.mode.editor.handleInput(data),this.host.refresh();return}if(this.mode.type==="chooseValue"){let mode=this.mode;if(kb.matches(data,"tui.select.up")){this.mode={...mode,index:mode.index===0?mode.options.length-1:mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...mode,index:(mode.index+1)%mode.options.length},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let option=mode.options[mode.index];this.mode={type:"list"},this.writeValue(mode.key,this.parseChosen(option))}return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?this.rowCount()-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%this.rowCount(),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;let[key]=entry;this.host.mutate(()=>this.model.setField(["compat",key],DELETE)),this.index=Math.min(this.index,this.rowCount()-2<0?0:this.rowCount()-2);return}if(kb.matches(data,"app.list.toggle")||kb.matches(data,"tui.select.confirm")){this.activateRow();return}}activateRow(){let entries=this.entries();if(this.index===entries.length){let api=this.effectiveApi();if(!api){this.fail("Set API Type first \u2014 compat fields depend on the effective api.");return}if(compatFieldsForApi(api).length===0){this.fail(`No compat fields are known for ${api}.`);return}let taken=new Set(entries.map(([key2])=>key2));this.host.pushPane(new CompatKeyPickerPane(this.host,api,taken,key2=>this.beginValueEntry(key2)));return}let[key,value2]=entries[this.index],field3=this.effectiveApi()?compatFieldFor(this.effectiveApi(),key):void 0;if(!field3){this.beginJsonEdit(key,value2);return}switch(field3.kind){case"boolean":this.writeValue(key,value2!==!0);return;case"enum":this.mode={type:"chooseValue",key,options:field3.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,value2);return;case"json":this.beginJsonEdit(key,value2);return;case"stringMap":this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginValueEntry(key){let api=this.effectiveApi(),field3=compatFieldFor(api,key);switch(field3.kind){case"boolean":this.mode={type:"chooseValue",key,options:["true","false"],index:0},this.host.refresh();return;case"enum":this.mode={type:"chooseValue",key,options:field3.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,void 0);return;case"json":this.beginJsonEdit(key,void 0);return;case"stringMap":this.writeValue(key,{}),this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginTextEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let parsed=Number(raw.trim());if(!Number.isFinite(parsed))return this.error=`${key} must be a number.`,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,parsed)},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(String(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}beginJsonEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let text2=raw.trim();if(!text2){this.mode={type:"list"},this.writeValue(key,DELETE);return}let shapeError=validateJsonCompatValue(key,text2);if(shapeError)return this.error=shapeError,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,JSON.parse(text2))},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(JSON.stringify(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}parseChosen(option){return option==="true"?!0:option==="false"?!1:option}writeValue(key,value2){this.host.mutate(()=>this.model.setField(["compat",key],value2))}fail(message){this.error=message,this.host.refresh()}setFocused(focused){this.focused=focused,this.mode.type==="editValue"&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="editValue"}hints(){return this.mode.type==="editValue"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):this.mode.type==="chooseValue"?[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","set"),keyHint("tui.select.cancel","cancel")].join(" "):[keyHint("tui.select.confirm","edit"),keyHint("app.list.toggle","toggle"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ")}},CompatKeyPickerPane=class{constructor(host,api,taken,onPick){this.crumb="compat \xB7 new entry",this.query="",this.index=0,this.focused=!1,this.host=host,this.api=api,this.taken=taken,this.onPick=onPick,this.editor=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()})}candidates(){let available=compatFieldsForApi(this.api).filter(field3=>!this.taken.has(field3.key)),query=this.query.trim();return query?fuzzyFilter(available,query,field3=>`${field3.key} ${field3.note??""}`):available}render(width){let theme2=this.host.theme,lines=[this.editor.renderLine(width)],candidates=this.candidates();candidates.length===0&&lines.push(renderInfoLine(theme2,"No remaining known fields.",width));for(let[rowIndex,field3]of candidates.entries())lines.push(renderPlainLine(theme2,field3.key,{active:rowIndex===this.index,paneFocused:this.focused,note:field3.note?`\xB7 ${field3.kind} \u2014 ${truncate2(field3.note,30)}`:`\xB7 ${field3.kind}`,width}));return lines}scrollWindow(){return{top:1,cursor:1+this.index}}pickCurrent(){let field3=this.candidates()[this.index];field3&&(this.host.popPane(),this.onPick(field3.key))}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){let count=this.candidates().length;count>0&&(this.index=this.index===0?count-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){let count=this.candidates().length;count>0&&(this.index=(this.index+1)%count),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.editor.handleInput(data),this.query=this.editor.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.editor.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","back")].join(" ")}};function baseUrlHint(api){switch(api){case"openai-responses":case"openai-completions":case"openai-codex-responses":return"baseUrl includes the version path, e.g. https://api.openai.com/v1";case"anthropic-messages":return"baseUrl is the bare origin \u2014 /v1/messages is added automatically";case"mistral-conversations":return"baseUrl is the bare origin \u2014 /v1 is added automatically";case"google-generative-ai":return"baseUrl includes the version path, e.g. https://generativelanguage.googleapis.com/v1beta";default:return}}function validateBaseUrlValue(value2){let url;try{url=new URL(value2)}catch{return"baseUrl must be a valid URL."}if(url.protocol!=="http:"&&url.protocol!=="https:")return`Unsupported protocol: ${url.protocol}`;if(url.username||url.password||url.hash)return"baseUrl must not contain credentials or a fragment."}var ApiAuthPane=class{constructor(host,registry){this.rows=["baseUrl","apiKey","apiType"],this.index=0,this.focused=!1,this.host=host,this.registry=registry}provider(){return this.host.store.getProvider(this.host.providerId)}scrollWindow(){return{cursor:this.index,bottom:this.bottomNoteCount()}}bottomNoteCount(){let status=this.registry.getProviderAuthStatus(this.host.providerId),hint2=baseUrlHint(this.provider()?.api);return(this.error?1:0)+(status.configured?1:0)+1+(hint2?1:0)}render(width){let theme2=this.host.theme,provider=this.provider(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;if(row==="baseUrl"){let value2=provider?.baseUrl;lines.push(renderKeyValueLine(theme2,{keyLabel:"baseUrl",valueText:value2??"not set",unset:!value2,active,paneFocused:this.focused,editing:this.editingRow==="baseUrl"?this.editing:void 0,width}))}else if(row==="apiKey"){let value2=provider?.apiKey;lines.push(renderKeyValueLine(theme2,{keyLabel:"apiKey",valueText:value2?maskApiKey(value2):"not set",unset:!value2,active,paneFocused:this.focused,editing:this.editingRow==="apiKey"?this.editing:void 0,width}))}else{let value2=provider?.api;lines.push(renderKeyValueLine(theme2,{keyLabel:"API Type",valueText:value2??"not set",unset:!value2,active,paneFocused:this.focused,width}))}}this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2))));let status=this.registry.getProviderAuthStatus(this.host.providerId);status.configured&&status.source==="stored"?lines.push(renderInfoLine(theme2,"A stored credential (auth.json) takes precedence over the apiKey here.",width)):status.configured&&status.source==="environment"&&lines.push(renderInfoLine(theme2,`An environment variable (${status.label??"env"}) currently provides the key.`,width)),lines.push(renderInfoLine(theme2,"Values are stored raw; $VAR / !command references resolve at request time.",width));let hint2=baseUrlHint(provider?.api);return hint2&&lines.push(renderInfoLine(theme2,hint2,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?this.rows.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%this.rows.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(new ApiTypePane(this.host)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];if(row!=="baseUrl"&&row!=="apiKey")return;let current=row==="baseUrl"?this.provider()?.baseUrl??"":this.provider()?.apiKey??"",editor=new ValueEditor({onCommit:value2=>this.commit(row,value2),onCancel:()=>{this.editing=void 0,this.editingRow=void 0,this.error=void 0,this.host.refresh()}});this.editing=editor,this.editingRow=row,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current),this.host.refresh()}commit(row,raw){let value2=raw.trim();if(row==="baseUrl"&&value2){let invalid=validateBaseUrlValue(value2);if(invalid){this.error=invalid,this.host.refresh();return}}if(row==="baseUrl"&&!value2){let builtin=builtinDefaults(this.host.providerId).baseUrl!==void 0,modelsCovered=this.host.store.getModels(this.host.providerId).every(model=>model.baseUrl!==void 0);if(!builtin&&!modelsCovered&&this.host.store.getModels(this.host.providerId).length>0){this.error="baseUrl cannot be removed while models rely on it.",this.host.refresh();return}}this.error=void 0,this.editing=void 0,this.editingRow=void 0,this.host.mutate(()=>this.host.store.setProviderField(this.host.providerId,[row],value2===""?DELETE:value2))}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}},ApiTypePane=class{constructor(host){this.crumb="API Type",this.index=0,this.focused=!1,this.host=host;let current=this.host.store.getProvider(this.host.providerId)?.api,options=this.options();this.index=Math.max(0,options.indexOf(current))}options(){let current=this.host.store.getProvider(this.host.providerId)?.api,base=[void 0,...API_TYPES];return current&&!API_TYPES.includes(current)&&base.push(current),base}unsetLabel(){let fallback=builtinDefaults(this.host.providerId).api;return fallback?`not set (built-in default: ${fallback})`:"not set (models define their own)"}render(width){let theme2=this.host.theme,current=this.host.store.getProvider(this.host.providerId)?.api,lines=this.options().map((option,rowIndex)=>{let active=rowIndex===this.index,label=`${option===current?"\u25CF":"\u25CB"} ${option??this.unsetLabel()}`;return renderPlainLine(theme2,label,{active,paneFocused:this.focused,dim:option===void 0,width})});return this.error&&lines.push(renderInfoLine(theme2,this.error,width)),lines}scrollWindow(){return{cursor:this.index,bottom:this.error?1:0}}handleInput(data){let kb=this.host.keybindings,options=this.options();if(kb.matches(data,"tui.select.up")){this.index=this.index===0?options.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%options.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let option=options[this.index];if(option===void 0){let uncovered=this.host.store.getModels(this.host.providerId).filter(model=>!model.api&&!builtinDefaults(this.host.providerId,model.id).api);if(uncovered.length>0){this.error=uncovered.length===1?`Model "${uncovered[0].id}" resolves its API from here \u2014 give it a model-level API first.`:`${uncovered.length} ${plural(uncovered.length,"model")} resolve their API from here \u2014 give them model-level APIs first.`,this.host.refresh();return}}this.error=void 0,this.host.mutate(()=>this.host.store.setProviderField(this.host.providerId,["api"],option??DELETE)),this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","select"),keyHint("tui.select.cancel","back")].join(" ")}};var REASONING_OPTIONS=[{label:"true",value:!0},{label:"false",value:!1},{label:"default (false)",value:void 0}],ReasoningPane=class{constructor(host,model){this.crumb="reasoning",this.index=0,this.focused=!1,this.host=host,this.model=model;let current=model.read().reasoning;this.index=current===!0?0:current===!1?1:2}render(width){let theme2=this.host.theme,current=this.model.read().reasoning;return REASONING_OPTIONS.map((option,optionIndex)=>{let selected=option.value===void 0?current===void 0:current===option.value;return renderPlainLine(theme2,`${selected?"\u25CF":"\u25CB"} ${option.label}`,{active:optionIndex===this.index,paneFocused:this.focused,dim:option.value===void 0,width})})}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){this.index=this.index===0?REASONING_OPTIONS.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%REASONING_OPTIONS.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let option=REASONING_OPTIONS[this.index];this.host.mutate(()=>this.model.setField(["reasoning"],option.value===void 0?DELETE:option.value)),this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","set"),keyHint("tui.select.cancel","back")].join(" ")}},InputTypesPane=class{constructor(host,model){this.crumb="input",this.index=0,this.focused=!1,this.host=host,this.model=model}selected(){return new Set(this.model.read().input??["text"])}render(width){let theme2=this.host.theme,selected=this.selected(),lines=INPUT_TYPES.map((type,rowIndex)=>renderPlainLine(theme2,type,{checked:selected.has(type),active:rowIndex===this.index,paneFocused:this.focused,width}));return this.model.read().input===void 0&&lines.push(renderInfoLine(theme2,"Not set \u2014 the runtime default is [text].",width)),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){this.index=this.index===0?INPUT_TYPES.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%INPUT_TYPES.length,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let type=INPUT_TYPES[this.index],selected=this.selected();if(selected.has(type)){if(selected.size===1){this.error="At least one input type must stay selected.",this.host.refresh();return}selected.delete(type)}else selected.add(type);this.error=void 0;let next=INPUT_TYPES.filter(entry=>selected.has(entry));this.host.mutate(()=>this.model.setField(["input"],[...next]));return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","toggle"),keyHint("tui.select.confirm","done"),keyHint("tui.select.cancel","back")].join(" ")}},COST_RATES=["input","output","cacheRead","cacheWrite"],CostPane=class{constructor(host,model){this.crumb="cost",this.index=0,this.focused=!1,this.host=host,this.model=model}cost(){let cost=this.model.read().cost;if(cost)return{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite}}render(width){let theme2=this.host.theme,cost=this.cost(),lines=[];for(let[rowIndex,rate]of COST_RATES.entries()){let value2=cost?.[rate];lines.push(renderKeyValueLine(theme2,{keyLabel:rate,valueText:value2===void 0?"0 (default)":`$${value2} / M tokens`,unset:value2===void 0,active:rowIndex===this.index,paneFocused:this.focused,editing:this.editingRate===rate?this.editing:void 0,width}))}let tiers=this.model.read().cost?.tiers;return tiers&&tiers.length>0&&lines.push(renderInfoLine(theme2,`tiers: ${tiers.length} (read-only; kept as-is)`,width)),this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?COST_RATES.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%COST_RATES.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.beginEdit("tweak");return}if(isPrintableInput(data)){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let rate=COST_RATES[this.index],current=this.cost()?.[rate],editor=new ValueEditor({onCommit:value2=>this.commit(rate,value2),onCancel:()=>{this.editing=void 0,this.editingRate=void 0,this.error=void 0,this.host.refresh()}});this.editing=editor,this.editingRate=rate,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current===void 0?"":String(current)),this.host.refresh()}commit(rate,raw){let value2=raw.trim(),parsed=value2===""?0:Number(value2);if(!Number.isFinite(parsed)||parsed<0){this.error="cost rates must be finite non-negative numbers.",this.host.refresh();return}this.error=void 0,this.editing=void 0,this.editingRate=void 0,this.host.mutate(()=>{this.model.read().cost?this.model.setField(["cost",rate],parsed):this.model.setField(["cost"],{input:0,output:0,cacheRead:0,cacheWrite:0,[rate]:parsed})})}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit"),keyHint("tui.select.cancel","back")].join(" ")}},ModelSpecificApiPane=class{constructor(host,model){this.crumb="Model-Specific API",this.rows=["baseUrl","apiType"],this.index=0,this.focused=!1,this.host=host,this.model=model}inherited(key){let provider=this.host.store.getProvider(this.host.providerId),providerValue=key==="api"?provider?.api:provider?.baseUrl;if(providerValue)return{value:providerValue,via:"provider"};let current=this.model.read(),effective=key==="api"?this.host.effectiveApi(current):this.host.effectiveBaseUrl(current);return effective?{value:effective,via:"built-in"}:void 0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;if(row==="baseUrl"){let override=current.baseUrl,inherited=override?void 0:this.inherited("baseUrl");lines.push(renderKeyValueLine(theme2,{keyLabel:"baseUrl",valueText:override??inherited?.value??"not set",unset:!override,note:inherited?`\xB7 ${inherited.via}`:void 0,active,paneFocused:this.focused,editing:this.editing,width}))}else{let override=current.api,inherited=override?void 0:this.inherited("api");lines.push(renderKeyValueLine(theme2,{keyLabel:"API Type",valueText:override??inherited?.value??"not set",unset:!override,note:inherited?`\xB7 ${inherited.via}`:void 0,active,paneFocused:this.focused,width}))}}this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2))));let hint2=baseUrlHint(this.host.effectiveApi(current));return hint2&&lines.push(renderInfoLine(theme2,hint2,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?this.rows.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%this.rows.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(new ModelApiTypePane(this.host,this.model)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let base=this.model.read().baseUrl??this.inherited("baseUrl")?.value??"",editor=new ValueEditor({onCommit:value2=>this.commit(value2),onCancel:()=>{this.editing=void 0,this.error=void 0,this.host.refresh()}});this.editing=editor,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(base),this.host.refresh()}commit(raw){let value2=raw.trim();if(value2){let invalid=validateBaseUrlValue(value2);if(invalid){this.error=invalid,this.host.refresh();return}}this.error=void 0,this.editing=void 0,this.host.mutate(()=>this.model.setField(["baseUrl"],value2===""?DELETE:value2))}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}},ModelApiTypePane=class{constructor(host,model){this.crumb="API Type",this.index=0,this.focused=!1,this.host=host,this.model=model;let current=model.read().api,options=this.options();this.index=Math.max(0,options.findIndex(option=>option.value===current))}fallback(){let provider=this.host.store.getProvider(this.host.providerId);return provider?.api??builtinDefaults(this.host.providerId,this.model.read().id,provider?.api).api}options(){let current=this.model.read().api,providerApi=this.host.store.getProvider(this.host.providerId)?.api,fallback=this.fallback(),options=[{label:providerApi?`provider: ${providerApi}`:fallback?`built-in: ${fallback}`:"no provider or built-in API",value:void 0}];for(let api of API_TYPES)options.push({label:api,value:api});return current&&!API_TYPES.includes(current)&&options.push({label:current,value:current}),options}render(width){let theme2=this.host.theme,current=this.model.read().api,lines=this.options().map((option,rowIndex)=>{let selected=option.value===current;return renderPlainLine(theme2,`${selected?"\u25CF":"\u25CB"} ${option.label}`,{active:rowIndex===this.index,paneFocused:this.focused,dim:option.value===void 0,width})});return this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings,options=this.options();if(kb.matches(data,"tui.select.up")){this.index=this.index===0?options.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%options.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let option=options[this.index];if(option.value===void 0&&!this.fallback()){this.error="Nothing to inherit \u2014 pick an API.",this.host.refresh();return}this.error=void 0,this.host.mutate(()=>this.model.setField(["api"],option.value??DELETE)),this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","select"),keyHint("tui.select.cancel","back")].join(" ")}};var ThinkingMapPane=class{constructor(host,model){this.crumb="thinkingLevelMap",this.mode={type:"levels"},this.index=0,this.focused=!1,this.host=host,this.model=model}map(){return this.model.read().thinkingLevelMap??{}}render(width){let theme2=this.host.theme,lines=[];if(this.model.read().reasoning!==!0&&lines.push(renderInfoLine(theme2,"reasoning is not true \u2014 the map is stored but currently has no effect.",width)),this.mode.type==="levels")for(let[rowIndex,level]of THINKING_LEVELS.entries()){let value2=this.map()[level],status=value2===void 0?"default":value2===null?"null (hidden)":value2;lines.push(renderKeyValueLine(theme2,{keyLabel:level,valueText:status,unset:value2===void 0,active:rowIndex===this.index,paneFocused:this.focused,width}))}else if(this.mode.type==="choice"){lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 mapping`,width));for(let[choiceIndex,label]of["String target (provider effort)","Hidden (null)","Default (remove key)"].entries())lines.push(renderPlainLine(theme2,label,{active:choiceIndex===this.mode.index,paneFocused:this.focused,width}))}else lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 non-empty provider effort`,width)),lines.push(renderKeyValueLine(theme2,{keyLabel:this.mode.level,active:!0,paneFocused:this.focused,editing:this.editor,width}));return this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="target"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editor?.handleInput(data),this.host.refresh();return}if(this.mode.type==="choice"){if(kb.matches(data,"tui.select.up")){this.mode={...this.mode,index:this.mode.index===0?2:this.mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...this.mode,index:(this.mode.index+1)%3},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"levels"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let{level,index:index3}=this.mode;if(index3===0){let editor=new ValueEditor({onCommit:value2=>{let target=value2.trim();if(!target)return this.error="A string target must be non-empty; use Hidden for null.",this.host.refresh();this.error=void 0,this.mode={type:"levels"},this.editor=void 0,this.host.mutate(()=>this.model.setField(["thinkingLevelMap",level],target))},onCancel:()=>{this.editor=void 0,this.mode={type:"levels"},this.host.refresh()}});this.editor=editor,editor.focused=this.focused;let existing=this.map()[level];typeof existing=="string"&&editor.beginTweak(existing),this.mode={type:"target",level},this.host.refresh();return}this.mode={type:"levels"},this.host.mutate(()=>this.model.setField(["thinkingLevelMap",level],index3===1?null:DELETE));return}return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?THINKING_LEVELS.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%THINKING_LEVELS.length,this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){this.mode={type:"choice",level:THINKING_LEVELS[this.index],index:0},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused,this.editor&&(this.editor.focused=focused&&this.mode.type==="target")}isEditing(){return this.mode.type==="target"}hints(){return this.mode.type==="target"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","back")].join(" "):[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.mode.type==="choice"?"set":"edit"),keyHint("tui.select.cancel","back")].join(" ")}};var DEFAULT_CONTEXT_WINDOW2=128e3,DEFAULT_MAX_TOKENS2=16384,ModelFieldsPane=class{constructor(host,model){this.index=0,this.focused=!1,this.renaming=!1,this.disposed=!1,this.host=host,this.model=model;let rows=[{kind:"text",key:"id"},{kind:"text",key:"name"},{kind:"reasoning"},{kind:"subpage",key:"thinkingLevelMap"},{kind:"subpage",key:"input"},{kind:"subpage",key:"cost"},{kind:"number",key:"contextWindow"},{kind:"number",key:"maxTokens"},{kind:"subpage",key:"compat"}];model.isDraft?rows.push({kind:"modelApi"}):rows.push({kind:"builtin"},{kind:"modelApi"},{kind:"deleteModel"}),this.rows=rows}startEditingId(){this.index=0,this.beginEdit("overwrite")}draftEmpty(){return this.model.isDraft&&Object.keys(this.model.read()).length===0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[],api=this.host.effectiveApi(current);lines.push(renderInfoLine(theme2,api?`api: ${api}${current.api?" (model)":""}`:"api: none resolved \u2014 see Model-Specific API below",width));for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;lines.push(this.renderRow(row,current,active,width))}return this.error&&lines.push(theme2.fg("error",truncate2(this.error,Math.max(10,width-2)))),this.renaming&&lines.push(renderInfoLine(theme2,"Saving model id\u2026",width)),lines}scrollWindow(){return{top:1,bottom:(this.error?1:0)+(this.renaming?1:0),cursor:1+this.index}}renderRow(row,current,active,width){let theme2=this.host.theme,editing=this.editingRow===row?this.editing:void 0;switch(row.kind){case"text":{let value2=current[row.key],unsetText=row.key==="id"?"required":"falls back to id";return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value2??`not set (${unsetText})`,unset:!value2,active,paneFocused:this.focused,editing,width})}case"reasoning":{let value2=current.reasoning;return renderKeyValueLine(theme2,{keyLabel:"reasoning",valueText:value2===void 0?"false (default)":String(value2),unset:value2===void 0,active,paneFocused:this.focused,width})}case"subpage":{let summary=this.subpageSummary(row.key,current);return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:summary.text,unset:summary.unset,active,paneFocused:this.focused,width})}case"number":{let value2=current[row.key],fallback=row.key==="contextWindow"?DEFAULT_CONTEXT_WINDOW2:DEFAULT_MAX_TOKENS2;return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value2===void 0?`${fallback} (default)`:String(value2),unset:value2===void 0,active,paneFocused:this.focused,editing,width})}case"builtin":{let id=current.id,count=id?matchBuiltinModels(id,this.host.effectiveApi(current)).length:0;return renderKeyValueLine(theme2,{valueText:"Use Built-in Data",active,paneFocused:this.focused,note:id?`\xB7 ${count} ${plural(count,"candidate")}`:"\xB7 set id first",width})}case"modelApi":return renderKeyValueLine(theme2,{valueText:"Model-Specific API",active,paneFocused:this.focused,note:`\xB7 ${this.modelApiSummary(current)}`,width});case"deleteModel":return renderKeyValueLine(theme2,{valueText:"Delete Model",active,paneFocused:this.focused,width})}}modelApiSummary(current){let overrides=[current.baseUrl?"baseUrl":"",current.api?"API Type":""].filter(Boolean);if(overrides.length>0)return overrides.join(" + ");let provider=this.host.store.getProvider(this.host.providerId);return provider?.api||provider?.baseUrl?"provider defaults":this.host.effectiveApi(current)||this.host.effectiveBaseUrl(current)?"built-in defaults":"not set"}subpageSummary(key,current){switch(key){case"thinkingLevelMap":{let map=current.thinkingLevelMap,count=map?Object.keys(map).length:0;return count>0?{text:`${count} ${plural(count,"mapping")}`,unset:!1}:{text:"default",unset:!0}}case"input":return current.input?{text:`[${current.input.join(", ")}]`,unset:!1}:{text:"[text] (default)",unset:!0};case"cost":{let cost=current.cost;return cost?{text:`$${cost.input} / $${cost.output} in/out`,unset:!1}:{text:"all 0 (default)",unset:!0}}case"compat":{let compat=current.compat,count=compat?Object.keys(compat).length:0;if(count>0)return{text:`${count} ${count===1?"entry":"entries"}`,unset:!1};let inherited=this.host.store.getProvider(this.host.providerId)?.compat,inheritedCount=inherited?Object.keys(inherited).length:0;return inheritedCount>0?{text:`${inheritedCount} from provider`,unset:!0}:{text:"none",unset:!0}}}}handleInput(data){if(this.renaming||this.disposed)return;let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}if(kb.matches(data,"tui.select.up")){this.index=this.index===0?this.rows.length-1:this.index-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.index=(this.index+1)%this.rows.length,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){if(!this.model.isDraft){this.host.popPane();return}if(this.draftEmpty()){this.host.discardModelDraft();return}let label=this.model.read().name??this.model.read().id??"New Model";this.host.confirm(`Discard the new model "${label}"? Its fields are not saved.`,"Discard Model",()=>this.host.discardModelDraft());return}if(kb.matches(data,"app.list.toggle")){this.toggleRow();return}if(kb.matches(data,"tui.select.confirm")){this.enterRow();return}if(isPrintableInput(data)){this.overwriteRow(data);return}}toggleRow(){if(this.rows[this.index].kind!=="reasoning")return;let current=this.model.read().reasoning;this.host.mutate(()=>this.model.setField(["reasoning"],current!==!0))}enterRow(){let row=this.rows[this.index];switch(row.kind){case"text":case"number":this.beginEdit("tweak");return;case"reasoning":this.host.pushPane(new ReasoningPane(this.host,this.model));return;case"subpage":this.pushSubpage(row.key);return;case"modelApi":this.host.pushPane(new ModelSpecificApiPane(this.host,this.model));return;case"builtin":{if(!this.model.read().id){this.host.notify("Set the model id first.","warning");return}this.host.pushPane(new BuiltinCandidatesPane(this.host,this.model));return}case"deleteModel":{let id=this.model.read().id;if(!id)return;if(this.host.isCurrentModel(id)){this.host.notify("The current model cannot be deleted; switch models with /model first.","error");return}this.host.confirm(`Delete model "${id}" from ${this.host.providerId}?`,"Delete Model",()=>{this.host.mutate(()=>this.host.store.removeModel(this.host.providerId,id)),this.host.onModelRemoved(id)});return}}}overwriteRow(data){let row=this.rows[this.index];if(row.kind==="text"||row.kind==="number"){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];if(row.kind!=="text"&&row.kind!=="number")return;let current=this.model.read()[row.key],editor=new ValueEditor({onCommit:value2=>this.commitText(row,value2),onCancel:()=>{if(this.editing=void 0,this.editingRow=void 0,this.error=void 0,this.draftEmpty()){this.host.discardModelDraft();return}this.host.refresh()}});this.editing=editor,this.editingRow=row,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current===void 0?"":String(current)),this.host.refresh()}commitText(row,raw){let value2=raw.trim(),finish=error=>{if(this.error=error,error){this.host.refresh();return}this.editing=void 0,this.editingRow=void 0,this.host.refresh()};if(row.key==="id"){if(!value2){finish("id is required and cannot be empty.");return}if(this.model.isDraft){this.model.setField(["id"],value2),finish(this.host.commitModelDraft());return}let current=this.model.read().id;if(!current){finish("Missing current id.");return}if(value2===current){finish();return}if(this.host.isCurrentModel(current)){finish("The current model's id cannot be renamed; switch models with /model first.");return}if(this.host.store.getModel(this.host.providerId,value2)){finish(`Model "${value2}" already exists.`);return}this.renaming=!0,this.host.refresh(),this.model.rename(value2).then(error=>{this.renaming=!1,this.disposed||finish(error)},error=>{this.renaming=!1,this.disposed||finish(error instanceof Error?error.message:String(error))});return}if(row.key==="name"){this.host.mutate(()=>this.model.setField(["name"],value2===""?DELETE:value2)),finish();return}if(value2===""){this.host.mutate(()=>this.model.setField([row.key],DELETE)),finish();return}let parsed=Number(value2);if(!Number.isSafeInteger(parsed)||parsed<=0){finish(`${row.key} must be a positive integer.`);return}this.host.mutate(()=>this.model.setField([row.key],parsed)),finish()}pushSubpage(key){switch(key){case"thinkingLevelMap":this.host.pushPane(new ThinkingMapPane(this.host,this.model));return;case"input":this.host.pushPane(new InputTypesPane(this.host,this.model));return;case"cost":this.host.pushPane(new CostPane(this.host,this.model));return;case"compat":this.host.pushPane(new CompatPane(this.host,this.model));return}}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0||this.renaming}dispose(){this.disposed=!0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("app.list.toggle","toggle"),keyHint("tui.select.cancel",this.model.isDraft?"discard":"back")].join(" ")}};var LEFT_WIDTH_MIN=16,LEFT_WIDTH_MAX=40,BODY_ROWS=14,MIN_WIDTH=56;function padTo(line,width){let missing=width-visibleWidth(line);return missing>0?line+" ".repeat(missing):line}function leftItemKey(item){return item?item.kind==="model"?`model:${item.modelId}`:item.kind:""}var ProviderEditorScreen=class{constructor(tui,theme2,keybindings,done,options){this.leftItems=[],this.leftIndex=0,this.focusPane="left",this.stack=[],this.disposed=!1,this.renaming=!1,this._focused=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.options=options,this.host=this.createHost(),this.rebuildLeftItems(),this.resetRightStack()}get focused(){return this._focused}set focused(value2){this._focused=value2,this.topPane()?.setFocused(value2&&this.focusPane==="right")}invalidate(){this.cache=void 0}dispose(){if(!this.disposed){this.disposed=!0;for(let pane of this.stack)pane.dispose?.();this.stack=[],hasProviderSettings(this.options.store.getProvider(this.options.providerId))||this.options.store.discardProviderDraft(this.options.providerId)}}render(width){if(this.cache&&this.cache.width===width)return this.cache.lines;let lines=this.renderFrame(width);return this.cache={width,lines},lines}handleInput(data){if(this.focusPane==="right"){let pane=this.topPane();if(pane&&!pane.isEditing?.()&&this.keybindings.matches(data,"app.provider.switchPaneLeft")){pane.setFocused(!1),this.focusPane="left",this.refresh();return}pane?.handleInput(data);return}let kb=this.keybindings;if(kb.matches(data,"tui.select.up")){this.moveLeft(-1);return}if(kb.matches(data,"tui.select.down")){this.moveLeft(1);return}if(kb.matches(data,"app.provider.switchPaneRight")){this.activateLeftItem("inspect");return}if(kb.matches(data,"tui.select.confirm")){this.activateLeftItem("activate");return}kb.matches(data,"tui.select.cancel")&&this.done("back")}syncFromStore(){if(this.disposed||this.renaming)return;let selected=this.leftItems[this.leftIndex],selectedKey=leftItemKey(selected);this.rebuildLeftItems();let nextIndex=this.leftItems.findIndex(item=>leftItemKey(item)===selectedKey);this.leftIndex=nextIndex>=0?nextIndex:Math.min(this.leftIndex,this.selectableIndex(0)),nextIndex<0&&selected?.kind==="model"&&this.resetRightStack(),this.refresh()}rebuildLeftItems(){let items=[{kind:"apiAuth"},{kind:"fetch"},{kind:"separator"}];for(let model of this.options.store.getModels(this.options.providerId))items.push({kind:"model",modelId:model.id});this.draft&&items.push({kind:"draft"}),items.push({kind:"separator"},{kind:"addModel"},{kind:"deleteProvider"}),this.leftItems=items}selectableIndex(start){let index3=this.leftItems.findIndex((item,i)=>i>=start&&item.kind!=="separator");return index3>=0?index3:0}moveLeft(delta){let selectable=this.leftItems.map((item,index3)=>({item,index:index3})).filter(entry=>entry.item.kind!=="separator");if(selectable.length===0)return;let position=selectable.findIndex(entry=>entry.index===this.leftIndex),next=selectable[(position+delta+selectable.length)%selectable.length];next.index!==this.leftIndex&&(this.leftIndex=next.index,this.resetRightStack(),this.refresh())}activateLeftItem(via){let item=this.leftItems[this.leftIndex];if(item)switch(item.kind){case"apiAuth":case"model":case"draft":this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return;case"fetch":if(this.focusPane="right",via==="activate"){let pane=this.topPane();pane instanceof FetchModelsPane&&pane.start()}this.topPane()?.setFocused(this._focused),this.refresh();return;case"addModel":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}this.draft||(this.draft={fields:{}},this.rebuildLeftItems());let draftIndex=this.leftItems.findIndex(entry=>entry.kind==="draft");draftIndex>=0&&(this.leftIndex=draftIndex),this.resetRightStack(),this.focusPane="right";let pane=this.topPane();pane?.setFocused(this._focused),pane instanceof ModelFieldsPane&&!this.draft.fields.id&&pane.startEditingId(),this.refresh();return}case"deleteProvider":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}if(this.host.isCurrentProvider()){this.host.notify("The current model's provider cannot be deleted; switch models with /model first.","error");return}let builtin=isBuiltinProviderId(this.options.providerId);this.host.confirm(`Delete provider "${this.options.providerId}" from models.json?`+(builtin?" The built-in catalog remains and its models may reappear.":"")+" Stored credentials in auth.json are kept.","Delete Provider",()=>{this.options.store.removeProvider(this.options.providerId),this.options.refresher.touch(this.options.providerId),this.done("deleted")});return}default:return}}renderLeft(width){let theme2=this.theme,focused=this.focusPane==="left",rows=[],renderRow=index3=>{let item=this.leftItems[index3];return item.kind==="separator"?theme2.fg("borderMuted",` ${"\u2500".repeat(Math.max(1,width-4))}`):this.renderLeftItem(item,index3===this.leftIndex,focused,width)};if(this.leftItems.length<=BODY_ROWS)for(let index3=0;index3<this.leftItems.length;index3++)rows.push(renderRow(index3));else{let slots=BODY_ROWS-1,start=Math.max(0,Math.min(this.leftIndex-Math.floor(slots/2),this.leftItems.length-slots));for(let index3=start;index3<start+slots;index3++)rows.push(renderRow(index3));let selectable=this.leftItems.filter(item=>item.kind!=="separator"),position=selectable.indexOf(this.leftItems[this.leftIndex]);rows.push(theme2.fg("dim",` (${position+1}/${selectable.length})`))}for(;rows.length<BODY_ROWS;)rows.push("");return rows}renderLeftItem(item,active,focused,width){let theme2=this.theme,store=this.options.store,lit=active&&focused,marker=lit?theme2.fg("accent",`${CURSOR} `):" ",style=(text3,dim2=!1)=>theme2.fg(lit?"accent":dim2?"dim":"text",text3),text2,note;switch(item.kind){case"apiAuth":text2="API Auth";break;case"fetch":text2="Fetch Models",note=this.fetchStatus;break;case"model":{let model=store.getModel(this.options.providerId,item.modelId);text2=model?modelDisplayName(model):item.modelId;break}case"draft":{text2=this.draft?.fields.name??this.draft?.fields.id??"New Model",note="\xB7 draft";break}case"addModel":text2="+ Add Model";break;case"deleteProvider":text2="Delete Provider";break;default:text2=""}let dim=item.kind==="draft"&&!this.draft?.fields.name&&!this.draft?.fields.id;if(item.kind==="model"||item.kind==="draft"){let budget=Math.max(8,width-2-(note?visibleWidth(note)+1:0));text2=truncateMiddle(text2,budget)}let noteText=note?theme2.fg("dim",` ${note}`):"";return truncateToWidth(marker+style(text2,dim)+noteText,width)}topPane(){return this.stack[this.stack.length-1]}pushPane(pane){this.topPane()?.setFocused(!1),this.focusPane="right",this.stack.push(pane),pane.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}popPane(){if(this.stack.length<=1){this.topPane()?.setFocused(!1),this.focusPane="left",this.refresh();return}let pane=this.stack.pop();pane?.setFocused(!1),pane?.dispose?.(),this.topPane()?.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}resetRightStack(){for(let pane of this.stack)pane.dispose?.();let item=this.leftItems[this.leftIndex];this.stack=[this.createBasePane(item)],this.topPane()?.setFocused(this._focused&&this.focusPane==="right")}createBasePane(item){switch(item?.kind){case"apiAuth":return new ApiAuthPane(this.host,this.options.registry);case"fetch":return new FetchModelsPane(this.host);case"model":return new ModelFieldsPane(this.host,this.persistedHandle(item.modelId));case"draft":return new ModelFieldsPane(this.host,this.draftHandle());case"addModel":return new InfoPane(this.host,["Press Enter to create a model.","A draft is kept in memory until its id is set; Esc on the draft discards it."],()=>this.activateLeftItem("activate"));case"deleteProvider":return new InfoPane(this.host,["Press Enter to delete this provider from models.json."],()=>this.activateLeftItem("activate"));default:return new InfoPane(this.host,[])}}persistedHandle(modelId2){let store=this.options.store,providerId=this.options.providerId,ref={id:modelId2},renamingSnapshot;return{isDraft:!1,read:()=>renamingSnapshot??store.getModel(providerId,ref.id)??{id:ref.id},setField:(path14,value2)=>{store.setModelField(providerId,ref.id,path14,value2)},rename:async newId=>{let oldId=ref.id;renamingSnapshot=store.getModel(providerId,oldId),this.renaming=!0;try{let error=await store.renameModel(providerId,oldId,newId);if(error)return error;ref.id=newId;let selected=this.leftItems[this.leftIndex];selected?.kind==="model"&&selected.modelId===oldId&&(selected.modelId=newId),this.options.refresher.touch(providerId);return}finally{renamingSnapshot=void 0,this.renaming=!1,this.syncFromStore()}}}}draftHandle(){let draft=this.draft;if(!draft)throw new Error("No model draft");return{isDraft:!0,rename:async()=>"Commit the model draft before renaming it.",read:()=>draft.fields,setField:(path14,value2)=>{if(path14.length===1){let key=path14[0];value2===DELETE?delete draft.fields[key]:draft.fields[key]=value2}else{let[head,...rest]=path14,container={...draft.fields[head]??{}},current=container;for(let segment2 of rest.slice(0,-1)){let next=current[segment2];if(typeof next=="object"&&next!==null&&!Array.isArray(next))current=next;else{let created={};current[segment2]=created,current=created}}let leaf=rest[rest.length-1];value2===DELETE?delete current[leaf]:current[leaf]=value2,draft.fields[head]=container}this.refresh()}}}createHost(){let store=this.options.store,providerId=this.options.providerId;return{tui:this.tui,theme:this.theme,keybindings:this.keybindings,store,refresher:this.options.refresher,providerId,pushPane:pane=>this.pushPane(pane),popPane:()=>this.popPane(),mutate:apply=>{let before=store.pendingCount;apply(),store.pendingCount!==before&&(!store.isDraftProvider(providerId)||hasProviderSettings(store.getProvider(providerId)))&&this.options.refresher.touch(providerId),this.refresh()},refresh:()=>this.refresh(),notify:(message,type)=>this.options.notify(message,type),effectiveApi:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).api,effectiveBaseUrl:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).baseUrl,commitModelDraft:()=>this.commitModelDraft(),discardModelDraft:()=>this.discardModelDraft(),isCurrentModel:modelId2=>this.options.currentModel?.provider===providerId&&this.options.currentModel.id===modelId2,isCurrentProvider:()=>this.options.currentModel?.provider===providerId,setFetchStatus:status=>{this.fetchStatus=status,this.refresh()},runFetch:signal=>fetchProviderModels(this.options,signal),importModels:async(models,signal)=>{let error=await importProviderModels(this.options,models,signal);return this.disposed||this.syncFromStore(),error},confirm:(message,actionLabel,action)=>this.pushPane(new ConfirmPane(this.host,message,actionLabel,action)),onModelRemoved:()=>{for(this.rebuildLeftItems(),this.leftIndex=Math.min(this.leftIndex,this.leftItems.length-1);this.leftIndex>0&&this.leftItems[this.leftIndex]?.kind==="separator";)this.leftIndex--;this.leftItems[this.leftIndex]?.kind==="separator"&&(this.leftIndex=this.selectableIndex(0)),this.focusPane="left",this.resetRightStack(),this.refresh()}}}discardModelDraft(){if(!this.draft)return;this.draft=void 0,this.rebuildLeftItems();let addIndex=this.leftItems.findIndex(item=>item.kind==="addModel");this.leftIndex=addIndex>=0?addIndex:this.selectableIndex(0),this.focusPane="left",this.resetRightStack(),this.refresh()}commitModelDraft(){let draft=this.draft;if(!draft)return"No model draft.";let id=(draft.fields.id??"").trim();if(!id)return"Model id is required.";if(this.options.store.getModel(this.options.providerId,id))return`Model "${id}" already exists.`;if(!this.host.effectiveApi(draft.fields))return"Cannot resolve an api \u2014 set one under Model-Specific API or the provider's API Auth.";if(!this.host.effectiveBaseUrl(draft.fields))return"Cannot resolve a baseUrl \u2014 set one under Model-Specific API or the provider's API Auth.";let model={...{...draft.fields},id};this.draft=void 0,this.host.mutate(()=>this.options.store.addModel(this.options.providerId,model)),this.rebuildLeftItems();let index3=this.leftItems.findIndex(item=>item.kind==="model"&&item.modelId===id);index3>=0&&(this.leftIndex=index3),this.resetRightStack(),this.refresh()}refresh(){this.invalidate(),this.tui.requestRender()}renderFrame(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0];if(width<MIN_WIDTH)return[border,truncateToWidth(theme2.fg("warning",` /provider needs at least ${MIN_WIDTH} columns`),width),border];let leftWidth=this.computeLeftWidth(width),rightWidth=width-leftWidth-3,separator=theme2.fg("border"," \u2502 "),title=this.renderTitle(width),crumb=truncateToWidth(this.theme.fg("muted",this.topPane()?.crumb??""),rightWidth),leftLines=this.renderLeft(leftWidth),pane=this.topPane(),paneLines=pane?windowLines(theme2,pane.render(rightWidth),BODY_ROWS-1,pane.scrollWindow?.()):[],rightLines=[crumb,...paneLines],body=[];for(let row=0;row<BODY_ROWS;row++){let left=padTo(truncateToWidth(leftLines[row]??"",leftWidth),leftWidth),right=truncateToWidth(rightLines[row]??"",rightWidth);body.push(left+separator+right)}let footerLines=this.renderFooter(width);return[border,title,border,...body,border,...footerLines,border]}computeLeftWidth(width){let longest=12;for(let item of this.leftItems){if(item.kind==="separator")continue;let label="";switch(item.kind){case"apiAuth":label="API Auth";break;case"fetch":label=`Fetch Models${this.fetchStatus?` ${this.fetchStatus}`:""}`;break;case"model":{let model=this.options.store.getModel(this.options.providerId,item.modelId);label=model?modelDisplayName(model):item.modelId;break}case"draft":label=`${this.draft?.fields.name??this.draft?.fields.id??"New Model"} \xB7 draft`;break;case"addModel":label="+ Add Model";break;case"deleteProvider":label="Delete Provider";break}longest=Math.max(longest,visibleWidth(label))}let fit=Math.max(LEFT_WIDTH_MIN,Math.min(LEFT_WIDTH_MAX,longest+2));return Math.min(fit,Math.max(LEFT_WIDTH_MIN,Math.floor(width*.45)))}renderTitle(width){let theme2=this.theme,title=` /provider \xB7 ${this.options.providerId}`;return isBuiltinProviderId(this.options.providerId)&&(title+=" \xB7 overlays built-in catalog"),truncateToWidth(theme2.fg("accent",theme2.bold(title)),width)}renderFooter(width){if(this.focusPane==="right"){let hints2=[this.topPane()?.hints()??"",keyHint("app.provider.switchPaneLeft","focus left")].filter(Boolean).join(" ");return[truncateToWidth(hints2,width)]}let hints=[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.leftActivateLabel()),keyHint("app.provider.switchPaneRight","focus right"),keyHint("tui.select.cancel","back")].join(" ");return[truncateToWidth(hints,width)]}leftActivateLabel(){switch(this.leftItems[this.leftIndex]?.kind){case"fetch":return"fetch";case"addModel":return"create";case"deleteProvider":return"delete";default:return"open"}}};function modelDisplayName(model){return model.name??model.id}var LIST_ROWS=12,ProviderListScreen=class{constructor(tui,theme2,keybindings,done,store){this.mode="list",this.query="",this.index=0,this.active=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.store=store,this.input=new ValueEditor({onCommit:()=>this.confirm(),onCancel:()=>this.cancel()})}get focused(){return this.active}set focused(value2){this.active=value2,this.input.focused=value2}invalidate(){}filtered(){let ids=this.store.getProviderIds();return this.query.trim()?fuzzyFilter(ids,this.query,id=>id):ids}render(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",lines=[border,truncateToWidth(theme2.fg("accent",theme2.bold(" /provider \u2014 models.json providers")),width),border,renderKeyValueLine(theme2,{keyLabel:this.mode==="list"?"Search":"Provider id",active:!1,paneFocused:this.active,editing:this.input,width}),""],area=[];if(this.mode==="list"){let entries=this.filtered(),total=entries.length+1;this.index=Math.min(this.index,total-1);let rows=[];for(let row=0;row<total;row++){let id=entries[row-1],provider=id===void 0?void 0:this.store.getProvider(id),note=id===void 0?void 0:provider?[`${String(provider.models?.length??0)} ${plural(provider.models?.length??0,"model")}`,provider.api].filter(Boolean).join(" \xB7 "):"pending deletion";rows.push(renderPlainLine(theme2,row===0?"+ Add Provider":id,{active:row===this.index,paneFocused:this.active,note,width}))}entries.length===0&&rows.push(renderInfoLine(theme2,this.query?"No matching providers.":"No providers yet.",width)),area.push(...windowLines(theme2,rows,LIST_ROWS,{cursor:this.index}))}else this.error&&area.push(truncateToWidth(theme2.fg("error",this.error),width));for(;area.length<LIST_ROWS;)area.push("");let hints=this.mode==="newProvider"?[keyHint("tui.input.submit","create"),keyHint("tui.select.cancel","cancel")]:[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","open"),keyHint("tui.select.cancel","close")];return[...lines,...area,border,truncateToWidth(hints.join(" "),width),border]}handleInput(data){let kb=this.keybindings;if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.mode==="list"){let total=this.filtered().length+1;if(kb.matches(data,"tui.select.up"))this.index=(this.index+total-1)%total;else if(kb.matches(data,"tui.select.down"))this.index=(this.index+1)%total;else if(kb.matches(data,"tui.select.confirm")){this.confirm();return}else{let previous=this.query;this.input.handleInput(data),this.query=this.input.value,this.query!==previous&&(this.index=this.query&&this.filtered().length>0?1:0)}}else this.input.handleInput(data);this.tui.requestRender()}confirm(){if(this.mode==="newProvider"){let id=this.input.value.trim();if(!id)this.error="Provider id must be non-empty.";else if(this.store.getProviderIds().includes(id))this.error="This provider id already exists.";else{this.store.ensureProviderView(id),this.done({kind:"open",providerId:id});return}}else if(this.index===0)this.mode="newProvider",this.error=void 0,this.input.reset(this.query);else{let id=this.filtered()[this.index-1];id&&this.done({kind:"open",providerId:id})}this.tui.requestRender()}cancel(){if(this.mode==="list"){this.done({kind:"close"});return}this.mode="list",this.error=void 0,this.input.reset(this.query),this.tui.requestRender()}};var ProviderTuiSession=class extends Container{constructor(tui){super(),this.controller=new AbortController,this.active=!1,this.tui=tui}get signal(){return this.controller.signal}get focused(){return this.active}set focused(value2){this.active=value2,this.screen&&isFocusable(this.screen)&&(this.screen.focused=value2)}setScreen(screen){if(this.signal.aborted){screen.dispose?.();return}this.disposeScreen(),this.screen=screen,this.clear(),this.addChild(screen),this.tui.setFocus(this),this.tui.requestRender()}handleInput(data){this.signal.aborted||this.screen?.handleInput?.(data)}dispose(){this.signal.aborted||(this.controller.abort(),this.disposeScreen(),this.clear())}disposeScreen(){let previous=this.screen;this.screen=void 0,previous&&isFocusable(previous)&&(previous.focused=!1),previous?.dispose?.()}};var SavingScreen=class extends Container{constructor(theme2,keybindings,onCancel){super(),this.keybindings=keybindings,this.onCancel=onCancel,this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2))),this.addChild(new Text(theme2.fg("muted","Saving provider changes and updating models\u2026"),1,1)),this.addChild(new Text(keyHint("tui.select.cancel","return to providers"),1,0)),this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2)))}handleInput(data){this.keybindings.matches(data,"tui.select.cancel")&&this.onCancel()}};function createProviderErrorScreen(tui,done,error){return new ExtensionSelectorComponent("models.json cannot be edited",["Back"],done,done,{tui,description:`${truncate2(error,2400)}
|
|
1565
1565
|
|
|
1566
|
-
Fix the file manually and open /provider again.`})}function createProviderApp(tui,theme2,keybindings,done,options){let{store,registry,runtime}=options,session=new ProviderTuiSession(tui),refresher=new RefreshCoordinator(runtime),activeEditor,closing;function notify(message,type){session.signal.aborted||options.notify(message,type)}store.onSaveResult=result2=>{session.signal.aborted||((result2.kind==="invalid"||result2.kind==="error")&¬ify(result2.error,"error"),activeEditor?.syncFromStore(),tui.requestRender())};function showList(){session.signal.aborted||(activeEditor=void 0,session.setScreen(new ProviderListScreen(tui,theme2,keybindings,result2=>{result2.kind==="close"?requestClose():openProvider(result2.providerId)},store)))}function openProvider(providerId){if(!store.getProviderIds().includes(providerId)){notify(`No provider ${JSON.stringify(providerId)} in models.json.`,"warning"),showList();return}activeEditor=new ProviderEditorScreen(tui,theme2,keybindings,showList,{store,refresher,providerId,registry,runtime,currentModel:options.getCurrentModel(),notify}),session.setScreen(activeEditor)}function showUnsaved(error){let back="Return to providers",retry="Retry saving",discard="Discard unsaved changes and close";session.setScreen(new ExtensionSelectorComponent("Some changes are not saved",[back,retry,discard],choice=>{if(choice===back){showList();return}choice===retry&&store.retrySave(),choice===discard&&store.discardPending(),requestClose()},showList,{tui,description:truncate2(error,2400)}))}function requestClose(){if(closing||session.signal.aborted)return;let controller=new AbortController;closing=controller;let signal=AbortSignal.any([session.signal,controller.signal]);activeEditor=void 0,session.setScreen(new SavingScreen(theme2,keybindings,()=>{controller.abort(),closing=void 0,showList()})),finishClose(controller,signal)}async function finishClose(controller,signal){try{if(await store.flush(),signal.aborted)return;let unsaved=store.getPendingError();if(unsaved){closing=void 0,showUnsaved(unsaved);return}let outcome=await refresher.flush(signal);if(signal.aborted)return;outcome.ok||notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`,"warning");let current=options.getCurrentModel();if(current&&refresher.touchedProviders.includes(current.provider)){let refreshed=registry.find(current.provider,current.id);refreshed&&!await options.setModel(refreshed)&¬ify("Reselect the current model with /model to apply its updated configuration.","warning"),refreshed||notify("The current model is no longer available; select another with /model.","warning")}signal.aborted||done()}catch(error){signal.aborted||(notify(formatError(error),"error"),showList())}finally{closing===controller&&(closing=void 0)}}return options.initialProviderId?openProvider(options.initialProviderId):showList(),session}function providerExtension(pi){let modelsPath;pi.on("session_start",(_event,ctx)=>{modelsPath=ctx.modelRuntime.getModelsPath()}),pi.registerCommand(COMMAND_NAME,{description:COMMAND_DESCRIPTION,getArgumentCompletions:async prefix=>{if(!modelsPath)return null;let load=await ModelsJsonStore.load(modelsPath);if(!load.ok)return null;let query=prefix.trim().toLowerCase(),items=load.store.getProviderIds().filter(id=>id.toLowerCase().startsWith(query)).map(id=>{let count=load.store.getModels(id).length;return{value:id,label:id,description:`${String(count)} ${plural(count,"model")}`}});return items.length?items:null},handler:async(args,ctx)=>{if(!ctx.hasUI||ctx.mode!=="tui"){ctx.ui.notify(NO_UI_WARNING,"warning");return}let path14=ctx.modelRuntime.getModelsPath();if(modelsPath=path14,!path14){ctx.ui.notify(NO_MODELS_FILE_WARNING,"warning");return}try{let load=await ModelsJsonStore.load(path14);if(!load.ok){await ctx.ui.custom((tui,_theme,_keybindings,done)=>createProviderErrorScreen(tui,done,load.error));return}await ctx.ui.custom((tui,theme2,keybindings,done)=>createProviderApp(tui,theme2,keybindings,done,{store:load.store,runtime:ctx.modelRuntime,registry:ctx.modelRegistry,getCurrentModel:()=>ctx.model,setModel:model=>pi.setModel(model),notify:(message,type)=>ctx.ui.notify(message,type),initialProviderId:args.trim()||void 0}))}catch(error){ctx.ui.notify(formatError(error),"error")}}})}var QUESTION_TOOL_NAME="question",QUESTION_LABEL="Question",QUESTION_DESCRIPTION="Ask the user 1-4 structured multiple-choice questions and return their selections. Never author an 'Other'-style option or a vague label like 'Option A' \u2014 the UI adds a custom-answer path itself. If you recommend an option, put it first and append ' (Recommended)' to its label.",QUESTION_PROMPT_SNIPPET="Ask the user structured multiple-choice questions when blocked on a decision only they can make",QUESTION_PROMPT_GUIDELINES=["Use `question` only for decisions you cannot resolve from the request, the code, or sensible defaults (direction, preference, permissions, destructive choices); for everything else choose a reasonable default and state it.","Batch related decisions into one `question` call (1-4 questions); ask no more than needed to unblock the next step.","Treat `question` answers as decisions: act on them without re-litigating, and do not re-ask unless circumstances change."];registerListKeybindings();function ruleBorder(theme2,width,color2="accent"){return theme2.fg(color2,"\u2500".repeat(Math.max(0,width)))}function wrapWithPrefix(prefix,text2,width,outputLines){let prefixWidth=visibleWidth(prefix);if(prefixWidth>=width){for(let line of wrapTextWithAnsi(prefix+text2,width))outputLines.push(line);return}let wrappedLines=wrapTextWithAnsi(text2,width-prefixWidth),continuationPrefix=" ".repeat(prefixWidth);for(let lineIndex=0;lineIndex<wrappedLines.length;lineIndex++)outputLines.push(`${lineIndex===0?prefix:continuationPrefix}${wrappedLines[lineIndex]}`)}var QUESTION_LIMITS={questionChars:400,headerChars:32,optionLabelChars:80,optionDescriptionChars:300,previewChars:8e3,userTextChars:4e3,modelResultChars:12e3},TRUNCATION_FOLLOW_UP="Ask the user a focused follow-up question to clarify the omitted portion.";var PreviewLinesCache=class{constructor(){this.cache=new Map}get(previewText,width,maxLines,compute){let byDimensions=this.cache.get(previewText);byDimensions||(byDimensions=new Map,this.cache.set(previewText,byDimensions));let key=`${width}x${maxLines}`,lines=byDimensions.get(key);return lines||(lines=compute(),byDimensions.set(key,lines)),lines}},WidthCachedRender=class{invalidate(){this.cachedLines=void 0}get(width,height,compute){return this.cachedLines!==void 0&&this.cachedWidth===width&&this.cachedHeight===height?this.cachedLines:(this.cachedLines=compute(width,height),this.cachedWidth=width,this.cachedHeight=height,this.cachedLines)}};var OTHER_OPTION={kind:"other",label:"Type something"};function newQuestionState(){return{optionIndex:0,multiSelected:new Set,notesByOption:new Map}}function selectedCustomAnswer(state2){return state2.customAnswer?.selected?state2.customAnswer:void 0}function hasMultiAnswer(state2){return state2.multiSelected.size>0||selectedCustomAnswer(state2)!==void 0}function hasAnswer(state2){return!!state2.singleAnswer||hasMultiAnswer(state2)}function displayOptions(question2){return[...question2.options.map((option,optionIndex)=>({...option,kind:"option",optionIndex})),OTHER_OPTION]}function noteEntries(state2,allowedOptions){let allowed=new Set(allowedOptions),entries=[...state2.notesByOption.entries()].filter(([option])=>allowed.has(option)).filter(([,text2])=>text2.trim().length>0).map(([option,text2])=>({option,text:text2.trim()}));return entries.length?entries:void 0}function firstUnanswered(states2){for(let i=0;i<states2.length;i++){let state2=states2[i];if(!hasAnswer(state2))return i}}function orderedAnswers(questions,states2){let answers=[];for(let i=0;i<questions.length;i++){let question2=questions[i],state2=states2[i];if(state2.singleAnswer){let notes=state2.singleAnswer.kind==="option"&&state2.singleAnswer.answer?noteEntries(state2,[state2.singleAnswer.answer]):void 0;answers.push(notes?{...state2.singleAnswer,notes}:state2.singleAnswer);continue}if(question2.multiSelect&&hasMultiAnswer(state2)){let selected=[];for(let idx of[...state2.multiSelected].sort((a,b2)=>a-b2)){let option=question2.options[idx];option&&selected.push(option.label)}let custom=selectedCustomAnswer(state2);custom&&selected.push(custom.text);let notes=noteEntries(state2,selected);answers.push({questionIndex:i,question:question2.question,header:question2.header,kind:"multi",answer:null,selected,...notes?{notes}:{}})}}return answers}var PREVIEW_MAX_LINES=16,PREVIEW_CHROME_ROWS=18,VIEWPORT_SCROLL_STEP=4;function applyVerticalViewport(lines,width,terminalRows,theme2,options={}){let maxRows=Math.max(1,Math.floor(terminalRows));if(lines.length<=maxRows)return{lines,start:0,maxStart:0};if(maxRows<5){let anchor=Math.max(0,Math.min(lines.length-1,options.anchorLine??0)),start2=Math.max(0,Math.min(lines.length-maxRows,anchor-Math.floor(maxRows/2)));return{lines:lines.slice(start2,start2+maxRows),start:start2,maxStart:lines.length-maxRows}}let first=lines[0]??"",last=lines[lines.length-1]??"",body=lines.slice(1,-1),contentRows=maxRows-4,maxStart=Math.max(0,body.length-contentRows),anchorInBody=Math.max(0,Math.min(body.length-1,(options.anchorLine??1)-1)),requestedStart=options.preferredStart??Math.max(0,anchorInBody-Math.floor(contentRows/2)),start=Math.max(0,Math.min(maxStart,requestedStart)),bottomHidden=Math.max(0,body.length-start-contentRows),indicator=text2=>theme2.fg("dim",truncateToWidth(text2,Math.max(1,width)));return{lines:[first,start>0?indicator(`\u2191 ${start} rows hidden`):"",...body.slice(start,start+contentRows),bottomHidden>0?indicator(`\u2193 ${bottomHidden} rows hidden`):"",last],start,maxStart}}function createQuestionDialog(questions,signal){return(tui,theme2,keybindings,done)=>{let currentIdx=0,view="question",inputMode,noteTarget,notesSnapshot,reviewScrollOffset=0,reviewMaxScrollOffset=0,dialogFocused=!1,footerFocused=!1,finished=!1,cache=new WidthCachedRender,previewCache=new PreviewLinesCache,states2=questions.map(()=>newQuestionState()),optionsByQuestion=questions.map(question2=>displayOptions(question2)),editorTheme={borderColor:s=>theme2.fg("accent",s),selectList:{selectedPrefix:t=>theme2.fg("accent",t),selectedText:t=>theme2.fg("accent",t),description:t=>theme2.fg("muted",t),scrollInfo:t=>theme2.fg("dim",t),noMatch:t=>theme2.fg("warning",t)}},editor=new Editor(tui,editorTheme),currentQuestion=()=>questions[currentIdx],currentState=()=>states2[currentIdx],currentOptions=()=>optionsByQuestion[currentIdx],keyMatches=(data,keybinding)=>keybindings.matches(data,keybinding),keyLabel2=keybinding=>keyLabel(keybinding,{keybindings}),keyAction=(keybinding,action)=>{let label=keyLabel2(keybinding);return label?`${label} ${action}`:""},editorSubmitAction=action=>{let label=keyLabel("tui.input.submit");return label?`${label} ${action}`:""},keyGroupAction=(bindings,action)=>{let labels=bindings.map(keyLabel2).filter(Boolean).join("/");return labels?`${labels} ${action}`:""},joinHints=(...hints)=>hints.filter(Boolean).join(" \u2022 ");function finish(result2){finished||(finished=!0,done(result2))}let onAbort=()=>finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"});signal?.aborted?onAbort():signal?.addEventListener("abort",onAbort,{once:!0});function refresh(){cache.invalidate(),tui.requestRender()}function syncEditorFocus(){editor.focused=dialogFocused&&inputMode!==void 0}function setCurrentIdx(index3){currentIdx=Math.max(0,Math.min(questions.length-1,index3)),view="question",inputMode=void 0,noteTarget=void 0,reviewScrollOffset=0,reviewMaxScrollOffset=0,notesSnapshot=void 0,footerFocused=!1,editor.setText(""),syncEditorFocus(),refresh()}function clearWarning(){currentState().warning=void 0}function focusedOption(){return currentOptions()[currentState().optionIndex]}function showReview(){let missing=firstUnanswered(states2);if(missing!==void 0){setCurrentIdx(missing),currentState().warning="Answer this question before reviewing your answers.",refresh();return}view="review",inputMode=void 0,noteTarget=void 0,reviewScrollOffset=0,reviewMaxScrollOffset=0,footerFocused=!1,editor.setText(""),syncEditorFocus(),refresh()}function advanceAfterAnswer(){if(questions.length===1&&!currentQuestion().multiSelect){finish({answers:orderedAnswers(questions,states2),outcome:"answered"});return}let missing=firstUnanswered(states2);if(missing===void 0){showReview();return}setCurrentIdx(missing)}function beginCustomInput(){let state2=currentState();inputMode="custom",noteTarget=void 0;let existingSingle=state2.singleAnswer?.kind==="custom"?state2.singleAnswer.answer:void 0;editor.setText(state2.customAnswer?.text??existingSingle??""),syncEditorFocus(),refresh()}function selectSingleOption(option){let question2=currentQuestion(),state2=currentState();state2.singleAnswer={questionIndex:currentIdx,question:question2.question,header:question2.header,kind:"option",answer:option.label,...option.preview?{preview:option.preview}:{}},state2.warning=void 0}function beginNotesInput(){let question2=currentQuestion(),state2=currentState(),option=focusedOption();if(!option||option.kind==="other"){beginCustomInput();return}if(question2.multiSelect&&!state2.multiSelected.has(option.optionIndex)){state2.warning="Select the option first, then add notes.",refresh();return}question2.multiSelect||(notesSnapshot={prior:state2.singleAnswer},selectSingleOption(option)),inputMode="notes",noteTarget=option.label,editor.setText(state2.notesByOption.get(option.label)??""),syncEditorFocus(),refresh()}function recordSingle(option){if(option.kind==="other"){if(currentState().singleAnswer?.kind==="custom"){advanceAfterAnswer();return}beginCustomInput();return}selectSingleOption(option),advanceAfterAnswer()}function recordMulti(){let state2=currentState();if(!hasMultiAnswer(state2)){state2.warning="Select at least one option, type a custom answer, or cancel the questions.",refresh();return}state2.warning=void 0,advanceAfterAnswer()}function toggleMultiOption(option){let state2=currentState();if(option.kind==="other"){if(state2.customAnswer)state2.customAnswer.selected=!state2.customAnswer.selected,clearWarning();else{let tabKey=keyLabel2("tui.input.tab");state2.warning=tabKey?`Press ${tabKey} to type a custom answer.`:"Choose Type something to type a custom answer."}return}state2.multiSelected.has(option.optionIndex)?state2.multiSelected.delete(option.optionIndex):state2.multiSelected.add(option.optionIndex),clearWarning()}function finishReview(){let missing=firstUnanswered(states2);if(missing!==void 0){setCurrentIdx(missing),currentState().warning="Answer this question before submitting.",refresh();return}finish({answers:orderedAnswers(questions,states2),outcome:"answered"})}editor.onSubmit=value2=>{let trimmed=value2.trim(),question2=currentQuestion(),state2=currentState();if(trimmed.length>QUESTION_LIMITS.userTextChars){state2.warning=`Keep notes and custom answers under ${QUESTION_LIMITS.userTextChars} characters.`,refresh();return}if(inputMode==="notes"){noteTarget&&(trimmed?state2.notesByOption.set(noteTarget,trimmed):state2.notesByOption.delete(noteTarget)),inputMode=void 0,noteTarget=void 0,notesSnapshot=void 0,editor.setText(""),syncEditorFocus(),refresh();return}if(inputMode==="custom"){if(!trimmed){inputMode=void 0,editor.setText(""),syncEditorFocus(),refresh();return}if(question2.multiSelect){state2.customAnswer={text:trimmed,selected:!0},state2.optionIndex=question2.options.length,inputMode=void 0,editor.setText(""),syncEditorFocus(),refresh();return}state2.singleAnswer={questionIndex:currentIdx,question:question2.question,header:question2.header,kind:"custom",answer:trimmed},inputMode=void 0,editor.setText(""),syncEditorFocus(),advanceAfterAnswer()}};function handleReviewInput(data){if(keyMatches(data,"tui.select.up")){reviewScrollOffset=Math.max(0,reviewScrollOffset-VIEWPORT_SCROLL_STEP),refresh();return}if(keyMatches(data,"tui.select.down")){reviewScrollOffset=Math.min(reviewMaxScrollOffset,reviewScrollOffset+VIEWPORT_SCROLL_STEP),refresh();return}if(keyMatches(data,"tui.editor.cursorLeft")){setCurrentIdx(questions.length-1);return}if(keyMatches(data,"tui.select.confirm")){finishReview();return}keyMatches(data,"tui.select.cancel")&&setCurrentIdx(questions.length-1)}function handleQuestionInput(data){if(inputMode){if(keyMatches(data,"tui.select.cancel")){inputMode==="notes"&¬esSnapshot&&(currentState().singleAnswer=notesSnapshot.prior),inputMode=void 0,noteTarget=void 0,notesSnapshot=void 0,editor.setText(""),syncEditorFocus(),refresh();return}editor.handleInput(data),refresh();return}if(keyMatches(data,"tui.editor.cursorLeft")){currentIdx>0&&setCurrentIdx(currentIdx-1);return}if(keyMatches(data,"tui.editor.cursorRight")){currentIdx<questions.length-1?setCurrentIdx(currentIdx+1):firstUnanswered(states2)===void 0&&showReview();return}let state2=currentState(),options=currentOptions();if(keyMatches(data,"tui.select.up")){footerFocused?(footerFocused=!1,state2.optionIndex=options.length-1):state2.optionIndex>0&&state2.optionIndex--,clearWarning(),refresh();return}if(keyMatches(data,"tui.select.down")){if(footerFocused)return;state2.optionIndex<options.length-1?state2.optionIndex++:footerFocused=!0,clearWarning(),refresh();return}if(keyMatches(data,"tui.input.tab")){footerFocused||beginNotesInput();return}if(data.length===1&&data>="1"&&data<="9"){let index3=data.charCodeAt(0)-49,target=options[index3];target&&(footerFocused=!1,state2.optionIndex=index3,clearWarning(),currentQuestion().multiSelect?(toggleMultiOption(target),refresh()):recordSingle(target));return}if(footerFocused){if(keyMatches(data,"tui.select.confirm")){finish({answers:orderedAnswers(questions,states2),outcome:"needs_clarification"});return}keyMatches(data,"tui.select.cancel")&&finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"});return}let question2=currentQuestion(),option=options[state2.optionIndex];if(question2.multiSelect&&keyMatches(data,"app.list.toggle")){option&&toggleMultiOption(option),refresh();return}if(keyMatches(data,"tui.select.confirm")){if(question2.multiSelect){if(option?.kind==="other"&&!state2.customAnswer){beginCustomInput();return}recordMulti()}else option&&recordSingle(option);return}keyMatches(data,"tui.select.cancel")&&finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"})}function handleInput(data){view==="review"?handleReviewInput(data):handleQuestionInput(data)}function render2(width){return cache.get(width,tui.terminal.rows,compute)}function renderTabs(renderWidth,lines){if(questions.length<2)return;let tabCount=questions.length+1,headerWidth=Math.max(4,Math.floor((renderWidth-tabCount*5)/tabCount)),tabs=[...questions.map((question2,index3)=>{let answered=hasAnswer(states2[index3]),label=` ${answered?"\u25A0":"\u25A1"} ${truncateToWidth(question2.header,headerWidth)} `;return view==="question"&&index3===currentIdx?theme2.bg("selectedBg",theme2.fg(answered?"success":"text",label)):theme2.fg(answered?"success":"muted",label)}),view==="review"?theme2.bg("selectedBg",theme2.fg("text"," \u2713 Submit ")):theme2.fg(firstUnanswered(states2)===void 0?"success":"dim"," \u2713 Submit ")].join(" ");wrapWithPrefix(" ",tabs,renderWidth,lines),lines.push("")}function previewLines(previewText,width,terminalRows){let maxLines=Math.max(4,Math.min(PREVIEW_MAX_LINES,terminalRows-PREVIEW_CHROME_ROWS));return previewCache.get(previewText,width,maxLines,()=>{let rendered=new Markdown(previewText,1,0,getMarkdownTheme()).render(Math.max(1,width));return rendered.length<=maxLines?rendered:[...rendered.slice(0,maxLines),theme2.fg("dim",truncateToWidth(`\u2026 ${rendered.length-maxLines} preview lines hidden`,Math.max(1,width)))]})}function multiMarker(option,checked,hasCustomAnswer){return option.kind==="other"&&!hasCustomAnswer?" ":checked?theme2.fg("success","[x]"):theme2.fg("dim","[ ]")}function renderReview(renderWidth,lines){wrapWithPrefix(" ",theme2.fg("accent","Review answers"),renderWidth,lines),lines.push("");for(let answer of orderedAnswers(questions,states2)){wrapWithPrefix(" ",theme2.fg("text",`${answer.questionIndex+1}. ${answer.question}`),renderWidth,lines);let response=answer.kind==="multi"?answer.selected?.join(", ")??"(no input)":answer.answer??"(no input)";wrapWithPrefix(" ",theme2.fg("success",response),renderWidth,lines);for(let note of answer.notes??[])wrapWithPrefix(" ",theme2.fg("muted",`Note for ${note.option}: ${note.text}`),renderWidth,lines);lines.push("")}wrapWithPrefix(" ",theme2.fg("dim",joinHints(keyAction("tui.select.confirm","submit"),keyAction("tui.select.cancel","edit last question"),keyGroupAction(["tui.select.up","tui.select.down"],"scroll"))),renderWidth,lines)}function compute(width,terminalRows){let lines=[],renderWidth=Math.max(1,width);if(lines.push(ruleBorder(theme2,renderWidth)),renderTabs(renderWidth,lines),view==="review"){renderReview(renderWidth,lines),lines.push(ruleBorder(theme2,renderWidth));let viewport=applyVerticalViewport(lines,renderWidth,terminalRows,theme2,{preferredStart:reviewScrollOffset});return reviewMaxScrollOffset=viewport.maxStart,reviewScrollOffset=viewport.start,viewport.lines}let question2=currentQuestion(),state2=currentState(),options=currentOptions(),isMulti=question2.multiSelect===!0,digitRange=`1-${Math.min(9,options.length)}`;wrapWithPrefix(" ",`${theme2.fg("accent",question2.header)} ${theme2.fg("text",question2.question)}`,renderWidth,lines),lines.push("");let optionLines=[],focusedOptionStart=0,focusedOptionEnd=0,inputAnchorOffset,hasPreview=inputMode===void 0&&!isMulti&&options.some(option=>option.kind==="option"&&option.preview),showPreviewSideBySide=hasPreview&&renderWidth>=60,listWidth=showPreviewSideBySide?Math.max(20,Math.floor(renderWidth*.4)):renderWidth;for(let index3=0;index3<options.length;index3++){let option=options[index3],focused=!footerFocused&&index3===state2.optionIndex,checked=isMulti&&(option.kind==="option"&&state2.multiSelected.has(option.optionIndex)||option.kind==="other"&&state2.customAnswer?.selected===!0),selectedSingle=!isMulti&&(option.kind==="other"?state2.singleAnswer?.kind==="custom":state2.singleAnswer?.answer===option.label),marker=isMulti?multiMarker(option,checked,state2.customAnswer!==void 0):" ",focusArrow=focused?theme2.fg("accent","\u2192"):" ",note=option.kind==="option"&&state2.notesByOption.has(option.label)?theme2.fg("success"," +note"):"",customText=option.kind==="other"?state2.customAnswer?.text??(state2.singleAnswer?.kind==="custom"?state2.singleAnswer.answer:void 0):void 0,labelText=customText?`${option.label} \u270E ${customText}`:option.label,label=`${index3+1}. ${labelText}${selectedSingle?" \u2713":""}${note}`,color2=focused?"accent":selectedSingle||checked?"success":"text";focused&&(focusedOptionStart=optionLines.length),wrapWithPrefix(`${focusArrow} ${marker} `,theme2.fg(color2,label),listWidth,optionLines),option.kind==="option"&&option.description&&wrapWithPrefix(" ",theme2.fg("muted",option.description),listWidth,optionLines),focused&&(focusedOptionEnd=optionLines.length)}if(inputMode){optionLines.push("");let label=inputMode==="notes"?`Notes for ${noteTarget??"option"}:`:"Your answer:";wrapWithPrefix(" ",theme2.fg("muted",label),listWidth,optionLines);for(let line of editor.render(Math.max(1,listWidth-2)))optionLines.push(` ${line}`);inputAnchorOffset=Math.max(0,optionLines.length-1)}let optionListStartLine=lines.length;if(showPreviewSideBySide){let rightWidth=renderWidth-listWidth-2,focused=options[state2.optionIndex],previewText=focused?.kind==="option"&&focused.preview?focused.preview:"",preview=previewText?previewLines(previewText,rightWidth,terminalRows):[theme2.fg("dim","(no preview)")],rightLines=[...Array.from({length:focusedOptionStart},()=>""),...preview],maxRows=Math.max(optionLines.length,rightLines.length),pad2=" ".repeat(2);for(let row=0;row<maxRows;row++){let left=row<optionLines.length?optionLines[row]:"",leftPadded=left+" ".repeat(Math.max(0,listWidth-visibleWidth(left))),right=row<rightLines.length?rightLines[row]:"";lines.push(`${leftPadded}${pad2}${right}`)}}else{if(hasPreview){let focused=options[state2.optionIndex],previewText=focused?.kind==="option"&&focused.preview?focused.preview:"";previewText&&optionLines.splice(focusedOptionEnd,0,"",ruleBorder(theme2,renderWidth,"dim"),...previewLines(previewText,renderWidth,terminalRows))}lines.push(...optionLines)}lines.push("");let chatLine=lines.length,chatPrefix=footerFocused?theme2.fg("accent","\u2192"):" ";wrapWithPrefix(`${chatPrefix} `,theme2.fg(footerFocused?"accent":"text","Chat about this"),renderWidth,lines);let warningLine;if(state2.warning&&(lines.push(""),warningLine=lines.length,wrapWithPrefix(" ",theme2.fg("warning",state2.warning),renderWidth,lines)),lines.push(""),inputMode==="notes")wrapWithPrefix(" ",theme2.fg("dim",joinHints(editorSubmitAction("save notes"),keyAction("tui.select.cancel","back"))),renderWidth,lines);else if(inputMode==="custom"){let hint2=isMulti?"save custom answer":"continue";wrapWithPrefix(" ",theme2.fg("dim",joinHints(editorSubmitAction(hint2),keyAction("tui.select.cancel","back"))),renderWidth,lines)}else footerFocused?wrapWithPrefix(" ",theme2.fg("dim",joinHints(keyAction("tui.select.confirm","discuss"),keyAction("tui.select.up","return to options"),keyAction("tui.select.cancel","cancel"))),renderWidth,lines):isMulti?wrapWithPrefix(" ",theme2.fg("dim",joinHints(`${digitRange} toggle`,keyAction("app.list.toggle","toggle focused"),keyAction("tui.input.tab","notes/custom"),keyAction("tui.select.confirm","continue"),keyGroupAction(["tui.editor.cursorLeft","tui.editor.cursorRight"],"questions"),keyAction("tui.select.cancel","cancel"))),renderWidth,lines):wrapWithPrefix(" ",theme2.fg("dim",joinHints(`${digitRange} select`,keyAction("tui.input.tab","notes/custom"),keyAction("tui.select.confirm","select"),keyGroupAction(["tui.editor.cursorLeft","tui.editor.cursorRight"],"questions"),keyAction("tui.select.cancel","cancel"))),renderWidth,lines);lines.push(ruleBorder(theme2,renderWidth));let anchorLine=optionListStartLine+focusedOptionStart;return inputAnchorOffset!==void 0?anchorLine=optionListStartLine+inputAnchorOffset:warningLine!==void 0?anchorLine=warningLine:footerFocused&&(anchorLine=chatLine),applyVerticalViewport(lines,renderWidth,terminalRows,theme2,{anchorLine}).lines}return{get focused(){return dialogFocused},set focused(value2){dialogFocused=value2,syncEditorFocus()},render:render2,invalidate:()=>{cache.invalidate()},handleInput,dispose(){signal?.removeEventListener("abort",onAbort)}}}}var DECLINE_MESSAGE="User declined to answer the questions.",CLARIFICATION_MESSAGE="The user wants to discuss these questions before choosing an answer.",ENVELOPE_PREFIX="User decisions:",ENVELOPE_SUFFIX="Continue with these decisions in mind.";function buildToolResult(text2,details){return{content:[{type:"text",text:text2}],details}}function boundedText2(text2){if(text2.length<=QUESTION_LIMITS.modelResultChars)return text2;let suffix=`
|
|
1566
|
+
Fix the file manually and open /provider again.`})}function createProviderApp(tui,theme2,keybindings,done,options){let{store,registry,runtime}=options,session=new ProviderTuiSession(tui),refresher=new RefreshCoordinator(runtime),activeEditor,closing;function notify(message,type){session.signal.aborted||options.notify(message,type)}store.onSaveResult=result2=>{session.signal.aborted||((result2.kind==="invalid"||result2.kind==="error")&¬ify(result2.error,"error"),activeEditor?.syncFromStore(),tui.requestRender())};function showList(){session.signal.aborted||(activeEditor=void 0,session.setScreen(new ProviderListScreen(tui,theme2,keybindings,result2=>{result2.kind==="close"?requestClose():openProvider(result2.providerId)},store)))}function openProvider(providerId){if(!store.getProviderIds().includes(providerId)){notify(`No provider ${JSON.stringify(providerId)} in models.json.`,"warning"),showList();return}activeEditor=new ProviderEditorScreen(tui,theme2,keybindings,showList,{store,refresher,providerId,registry,runtime,currentModel:options.getCurrentModel(),notify}),session.setScreen(activeEditor)}function showUnsaved(error){let back="Return to providers",retry="Retry saving",discard="Discard unsaved changes and close";session.setScreen(new ExtensionSelectorComponent("Some changes are not saved",[back,retry,discard],choice=>{if(choice===back){showList();return}choice===retry&&store.retrySave(),choice===discard&&store.discardPending(),requestClose()},showList,{tui,description:truncate2(error,2400)}))}function requestClose(){if(closing||session.signal.aborted)return;let controller=new AbortController;closing=controller;let signal=AbortSignal.any([session.signal,controller.signal]);activeEditor=void 0,session.setScreen(new SavingScreen(theme2,keybindings,()=>{controller.abort(),closing=void 0,showList()})),finishClose(controller,signal)}async function finishClose(controller,signal){try{if(await store.flush(),signal.aborted)return;let unsaved=store.getPendingError();if(unsaved){closing=void 0,showUnsaved(unsaved);return}let outcome=await refresher.flush(signal);if(signal.aborted)return;outcome.ok||notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`,"warning");let current=options.getCurrentModel();if(current&&refresher.touchedProviders.includes(current.provider)){let refreshed=registry.find(current.provider,current.id);refreshed&&!await options.setModel(refreshed)&¬ify("Reselect the current model with /model to apply its updated configuration.","warning"),refreshed||notify("The current model is no longer available; select another with /model.","warning")}signal.aborted||done()}catch(error){signal.aborted||(notify(formatError(error),"error"),showList())}finally{closing===controller&&(closing=void 0)}}return options.initialProviderId?openProvider(options.initialProviderId):showList(),session}function providerExtension(pi){let modelsPath;pi.on("session_start",(_event,ctx)=>{modelsPath=ctx.modelRuntime.getModelsPath()}),pi.registerCommand(COMMAND_NAME,{description:COMMAND_DESCRIPTION,getArgumentCompletions:async prefix=>{if(!modelsPath)return null;let load=await ModelsJsonStore.load(modelsPath);if(!load.ok)return null;let query=prefix.trim().toLowerCase(),items=load.store.getProviderIds().filter(id=>id.toLowerCase().startsWith(query)).map(id=>{let count=load.store.getModels(id).length;return{value:id,label:id,description:`${String(count)} ${plural(count,"model")}`}});return items.length?items:null},handler:async(args,ctx)=>{if(!ctx.hasUI||ctx.mode!=="tui"){ctx.ui.notify(NO_UI_WARNING,"warning");return}let path14=ctx.modelRuntime.getModelsPath();if(modelsPath=path14,!path14){ctx.ui.notify(NO_MODELS_FILE_WARNING,"warning");return}try{let load=await ModelsJsonStore.load(path14);if(!load.ok){await ctx.ui.custom((tui,_theme,_keybindings,done)=>createProviderErrorScreen(tui,done,load.error));return}await ctx.ui.custom((tui,theme2,keybindings,done)=>createProviderApp(tui,theme2,keybindings,done,{store:load.store,runtime:ctx.modelRuntime,registry:ctx.modelRegistry,getCurrentModel:()=>ctx.model,setModel:model=>pi.setModel(model),notify:(message,type)=>ctx.ui.notify(message,type),initialProviderId:args.trim()||void 0}))}catch(error){ctx.ui.notify(formatError(error),"error")}}})}var QUESTION_TOOL_NAME="question",QUESTION_LABEL="Question",QUESTION_DESCRIPTION="Ask the user 1-4 structured multiple-choice questions and return their selections. Never author an 'Other'-style option or a vague label like 'Option A' \u2014 the UI adds a custom-answer path itself. If you recommend an option, put it first and append ' (Recommended)' to its label.",QUESTION_PROMPT_SNIPPET="Ask the user structured multiple-choice questions when blocked on a decision only they can make",QUESTION_PROMPT_GUIDELINES=["Use `question` only for decisions you cannot resolve from the request, the code, or sensible defaults (direction, preference, permissions, destructive choices); for everything else choose a reasonable default and state it.","Batch related decisions into one `question` call (1-4 questions); ask no more than needed to unblock the next step.","Treat `question` answers as decisions: act on them without re-litigating, and do not re-ask unless circumstances change."];registerListKeybindings();var DetailPane=class{constructor(){this.key="",this.offset=0,this.maxOffset=0,this.pageRows=1}reset(){this.key="",this.offset=0,this.maxOffset=0}page(direction){this.offset=Math.max(0,Math.min(this.maxOffset,this.offset+direction*this.pageRows))}render(key,title,content,width,rows,scrollHint,theme2){this.key!==key&&(this.key=key,this.offset=0);let bodyRows=Math.max(1,rows-2),wasAtEnd=this.maxOffset>0&&this.offset===this.maxOffset;this.maxOffset=Math.max(0,content.length-bodyRows),this.offset=wasAtEnd?this.maxOffset:Math.min(this.offset,this.maxOffset),this.pageRows=Math.max(1,bodyRows-1);let body=content.slice(this.offset,this.offset+bodyRows);if(rows<3)return body.slice(0,rows);let lines=[theme2.fg("muted",truncateToWidth(` ${title.replace(/\s+/gu," ")}`,width)),...body];if(this.maxOffset>0){for(;lines.length<rows-1;)lines.push("");let range2=`${this.offset+1}\u2013${this.offset+body.length}/${content.length}`;lines.push(theme2.fg("dim",truncateToWidth(` ${range2}${scrollHint?` \u2022 ${scrollHint}`:""}`,width)))}return lines}};function ruleBorder(theme2,width,color2="accent"){return theme2.fg(color2,"\u2500".repeat(Math.max(0,width)))}function wrapWithPrefix(prefix,text2,width,outputLines){let prefixWidth=visibleWidth(prefix);if(prefixWidth>=width){for(let line of wrapTextWithAnsi(prefix+text2,width))outputLines.push(line);return}let wrappedLines=wrapTextWithAnsi(text2,width-prefixWidth),continuationPrefix=" ".repeat(prefixWidth);for(let lineIndex=0;lineIndex<wrappedLines.length;lineIndex++)outputLines.push(`${lineIndex===0?prefix:continuationPrefix}${wrappedLines[lineIndex]}`)}var QUESTION_LIMITS={questionChars:400,headerChars:32,optionLabelChars:80,optionDescriptionChars:300,previewChars:8e3,userTextChars:4e3,modelResultChars:12e3},TRUNCATION_FOLLOW_UP="Ask the user a focused follow-up question to clarify the omitted portion.";function moreOptionsHint(direction,count){let arrow=direction==="up"?"\u2191":"\u2193";return count<=0?`${arrow} more ${direction==="up"?"above":"below"}`:`${arrow} ${count} more option${count===1?"":"s"}`}function windowItems(items,focus,rows){let count=items.length,total=items.reduce((sum,item)=>sum+item.height,0),build=(first,last,contentRows)=>({first,last,contentRows,showAbove:first>0,showBelow:last<count-1,hiddenAbove:items.slice(0,first).filter(item=>item.countsAsOption).length,hiddenBelow:items.slice(last+1).filter(item=>item.countsAsOption).length});if(total<=rows)return build(0,count-1,rows);let windowFor=contentRows=>{let first=focus,last=focus,used=items[focus].height;for(let grew=!0;grew;)grew=!1,last+1<count&&used+items[last+1].height<=contentRows&&(last++,used+=items[last].height,grew=!0),first>0&&used+items[first-1].height<=contentRows&&(first--,used+=items[first].height,grew=!0);return build(first,last,contentRows)};if(rows<=2)return{...windowFor(Math.max(1,rows)),showAbove:!1,showBelow:!1};let window2=windowFor(rows-2);return window2.first===0||window2.last===count-1?windowFor(rows-1):window2}var PreviewLinesCache=class{constructor(){this.cache=new Map}get(previewText,width,compute){let byWidth=this.cache.get(previewText);byWidth||(byWidth=new Map,this.cache.set(previewText,byWidth));let lines=byWidth.get(width);return lines||(lines=compute(),byWidth.set(width,lines)),lines}},WidthCachedRender=class{invalidate(){this.cachedLines=void 0}get(width,height,compute){return this.cachedLines!==void 0&&this.cachedWidth===width&&this.cachedHeight===height?this.cachedLines:(this.cachedLines=compute(width,height),this.cachedWidth=width,this.cachedHeight=height,this.cachedLines)}};var OTHER_OPTION={kind:"other",label:"Type something"};function newQuestionState(){return{optionIndex:0,multiSelected:new Set,notesByOption:new Map}}function selectedCustomAnswer(state2){return state2.customAnswer?.selected?state2.customAnswer:void 0}function hasMultiAnswer(state2){return state2.multiSelected.size>0||selectedCustomAnswer(state2)!==void 0}function hasAnswer(state2){return!!state2.singleAnswer||hasMultiAnswer(state2)}function displayOptions(question2){return[...question2.options.map((option,optionIndex)=>({...option,kind:"option",optionIndex})),OTHER_OPTION]}function noteEntries(state2,allowedOptions){let allowed=new Set(allowedOptions),entries=[...state2.notesByOption.entries()].filter(([option])=>allowed.has(option)).filter(([,text2])=>text2.trim().length>0).map(([option,text2])=>({option,text:text2.trim()}));return entries.length?entries:void 0}function firstUnanswered(states2){for(let i=0;i<states2.length;i++){let state2=states2[i];if(!hasAnswer(state2))return i}}function orderedAnswers(questions,states2){let answers=[];for(let i=0;i<questions.length;i++){let question2=questions[i],state2=states2[i];if(state2.singleAnswer){let notes=state2.singleAnswer.kind==="option"&&state2.singleAnswer.answer?noteEntries(state2,[state2.singleAnswer.answer]):void 0;answers.push(notes?{...state2.singleAnswer,notes}:state2.singleAnswer);continue}if(question2.multiSelect&&hasMultiAnswer(state2)){let selected=[];for(let idx of[...state2.multiSelected].sort((a,b2)=>a-b2)){let option=question2.options[idx];option&&selected.push(option.label)}let custom=selectedCustomAnswer(state2);custom&&selected.push(custom.text);let notes=noteEntries(state2,selected);answers.push({questionIndex:i,question:question2.question,header:question2.header,kind:"multi",answer:null,selected,...notes?{notes}:{}})}}return answers}var DIALOG_MAX_FRACTION=.5,DIALOG_MIN_ROWS=16,VIEWPORT_SCROLL_STEP=4;function dialogRowBudget(terminalRows){let rows=Math.max(1,Math.floor(terminalRows));return Math.min(rows,Math.max(DIALOG_MIN_ROWS,Math.floor(rows*DIALOG_MAX_FRACTION)))}function applyVerticalViewport(lines,width,maxRows,theme2,options={}){if(lines.length<=maxRows)return{lines,start:0,maxStart:0};if(maxRows<5){let anchor=Math.max(0,Math.min(lines.length-1,options.anchorLine??0)),start2=Math.max(0,Math.min(lines.length-maxRows,anchor-Math.floor(maxRows/2)));return{lines:lines.slice(start2,start2+maxRows),start:start2,maxStart:lines.length-maxRows}}let first=lines[0]??"",last=lines[lines.length-1]??"",body=lines.slice(1,-1),contentRows=maxRows-4,maxStart=Math.max(0,body.length-contentRows),anchorInBody=Math.max(0,Math.min(body.length-1,(options.anchorLine??1)-1)),requestedStart=options.preferredStart??Math.max(0,anchorInBody-Math.floor(contentRows/2)),start=Math.max(0,Math.min(maxStart,requestedStart)),bottomHidden=Math.max(0,body.length-start-contentRows),indicator=text2=>theme2.fg("dim",truncateToWidth(text2,Math.max(1,width)));return{lines:[first,start>0?indicator(`\u2191 ${start} rows hidden`):"",...body.slice(start,start+contentRows),bottomHidden>0?indicator(`\u2193 ${bottomHidden} rows hidden`):"",last],start,maxStart}}function createQuestionDialog(questions,signal){return(tui,theme2,keybindings,done)=>{let currentIdx=0,view="question",inputMode,noteTarget,notesSnapshot,reviewScrollOffset=0,reviewMaxScrollOffset=0,dialogFocused=!1,footerFocused=!1,finished=!1,cache=new WidthCachedRender,previewCache=new PreviewLinesCache,details=new DetailPane,states2=questions.map(()=>newQuestionState()),optionsByQuestion=questions.map(question2=>displayOptions(question2)),editorTheme={borderColor:s=>theme2.fg("accent",s),selectList:{selectedPrefix:t=>theme2.fg("accent",t),selectedText:t=>theme2.fg("accent",t),description:t=>theme2.fg("muted",t),scrollInfo:t=>theme2.fg("dim",t),noMatch:t=>theme2.fg("warning",t)}},editor=new Editor(tui,editorTheme),currentQuestion=()=>questions[currentIdx],currentState=()=>states2[currentIdx],currentOptions=()=>optionsByQuestion[currentIdx],keyMatches=(data,keybinding)=>keybindings.matches(data,keybinding),keyLabel2=keybinding=>keyLabel(keybinding,{keybindings}),keyAction=(keybinding,action)=>{let label=keyLabel2(keybinding);return label?`${label} ${action}`:""},editorSubmitAction=action=>{let label=keyLabel("tui.input.submit");return label?`${label} ${action}`:""},keyGroupAction=(bindings,action)=>{let labels=bindings.map(keyLabel2).filter(Boolean).join("/");return labels?`${labels} ${action}`:""},joinHints=(...hints)=>hints.filter(Boolean).join(" \u2022 ");function finish(result2){finished||(finished=!0,done(result2))}let onAbort=()=>finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"});signal?.aborted?onAbort():signal?.addEventListener("abort",onAbort,{once:!0});function refresh(){cache.invalidate(),tui.requestRender()}function syncEditorFocus(){editor.focused=dialogFocused&&inputMode!==void 0}function setCurrentIdx(index3){details.reset(),currentIdx=Math.max(0,Math.min(questions.length-1,index3)),view="question",inputMode=void 0,noteTarget=void 0,reviewScrollOffset=0,reviewMaxScrollOffset=0,notesSnapshot=void 0,footerFocused=!1,editor.setText(""),syncEditorFocus(),refresh()}function clearWarning(){currentState().warning=void 0}function focusedOption(){return currentOptions()[currentState().optionIndex]}function showReview(){let missing=firstUnanswered(states2);if(missing!==void 0){setCurrentIdx(missing),currentState().warning="Answer this question before reviewing your answers.",refresh();return}view="review",inputMode=void 0,noteTarget=void 0,reviewScrollOffset=0,reviewMaxScrollOffset=0,footerFocused=!1,editor.setText(""),syncEditorFocus(),refresh()}function advanceAfterAnswer(){if(questions.length===1&&!currentQuestion().multiSelect){finish({answers:orderedAnswers(questions,states2),outcome:"answered"});return}let missing=firstUnanswered(states2);if(missing===void 0){showReview();return}setCurrentIdx(missing)}function beginCustomInput(){details.reset();let state2=currentState();inputMode="custom",noteTarget=void 0;let existingSingle=state2.singleAnswer?.kind==="custom"?state2.singleAnswer.answer:void 0;editor.setText(state2.customAnswer?.text??existingSingle??""),syncEditorFocus(),refresh()}function selectSingleOption(option){let question2=currentQuestion(),state2=currentState();state2.singleAnswer={questionIndex:currentIdx,question:question2.question,header:question2.header,kind:"option",answer:option.label,...option.preview?{preview:option.preview}:{}},state2.warning=void 0}function beginNotesInput(){details.reset();let question2=currentQuestion(),state2=currentState(),option=focusedOption();if(!option||option.kind==="other"){beginCustomInput();return}if(question2.multiSelect&&!state2.multiSelected.has(option.optionIndex)){state2.warning="Select the option first, then add notes.",refresh();return}question2.multiSelect||(notesSnapshot={prior:state2.singleAnswer},selectSingleOption(option)),inputMode="notes",noteTarget=option.label,editor.setText(state2.notesByOption.get(option.label)??""),syncEditorFocus(),refresh()}function recordSingle(option){if(option.kind==="other"){if(currentState().singleAnswer?.kind==="custom"){advanceAfterAnswer();return}beginCustomInput();return}selectSingleOption(option),advanceAfterAnswer()}function recordMulti(){let state2=currentState();if(!hasMultiAnswer(state2)){state2.warning="Select at least one option, type a custom answer, or cancel the questions.",refresh();return}state2.warning=void 0,advanceAfterAnswer()}function toggleMultiOption(option){let state2=currentState();if(option.kind==="other"){if(state2.customAnswer)state2.customAnswer.selected=!state2.customAnswer.selected,clearWarning();else{let tabKey=keyLabel2("tui.input.tab");state2.warning=tabKey?`Press ${tabKey} to type a custom answer.`:"Choose Type something to type a custom answer."}return}state2.multiSelected.has(option.optionIndex)?state2.multiSelected.delete(option.optionIndex):state2.multiSelected.add(option.optionIndex),clearWarning()}function finishReview(){let missing=firstUnanswered(states2);if(missing!==void 0){setCurrentIdx(missing),currentState().warning="Answer this question before submitting.",refresh();return}finish({answers:orderedAnswers(questions,states2),outcome:"answered"})}editor.onSubmit=value2=>{let trimmed=value2.trim(),question2=currentQuestion(),state2=currentState();if(trimmed.length>QUESTION_LIMITS.userTextChars){state2.warning=`Keep notes and custom answers under ${QUESTION_LIMITS.userTextChars} characters.`,refresh();return}if(inputMode==="notes"){noteTarget&&(trimmed?state2.notesByOption.set(noteTarget,trimmed):state2.notesByOption.delete(noteTarget)),inputMode=void 0,noteTarget=void 0,notesSnapshot=void 0,editor.setText(""),syncEditorFocus(),refresh();return}if(inputMode==="custom"){if(!trimmed){inputMode=void 0,editor.setText(""),syncEditorFocus(),refresh();return}if(question2.multiSelect){state2.customAnswer={text:trimmed,selected:!0},state2.optionIndex=question2.options.length,inputMode=void 0,editor.setText(""),syncEditorFocus(),refresh();return}state2.singleAnswer={questionIndex:currentIdx,question:question2.question,header:question2.header,kind:"custom",answer:trimmed},inputMode=void 0,editor.setText(""),syncEditorFocus(),advanceAfterAnswer()}};function handleReviewInput(data){if(keyMatches(data,"tui.select.up")){reviewScrollOffset=Math.max(0,reviewScrollOffset-VIEWPORT_SCROLL_STEP),refresh();return}if(keyMatches(data,"tui.select.down")){reviewScrollOffset=Math.min(reviewMaxScrollOffset,reviewScrollOffset+VIEWPORT_SCROLL_STEP),refresh();return}if(keyMatches(data,"tui.editor.cursorLeft")){setCurrentIdx(questions.length-1);return}if(keyMatches(data,"tui.select.confirm")){finishReview();return}keyMatches(data,"tui.select.cancel")&&setCurrentIdx(questions.length-1)}function handleQuestionInput(data){if(inputMode){if(keyMatches(data,"tui.select.cancel")){inputMode==="notes"&¬esSnapshot&&(currentState().singleAnswer=notesSnapshot.prior),inputMode=void 0,noteTarget=void 0,notesSnapshot=void 0,editor.setText(""),syncEditorFocus(),refresh();return}editor.handleInput(data),refresh();return}if(keyMatches(data,"tui.editor.cursorLeft")){currentIdx>0&&setCurrentIdx(currentIdx-1);return}if(keyMatches(data,"app.question.pageUp")||keyMatches(data,"app.question.pageDown")){render2(tui.terminal.columns),details.page(keyMatches(data,"app.question.pageUp")?-1:1),refresh();return}if(keyMatches(data,"tui.editor.cursorRight")){currentIdx<questions.length-1?setCurrentIdx(currentIdx+1):firstUnanswered(states2)===void 0&&showReview();return}let state2=currentState(),options=currentOptions();if(keyMatches(data,"tui.select.up")){footerFocused?(footerFocused=!1,state2.optionIndex=options.length-1):state2.optionIndex>0&&state2.optionIndex--,clearWarning(),refresh();return}if(keyMatches(data,"tui.select.down")){if(footerFocused)return;state2.optionIndex<options.length-1?state2.optionIndex++:footerFocused=!0,clearWarning(),refresh();return}if(keyMatches(data,"tui.input.tab")){footerFocused||beginNotesInput();return}if(data.length===1&&data>="1"&&data<="9"){let index3=data.charCodeAt(0)-49,target=options[index3];target&&(footerFocused=!1,state2.optionIndex=index3,clearWarning(),currentQuestion().multiSelect?(toggleMultiOption(target),refresh()):recordSingle(target));return}if(footerFocused){if(keyMatches(data,"tui.select.confirm")){finish({answers:orderedAnswers(questions,states2),outcome:"needs_clarification"});return}keyMatches(data,"tui.select.cancel")&&finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"});return}let question2=currentQuestion(),option=options[state2.optionIndex];if(question2.multiSelect&&keyMatches(data,"app.list.toggle")){option&&toggleMultiOption(option),refresh();return}if(keyMatches(data,"tui.select.confirm")){if(question2.multiSelect){if(option?.kind==="other"&&!state2.customAnswer){beginCustomInput();return}recordMulti()}else option&&recordSingle(option);return}keyMatches(data,"tui.select.cancel")&&finish({answers:orderedAnswers(questions,states2),outcome:"cancelled"})}function handleInput(data){view==="review"?handleReviewInput(data):handleQuestionInput(data)}function render2(width){return cache.get(width,tui.terminal.rows,compute)}function renderTabs(renderWidth,lines){if(questions.length<2)return;let tabCount=questions.length+1,headerWidth=Math.max(4,Math.floor((renderWidth-tabCount*5)/tabCount)),tabs=[...questions.map((question2,index3)=>{let answered=hasAnswer(states2[index3]),label=` ${answered?"\u25A0":"\u25A1"} ${truncateToWidth(question2.header,headerWidth)} `;return view==="question"&&index3===currentIdx?theme2.bg("selectedBg",theme2.fg(answered?"success":"text",label)):theme2.fg(answered?"success":"muted",label)}),view==="review"?theme2.bg("selectedBg",theme2.fg("text"," \u2713 Submit ")):theme2.fg(firstUnanswered(states2)===void 0?"success":"dim"," \u2713 Submit ")].join(" ");wrapWithPrefix(" ",tabs,renderWidth,lines)}function previewLines(previewText,width){return previewCache.get(previewText,width,()=>new Markdown(previewText,1,0,getMarkdownTheme()).render(Math.max(1,width)))}function multiMarker(option,checked,hasCustomAnswer){return option.kind==="other"&&!hasCustomAnswer?" ":checked?theme2.fg("success","[x]"):theme2.fg("dim","[ ]")}function renderReview(renderWidth,lines){wrapWithPrefix(" ",theme2.fg("accent","Review answers"),renderWidth,lines),lines.push("");for(let answer of orderedAnswers(questions,states2)){wrapWithPrefix(" ",theme2.fg("text",`${answer.questionIndex+1}. ${answer.question}`),renderWidth,lines);let response=answer.kind==="multi"?answer.selected?.join(", ")??"(no input)":answer.answer??"(no input)";wrapWithPrefix(" ",theme2.fg("success",response),renderWidth,lines);for(let note of answer.notes??[])wrapWithPrefix(" ",theme2.fg("muted",`Note for ${note.option}: ${note.text}`),renderWidth,lines);lines.push("")}wrapWithPrefix(" ",theme2.fg("dim",joinHints(keyAction("tui.select.confirm","submit"),keyAction("tui.select.cancel","edit last question"),keyGroupAction(["tui.select.up","tui.select.down"],"scroll"))),renderWidth,lines)}function renderQuestionFooter(renderWidth,digitRange){let state2=currentState(),isMulti=currentQuestion().multiSelect===!0,lines=[],chatPrefix=footerFocused?theme2.fg("accent","\u2192"):" ";wrapWithPrefix(`${chatPrefix} `,theme2.fg(footerFocused?"accent":"text","Chat about this"),renderWidth,lines),state2.warning&&(lines.push(""),wrapWithPrefix(" ",theme2.fg("warning",state2.warning),renderWidth,lines));let hints;inputMode==="notes"?hints=joinHints(editorSubmitAction("save notes"),keyAction("tui.select.cancel","back")):inputMode==="custom"?hints=joinHints(editorSubmitAction(isMulti?"save custom answer":"continue"),keyAction("tui.select.cancel","back")):footerFocused?hints=joinHints(keyAction("tui.select.confirm","discuss"),keyAction("tui.select.up","return to options"),keyAction("tui.select.cancel","cancel")):isMulti?hints=joinHints(keyGroupAction(["tui.select.up","tui.select.down"],"navigate"),`${digitRange} toggle`,keyAction("app.list.toggle","toggle focused"),keyAction("tui.input.tab","notes/custom"),keyAction("tui.select.confirm","continue"),questions.length>1?keyGroupAction(["tui.editor.cursorLeft","tui.editor.cursorRight"],"questions"):"",keyAction("tui.select.cancel","cancel")):hints=joinHints(keyGroupAction(["tui.select.up","tui.select.down"],"navigate"),`${digitRange} select`,keyAction("tui.input.tab","notes/custom"),keyAction("tui.select.confirm","select"),questions.length>1?keyGroupAction(["tui.editor.cursorLeft","tui.editor.cursorRight"],"questions"):"",keyAction("tui.select.cancel","cancel"));let hintLine="";for(let hint2 of hints.split(" \u2022 ")){let joined=hintLine?`${hintLine} \u2022 ${hint2}`:hint2;hintLine&&visibleWidth(joined)>renderWidth-1?(wrapWithPrefix(" ",theme2.fg("dim",hintLine),renderWidth,lines),hintLine=hint2):hintLine=joined}return hintLine&&wrapWithPrefix(" ",theme2.fg("dim",hintLine),renderWidth,lines),lines.push(ruleBorder(theme2,renderWidth)),lines}function windowOptionLines(optionLines,items,focus,rows,width){let window2=windowItems(items,focus,rows),rowsBefore=count=>items.slice(0,count).reduce((sum,item)=>sum+item.height,0),from=rowsBefore(window2.first),block=optionLines.slice(from,rowsBefore(window2.last+1)),visible=applyVerticalViewport(block,width,window2.contentRows,theme2,{anchorLine:Math.max(0,block.findIndex(line=>line.includes(CURSOR_MARKER)))}).lines;if(!window2.showAbove&&!window2.showBelow)return{rows:visible,focusRow:rowsBefore(focus)-from};let hint2=(direction,count)=>theme2.fg("dim",` ${truncateToWidth(moreOptionsHint(direction,count),Math.max(1,width-1))}`),spare=Array.from({length:Math.max(0,window2.contentRows-visible.length)},()=>"");return{rows:[...window2.showAbove?[hint2("up",window2.hiddenAbove)]:[],...visible,...window2.showBelow?[hint2("down",window2.hiddenBelow)]:[],...spare],focusRow:(window2.showAbove?1:0)+rowsBefore(focus)-from}}function compute(width,terminalRows){let lines=[],renderWidth=Math.max(1,width),maxRows=dialogRowBudget(terminalRows);if(lines.push(ruleBorder(theme2,renderWidth)),renderTabs(renderWidth,lines),view==="review"){renderReview(renderWidth,lines),lines.push(ruleBorder(theme2,renderWidth));let viewport=applyVerticalViewport(lines,renderWidth,maxRows,theme2,{preferredStart:reviewScrollOffset});return reviewMaxScrollOffset=viewport.maxStart,reviewScrollOffset=viewport.start,viewport.lines}let question2=currentQuestion(),state2=currentState(),options=currentOptions(),isMulti=question2.multiSelect===!0;wrapWithPrefix(" ",theme2.fg("text",question2.question),renderWidth,lines);let footerLines=renderQuestionFooter(renderWidth,`1-${Math.min(9,options.length)}`),areaRows=Math.max(1,maxRows-lines.length-footerLines.length),sideBySide=!inputMode&&renderWidth>=72,listWidth=sideBySide?Math.min(Math.floor((renderWidth-3)/2),Math.max(24,...options.map((option,index3)=>6+visibleWidth(`${index3+1}. ${option.label.replace(/\s+/gu," ")}`)+2))):renderWidth,detailWidth=sideBySide?renderWidth-listWidth-3:renderWidth,optionLines=[],items=[],focusItem=footerFocused?options.length-1:state2.optionIndex;for(let index3=0;index3<options.length;index3++){let option=options[index3],focused=!footerFocused&&index3===state2.optionIndex,checked=isMulti&&(option.kind==="option"&&state2.multiSelected.has(option.optionIndex)||option.kind==="other"&&state2.customAnswer?.selected===!0),selectedSingle=!isMulti&&(option.kind==="other"?state2.singleAnswer?.kind==="custom":state2.singleAnswer?.answer===option.label),marker=isMulti?multiMarker(option,checked,state2.customAnswer!==void 0):" ",focusArrow=focused?theme2.fg("accent","\u2192"):" ",note=option.kind==="option"&&state2.notesByOption.has(option.label)?theme2.fg("success"," +note"):"",customText=option.kind==="other"?state2.customAnswer?.text??(state2.singleAnswer?.kind==="custom"?state2.singleAnswer.answer:void 0):void 0,labelText=(customText?`${option.label} \u270E ${customText}`:option.label).replace(/\s+/gu," "),label=`${index3+1}. ${labelText}${selectedSingle?" \u2713":""}${note}`,color2=focused?"accent":selectedSingle||checked?"success":"text",row=truncateToWidth(`${focusArrow} ${marker} ${theme2.fg(color2,label)}`,listWidth);optionLines.push(focused?theme2.bg("selectedBg",row+" ".repeat(Math.max(0,listWidth-visibleWidth(row)))):row),items.push({height:1,countsAsOption:!0})}if(inputMode){let start=optionLines.length,label=inputMode==="notes"?`Notes for ${noteTarget??"option"}:`:"Your answer:";optionLines.push(theme2.fg("muted",truncateToWidth(` ${label}`,listWidth)));for(let line of editor.render(Math.max(1,listWidth-2)))optionLines.push(` ${line}`);items.push({height:optionLines.length-start,countsAsOption:!1}),focusItem=items.length-1}let regionStart=lines.length,focusRow;if(inputMode){let windowed=windowOptionLines(optionLines,items,focusItem,areaRows,renderWidth);focusRow=windowed.focusRow,lines.push(...windowed.rows)}else{let option=options[state2.optionIndex],content=[],hasPreview=!footerFocused&&!isMulti&&option.kind==="option"&&!!option.preview,title=footerFocused?"Chat about this":`${hasPreview?"Preview":"Details"} \xB7 ${option.label}`;if(!footerFocused&&visibleWidth(`${state2.optionIndex+1}. ${option.label.replace(/\s+/gu," ")}`)>listWidth-6&&wrapWithPrefix(" ",theme2.fg("text",option.label),detailWidth,content),footerFocused)wrapWithPrefix(" ",theme2.fg("muted","Discuss this question before choosing an answer."),detailWidth,content);else if(option.kind==="option"){wrapWithPrefix(" ",theme2.fg("muted",option.description),detailWidth,content);let note=state2.notesByOption.get(option.label);note&&wrapWithPrefix(" ",theme2.fg("success",`Note: ${note}`),detailWidth,content),hasPreview&&option.preview&&content.push("",...previewLines(option.preview,detailWidth))}else{let custom=state2.customAnswer?.text??(state2.singleAnswer?.kind==="custom"?state2.singleAnswer.answer:void 0);wrapWithPrefix(" ",theme2.fg("muted",custom||"Write your own answer instead of choosing an option."),detailWidth,content)}let optionRows=sideBySide?areaRows:Math.max(1,Math.min(options.length,areaRows-4)),detailRows=sideBySide?areaRows:Math.max(1,areaRows-optionRows),left=windowOptionLines(optionLines,items,focusItem,optionRows,listWidth),right=details.render(`${currentIdx}:${state2.optionIndex}:${footerFocused}`,title,content,detailWidth,detailRows,keyGroupAction(["app.question.pageUp","app.question.pageDown"],"scroll"),theme2);if(focusRow=left.focusRow,sideBySide)for(let row=0;row<Math.max(left.rows.length,right.length);row++){let leftText=left.rows[row]??"",leftPadded=leftText+" ".repeat(Math.max(0,listWidth-visibleWidth(leftText)));lines.push(`${leftPadded}${theme2.fg("dim"," \u2502 ")}${right[row]??""}`)}else lines.push(...left.rows,...right)}let anchorLine=regionStart+focusRow;return lines.push(...footerLines),applyVerticalViewport(lines,renderWidth,maxRows,theme2,{anchorLine}).lines}return{get focused(){return dialogFocused},set focused(value2){dialogFocused=value2,syncEditorFocus()},render:render2,invalidate:()=>{cache.invalidate()},handleInput,dispose(){signal?.removeEventListener("abort",onAbort)}}}}var DECLINE_MESSAGE="User declined to answer the questions.",CLARIFICATION_MESSAGE="The user wants to discuss these questions before choosing an answer.",ENVELOPE_PREFIX="User decisions:",ENVELOPE_SUFFIX="Continue with these decisions in mind.";function buildToolResult(text2,details){return{content:[{type:"text",text:text2}],details}}function boundedText2(text2){if(text2.length<=QUESTION_LIMITS.modelResultChars)return text2;let suffix=`
|
|
1567
1567
|
|
|
1568
1568
|
[Question result truncated. ${TRUNCATION_FOLLOW_UP}]`;return`${text2.slice(0,Math.max(0,QUESTION_LIMITS.modelResultChars-suffix.length))}${suffix}`}function errorResult(error,message){return buildToolResult(`Question tool error (${error}): ${message}`,{answers:[],outcome:"error",cancelled:!1,error,message})}function answerScalar(answer){return answer.kind==="multi"?answer.selected?.length?answer.selected.join(", "):"(no input)":answer.answer&&answer.answer.length>0?answer.answer:"(no input)"}function answerKindLabel(answer){return answer.kind==="multi"?"Selections":answer.kind==="custom"?"Custom answer":"Selected option"}function answerSegment(answer){let lines=[`${answer.questionIndex+1}. [${answer.header}] ${answer.question}`,` ${answerKindLabel(answer)}: ${answerScalar(answer)}`];answer.preview&&lines.push(" Preview: selected (kept in tool details)");for(let note of answer.notes??[])lines.push(` Note for ${note.option}: ${note.text}`);return lines.join(`
|
|
1569
1569
|
`)}function successResult(answers){let text2=answers.length?boundedText2(`${ENVELOPE_PREFIX}
|
|
@@ -1598,7 +1598,7 @@ ${detailLines.join(`
|
|
|
1598
1598
|
`)},{name:"general",tools:[...DEFAULT_AGENT_TOOLS],systemPrompt:["Work independently on the delegated task from start to finish.","Inspect relevant repository instructions before changing files.","Prefer editing existing files; never create documentation files unless the task explicitly asks for them.","Keep changes focused, run appropriate verification, and report exact paths, checks, blockers, and remaining risks."].join(`
|
|
1599
1599
|
`)}];function subagentToolDescription(){return["Delegate bounded work to isolated one-shot subagents. Workers cannot see the parent conversation: each task needs a complete self-contained briefing, and you receive only their final reports.","",`Provide 1-${8} independent tasks; for sequential work, call this tool again with the previous result folded into the next briefing.`,"Foreground (default) blocks until every worker settles and returns all reports \u2014 use it when your next step depends on them. Top-level background: true returns a group reference right after preflight, not completed reports \u2014 use it when you have independent work to continue; group completion arrives later as an automatic notification. Manage the whole group with bg read/wait/kill, never an individual worker; backgrounding is all-or-nothing per invocation.","","Agent profiles:","- explorer (default): read-only investigation \u2014 finding files, searching code, and answering codebase questions; bash is restricted to read-only inspection (git log/diff/blame, ls, cat, and similar). Never use for changes.","- general: implementation \u2014 edits, fixes, refactors, and verification in a scoped area; use when the task changes files.","","Never delegate with vague instructions: state what must be investigated or changed and the expected output."].join(`
|
|
1600
1600
|
`)}var import_proper_lockfile5=__toESM(require_proper_lockfile(),1);import{mkdir as mkdir2,readFile as readFile6,rename as rename2,unlink as unlink3,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname24,join as join42}from"node:path";var LOCK_STALE_MS=1e4,LOCK_RETRY_OPTIONS={retries:5,factor:2,minTimeout:20,maxTimeout:200},BACKUP_ATTEMPTS=100;function isThinkingLevel(value2){return typeof value2=="string"&&THINKING_LEVELS2.includes(value2)}function normalizeOverride(value2,profile){if(!value2||typeof value2!="object"||Array.isArray(value2))throw new Error(`Profile override for "${profile}" must be an object.`);let input2=value2,output={};if(input2.model!==void 0){if(typeof input2.model!="string"||input2.model.trim().length===0||input2.model==="inherit")throw new Error(`Profile "${profile}" model override must be a concrete model id.`);output.model=input2.model.trim()}if(input2.thinking!==void 0){if(!isThinkingLevel(input2.thinking))throw new Error(`Profile "${profile}" thinking override is invalid.`);output.thinking=input2.thinking}let unknownKeys=Object.keys(input2).filter(key=>key!=="model"&&key!=="thinking");if(unknownKeys.length>0)throw new Error(`Profile "${profile}" has unsupported setting(s): ${unknownKeys.join(", ")}.`);return output}function getSubagentConfigPath(agentDir=getAgentDir()){return join42(agentDir,SUBAGENT_CONFIG_FILE)}function emptySubagentConfig(){return{version:1,profiles:{}}}function parseSubagentConfig(raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new Error(`${SUBAGENT_CONFIG_FILE} is not valid JSON.`)}if(!parsed||typeof parsed!="object"||Array.isArray(parsed))throw new Error(`${SUBAGENT_CONFIG_FILE} must be a JSON object.`);let root=parsed;if(root.version!==1)throw new Error(`${SUBAGENT_CONFIG_FILE} has unsupported version ${String(root.version)}.`);if(root.profiles!==void 0&&(!root.profiles||typeof root.profiles!="object"||Array.isArray(root.profiles)))throw new Error(`${SUBAGENT_CONFIG_FILE} profiles must be an object.`);let profiles={};for(let[name,value2]of Object.entries(root.profiles??{})){if(!SUBAGENT_AGENT_NAMES.includes(name))throw new Error(`${SUBAGENT_CONFIG_FILE} contains unknown profile "${name}".`);profiles[name]=normalizeOverride(value2,name)}let unknownKeys=Object.keys(root).filter(key=>key!=="version"&&key!=="profiles");if(unknownKeys.length>0)throw new Error(`${SUBAGENT_CONFIG_FILE} has unsupported field(s): ${unknownKeys.join(", ")}.`);return{version:1,profiles}}function errorMessage4(error){return error instanceof Error?error.message:String(error)}function configWarning(filePath,error){return`Ignoring invalid Subagent settings at ${filePath}; the file was left unchanged. ${errorMessage4(error)}`}async function loadSubagentConfig(agentDir=getAgentDir(),onWarning){let filePath=getSubagentConfigPath(agentDir);try{return parseSubagentConfig(await readFile6(filePath,"utf8"))}catch(error){return error.code==="ENOENT"||onWarning?.(configWarning(filePath,error)),emptySubagentConfig()}}async function writeSubagentConfigFile(filePath,config){let payload=`${JSON.stringify({version:1,profiles:config.profiles},null,2)}
|
|
1601
|
-
`;await mkdir2(dirname24(filePath),{recursive:!0});let tempPath=`${filePath}.${process.pid}.${Date.now()}.tmp`;try{await writeFile3(tempPath,payload,{encoding:"utf8",mode:384}),await rename2(tempPath,filePath)}catch(error){try{await unlink3(tempPath)}catch{}throw error}}async function backUpInvalidConfig(filePath,raw){for(let attempt2=0;attempt2<BACKUP_ATTEMPTS;attempt2++){let suffix=attempt2===0?"":`-${attempt2}`,backupPath=`${filePath}.invalid-${Date.now()}-${process.pid}${suffix}.bak`;try{return await writeFile3(backupPath,raw,{encoding:"utf8",mode:384,flag:"wx"}),backupPath}catch(error){if(error.code==="EEXIST")continue;throw new Error(`Could not back up invalid ${SUBAGENT_CONFIG_FILE}: ${errorMessage4(error)}`)}}throw new Error(`Could not allocate a backup path for invalid ${SUBAGENT_CONFIG_FILE}.`)}async function withSubagentConfigLock(filePath,fn){await mkdir2(dirname24(filePath),{recursive:!0});let release2;try{release2=await import_proper_lockfile5.default.lock(filePath,{realpath:!1,stale:LOCK_STALE_MS,retries:LOCK_RETRY_OPTIONS})}catch(error){throw error.code==="ELOCKED"?new Error(`Timed out waiting to update ${SUBAGENT_CONFIG_FILE}; another Pi process is saving it.`):error}try{return await fn()}finally{await release2()}}async function readConfigForMutation(filePath){let raw;try{raw=await readFile6(filePath,"utf8")}catch(error){if(error.code==="ENOENT")return{config:emptySubagentConfig()};throw error}try{return{config:parseSubagentConfig(raw)}}catch{return{config:emptySubagentConfig(),invalidRaw:raw}}}async function updateProfileOverride(profile,patch,agentDir=getAgentDir()){let filePath=getSubagentConfigPath(agentDir);return withFileMutationQueue2(filePath,()=>withSubagentConfigLock(filePath,async()=>{let{config,invalidRaw}=await readConfigForMutation(filePath),currentOverride=config.profiles[profile],current=currentOverride??{},next={...current};"model"in patch&&(patch.model===void 0?delete next.model:next.model=patch.model),"thinking"in patch&&(patch.thinking===void 0?delete next.thinking:next.thinking=patch.thinking);let hasNext=Object.keys(next).length>0;return(currentOverride!==void 0!==hasNext||current.model!==next.model||current.thinking!==next.thinking)&&(invalidRaw!==void 0&&await backUpInvalidConfig(filePath,invalidRaw),hasNext?config.profiles[profile]=next:delete config.profiles[profile],await writeSubagentConfigFile(filePath,config)),config}))}function modelId(model){return model?`${model.provider}/${model.id}`:"none"}function parseModelSpec(value2){let separator=value2.indexOf("/");return separator>0?{provider:value2.slice(0,separator),id:value2.slice(separator+1)}:{provider:"",id:value2}}function findModel(models,value2){if(value2)return models.find(model=>modelId(model)===value2)}function findAvailableModel(spec,registry){let normalized=spec.trim(),model;if(normalized.includes("/")){let{provider,id}=parseModelSpec(normalized);model=registry.find(provider,id)}else{let matches=registry.getAvailable().filter(candidate=>candidate.id===normalized);if(matches.length===1&&(model=matches[0]),matches.length>1)throw new Error(`Model id "${normalized}" is ambiguous; use provider/model.`)}if(!model)throw new Error(`Model "${normalized}" is not available.`);if(!registry.hasConfiguredAuth(model))throw new Error(`Model "${normalized}" has no configured authentication.`);return model}function effectiveModel(currentSessionModel,models,override){if(override?.model){let saved=findModel(models,override.model);if(saved)return saved}return currentSessionModel}function inheritedThinking(effective,currentThinking){return effective?clampThinkingLevel(effective,currentThinking):currentThinking}function compareModels(left,right){let provider=left.provider.localeCompare(right.provider);return provider!==0?provider:left.id.localeCompare(right.id)}function buildSettingsRows(options){let effective=effectiveModel(options.currentSessionModel,options.models,options.override);return[{action:"model",label:"Model",value:options.override?.model?`override \u2014 ${options.override.model}${findModel(options.models,options.override.model)?"":" [unavailable]"}`:`inherit \u2014 ${modelId(options.currentSessionModel)}`,override:options.override?.model!==void 0},{action:"thinking",label:"Thinking",value:options.override?.thinking?`override \u2014 ${options.override.thinking}`:`inherit \u2014 ${inheritedThinking(effective,options.currentThinking)}`,override:options.override?.thinking!==void 0}]}function buildModelChoices(options){let choices=new Map;choices.set(`inherit (${modelId(options.currentSessionModel)})${options.savedModelId?"":" \u2713"}`,void 0),options.savedModelId&&!findModel(options.models,options.savedModelId)&&choices.set(`${options.savedModelId} [unavailable] \u2713`,options.savedModelId);for(let model of options.models){let id=modelId(model);choices.set(`${id}${options.savedModelId===id?" \u2713":""}`,id)}return choices}function buildThinkingChoices(options){let effective=effectiveModel(options.currentSessionModel,options.models,options.override),levels=effective?getSupportedThinkingLevels(effective):[...THINKING_LEVELS2],inherited=inheritedThinking(effective,options.currentThinking),choices=new Map;choices.set(`inherit (${inherited})${options.override?.thinking?"":" \u2713"}`,void 0);for(let level of levels)choices.set(`${level}${options.override?.thinking===level?" \u2713":""}`,level);return choices}async function persistOverride(ctx,profile,patch){try{return await updateProfileOverride(profile.name,patch,getAgentDir())}catch(error){ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error?error.message:String(error)}`,"error");return}}async function selectProfile(ctx){let labels=AGENT_PROFILES.map(profile=>AGENT_PROFILE_LABELS[profile.name]),label=await ctx.ui.select("Agents",labels);return label===void 0?void 0:AGENT_PROFILES.find(profile=>AGENT_PROFILE_LABELS[profile.name]===label)}async function showDialogSettingsMenu(ctx,profile,override,currentThinking){let options=new Map;for(let row of buildSettingsRows({override,models:ctx.modelRegistry.getAvailable(),currentSessionModel:ctx.model,currentThinking}))options.set(`${row.label} \u2014 ${row.value}`,row.action);let label=await ctx.ui.select(AGENT_PROFILE_LABELS[profile.name],[...options.keys()]);return label===void 0?void 0:options.get(label)}async function showDialogModelPicker(ctx,profile,override){let models=[...ctx.modelRegistry.getAvailable()].sort(compareModels),choices=buildModelChoices({models,currentSessionModel:ctx.model,savedModelId:override?.model}),label=await ctx.ui.select(`Model \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,[...choices.keys()]);return label===void 0?void 0:{modelId:choices.get(label)}}async function showDialogThinkingPicker(ctx,profile,override,currentThinking){let choices=buildThinkingChoices({currentSessionModel:ctx.model,models:ctx.modelRegistry.getAvailable(),override,currentThinking}),label=await ctx.ui.select(`Thinking \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,[...choices.keys()]);return label===void 0?void 0:{level:choices.get(label)}}async function runDialogProfileSettings(ctx,profile,currentThinking){let agentDir=getAgentDir();for(;;){let override=(await loadSubagentConfig(agentDir,message=>ctx.ui.notify(message,"warning"))).profiles[profile.name],action=await showDialogSettingsMenu(ctx,profile,override,currentThinking);if(!action)return;if(action==="model"){let chosen=await showDialogModelPicker(ctx,profile,override);if(!chosen)continue;await persistOverride(ctx,profile,{model:chosen.modelId})}else{let chosen=await showDialogThinkingPicker(ctx,profile,override,currentThinking);if(!chosen)continue;await persistOverride(ctx,profile,{thinking:chosen.level})}}}async function showDialogAgentsCommand(ctx,currentThinking){for(;;){let profile=await selectProfile(ctx);if(!profile)return;await runDialogProfileSettings(ctx,profile,currentThinking)}}function hint(theme2,keybindings,binding,description){let key=keyLabel(binding,{keybindings});return key?`${theme2.fg("dim",key)}${theme2.fg("muted",` ${description}`)}`:""}function navigationHint(theme2,keybindings){let keys=[keyLabel("tui.select.up",{keybindings}),keyLabel("tui.select.down",{keybindings})].filter(Boolean).join("/");return keys?`${theme2.fg("dim",keys)}${theme2.fg("muted"," navigate")}`:""}var ChoiceMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2}constructor(options){super(),this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.choices=options.choices,this.onDone=options.onDone,this.title=options.title,this.cancelDescription=options.cancelDescription,this.selectedIndex=Math.min(Math.max(options.initialIndex??0,0),Math.max(0,options.choices.length-1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText(),this.updateList()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title)));let hints=[navigationHint(this.theme,this.keybindings),hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel",this.cancelDescription)].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}updateList(){this.listContainer.clear();for(let[index3,choice]of this.choices.entries()){let selected=index3===this.selectedIndex,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=this.theme.fg(selected?"accent":"text",choice.label);this.listContainer.addChild(new TruncatedText(`${prefix}${label}`,1,0))}}moveSelection(offset){this.choices.length!==0&&(this.selectedIndex=(this.selectedIndex+offset+this.choices.length)%this.choices.length,this.updateList())}invalidate(){this.updateStaticText(),this.updateList(),super.invalidate()}handleInput(data){if(this.keybindings.matches(data,"tui.select.up"))this.moveSelection(-1);else if(this.keybindings.matches(data,"tui.select.down"))this.moveSelection(1);else if(this.keybindings.matches(data,"tui.select.confirm")){let choice=this.choices[this.selectedIndex];choice&&this.onDone(choice)}else this.keybindings.matches(data,"tui.select.cancel")&&this.onDone(void 0)}};var MAX_VISIBLE_MODELS=10;function modelSearchText(item){return item.modelId===void 0?`inherit ${item.model?getModelSelectorSearchText(item.model):""}`:getModelSelectorSearchText(item)}var ProfileModelListComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(options){super(),this.allChoices=[],this.scopedChoices=[],this.activeChoices=[],this.filteredChoices=[],this.selectedIndex=0,this.statusTone="muted",this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.models=[...options.models],this.currentSessionModel=options.currentSessionModel,this.savedModelId=options.savedModelId,this.scopedModelKeys=new Set(options.scopedModels.map(({model})=>modelId(model))),this.scope=this.scopedModelKeys.size>0?"scoped":"all",this.onDone=options.onDone,this.scopeContainer=new Container,this.addChild(this.scopeContainer),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.rebuildChoices(this.savedModelId??"")}makeInheritChoice(){return{key:"",modelId:void 0,model:this.currentSessionModel,unavailable:!1,provider:this.currentSessionModel?.provider??"",id:"inherit",name:this.currentSessionModel?.name}}makeModelChoice(model){return{key:modelId(model),modelId:modelId(model),model,unavailable:!1,provider:model.provider,id:model.id,name:model.name}}makeUnavailableChoice(modelId2){let parsed=parseModelSpec(modelId2);return{key:modelId2,modelId:modelId2,model:void 0,unavailable:!0,provider:parsed.provider,id:parsed.id,name:void 0}}buildChoices(models){let sorted=[...models].sort(compareModels),availableById=new Map(this.models.map(model=>[modelId(model),model])),choices=[this.makeInheritChoice()];if(this.savedModelId){let saved=availableById.get(this.savedModelId);choices.push(saved?this.makeModelChoice(saved):this.makeUnavailableChoice(this.savedModelId))}for(let model of sorted)modelId(model)!==this.savedModelId&&choices.push(this.makeModelChoice(model));return choices}rebuildChoices(preferredKey){let currentKey=preferredKey??this.filteredChoices[this.selectedIndex]?.key??this.savedModelId??"";this.allChoices=this.buildChoices(this.models);let scopedModels=this.models.filter(model=>this.scopedModelKeys.has(modelId(model)));this.scopedChoices=this.buildChoices(scopedModels),this.activeChoices=this.scope==="scoped"?this.scopedChoices:this.allChoices,this.applyFilter(this.searchInput.getValue(),currentKey,!1),this.updateScopeView()}applyFilter(query,preferredKey,resetSelection=!0){if(this.filteredChoices=query?fuzzyFilter(this.activeChoices,query,modelSearchText):this.activeChoices,preferredKey!==void 0){let preferredIndex=this.filteredChoices.findIndex(choice=>choice.key===preferredKey);this.selectedIndex=preferredIndex>=0?preferredIndex:0}else query&&resetSelection?this.selectedIndex=0:this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredChoices.length-1));this.updateList()}updateScopeView(){if(this.scopeContainer.clear(),this.scopedModelKeys.size===0){this.scopeContainer.addChild(new Text(this.theme.fg("warning","Only showing models from configured providers. Use /login to add providers."),0,0)),this.scopeContainer.addChild(new Spacer(1));return}let all=this.scope==="all"?this.theme.fg("accent","all"):this.theme.fg("muted","all"),scoped=this.scope==="scoped"?this.theme.fg("accent","scoped"):this.theme.fg("muted","scoped");this.scopeContainer.addChild(new Text(`${this.theme.fg("muted","Scope: ")}${all}${this.theme.fg("muted"," | ")}${scoped}`,0,0)),this.scopeContainer.addChild(new Spacer(1))}choiceLabel(choice){if(choice.modelId===void 0){let inherited=choice.model?modelId(choice.model):"none";return`inherit ${this.theme.fg("muted",`(${inherited})`)}`}if(choice.unavailable){let badge=choice.provider?`${choice.provider} \xB7 unavailable`:"unavailable";return`${choice.id} ${this.theme.fg("warning",`[${badge}]`)}`}return`${choice.id} ${this.theme.fg("muted",`[${choice.provider}]`)}`}updateList(){this.listContainer.clear();let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(MAX_VISIBLE_MODELS/2),this.filteredChoices.length-MAX_VISIBLE_MODELS)),endIndex=Math.min(startIndex+MAX_VISIBLE_MODELS,this.filteredChoices.length);for(let index3=startIndex;index3<endIndex;index3++){let choice=this.filteredChoices[index3];if(!choice)continue;let selected=index3===this.selectedIndex,saved=choice.modelId===this.savedModelId,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=this.choiceLabel(choice),styledLabel=selected?this.theme.fg("accent",label):label,checkmark=saved?this.theme.fg("success"," \u2713"):"";this.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`,0,0))}if((startIndex>0||endIndex<this.filteredChoices.length)&&this.listContainer.addChild(new TruncatedText(this.theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredChoices.length})`),0,0)),this.filteredChoices.length===0)this.listContainer.addChild(new Text(this.theme.fg("muted"," No matching models"),0,0));else{let selected=this.filteredChoices[this.selectedIndex];selected?.model?.name&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(this.theme.fg("muted",` Model Name: ${selected.model.name}`),0,0)))}this.statusMessage&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(this.theme.fg(this.statusTone,` ${this.statusMessage}`),0,0)))}moveSelection(offset){this.filteredChoices.length!==0&&(this.selectedIndex=(this.selectedIndex+offset+this.filteredChoices.length)%this.filteredChoices.length,this.updateList())}toggleScope(){if(this.scopedModelKeys.size===0)return;let currentKey=this.filteredChoices[this.selectedIndex]?.key;this.scope=this.scope==="all"?"scoped":"all",this.activeChoices=this.scope==="scoped"?this.scopedChoices:this.allChoices,this.applyFilter(this.searchInput.getValue(),currentKey,!1),this.updateScopeView()}getSelectedChoice(){let selected=this.filteredChoices[this.selectedIndex];if(selected)return{modelId:selected.modelId,model:selected.model,unavailable:selected.unavailable}}updateModels(models){let selectedKey=this.filteredChoices[this.selectedIndex]?.key;this.models=[...models],this.rebuildChoices(selectedKey)}setStatus(message,tone="muted"){this.statusMessage=message,this.statusTone=tone,this.updateList()}invalidate(){this.updateScopeView(),this.updateList(),super.invalidate()}handleInput(data){if(this.keybindings.matches(data,"tui.input.tab"))this.toggleScope();else if(this.keybindings.matches(data,"tui.select.up"))this.moveSelection(-1);else if(this.keybindings.matches(data,"tui.select.down"))this.moveSelection(1);else if(this.keybindings.matches(data,"tui.select.confirm")){let selected=this.getSelectedChoice();selected&&this.onDone(selected)}else this.keybindings.matches(data,"tui.select.cancel")?this.onDone(void 0):(this.searchInput.handleInput(data),this.applyFilter(this.searchInput.getValue()))}};var MODEL_REFRESH_TIMEOUT_MS=15e3,MAX_REFRESH_ERROR_LENGTH=240;function refreshFailureMessage(providerIds){if(providerIds.length===1)return`Could not refresh ${providerIds[0]}; showing cached models.`;let visible=providerIds.slice(0,3),omitted=providerIds.length-visible.length,suffix=omitted>0?`, +${omitted} more`:"";return`Could not refresh ${providerIds.length} model catalogs (${visible.join(", ")}${suffix}); showing cached models.`}var ModelPickerComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.modelList.focused=value2}constructor(options){super(),this.refreshAbortController=new AbortController,this.closed=!1,this._focused=!1,this.tui=options.tui,this.theme=options.theme,this.keybindings=options.keybindings,this.title=`Model \u2014 ${AGENT_PROFILE_LABELS[options.profile.name]}`,this.hasScopedModels=options.scopedModels.length>0,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.modelList=new ProfileModelListComponent({theme:options.theme,keybindings:options.keybindings,models:options.models,scopedModels:options.scopedModels,currentSessionModel:options.currentSessionModel,savedModelId:options.savedModelId,onDone:options.onDone}),this.addChild(this.modelList),this.addChild(new Spacer(1)),this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title)));let hints=[navigationHint(this.theme,this.keybindings),this.hasScopedModels?hint(this.theme,this.keybindings,"tui.input.tab","scope"):"",hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel","back")].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}get refreshSignal(){return this.refreshAbortController.signal}cancelRefresh(){this.refreshAbortController.abort()}get isClosed(){return this.closed}dispose(){this.closed=!0,this.refreshAbortController.abort()}updateModels(models){this.closed||(this.modelList.updateModels(models),this.tui.requestRender())}setRefreshStatus(message,tone="muted"){this.closed||(this.modelList.setStatus(message,tone),this.tui.requestRender())}invalidate(){this.updateStaticText(),super.invalidate()}handleInput(data){this.modelList.handleInput(data)}};async function refreshPickerModels(ctx,picker){let timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,picker.cancelRefresh()},MODEL_REFRESH_TIMEOUT_MS);timeout.unref?.();try{let result2=await refreshModelCatalogs(ctx.modelRuntime,picker.refreshSignal);if(picker.isClosed||picker.refreshSignal.aborted&&!timedOut)return;if(picker.updateModels(ctx.modelRegistry.getAvailable()),result2.aborted&&timedOut){picker.setRefreshStatus("Model refresh timed out; showing cached models.","error");return}let providerIds=[...result2.errors.keys()];if(providerIds.length>0){picker.setRefreshStatus(refreshFailureMessage(providerIds),"error");return}let registryError=ctx.modelRegistry.getError?.();if(registryError){picker.setRefreshStatus(truncate4(registryError,MAX_REFRESH_ERROR_LENGTH),"error");return}picker.setRefreshStatus(void 0)}catch(error){if(picker.isClosed||picker.refreshSignal.aborted&&!timedOut)return;let message=timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`;picker.setRefreshStatus(truncate4(message,MAX_REFRESH_ERROR_LENGTH),"error")}finally{clearTimeout(timeout)}}var ProfileSettingsMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2}constructor(options){super(),this.selectedIndex=0,this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.onDone=options.onDone,this.title=AGENT_PROFILE_LABELS[options.profile.name],this.status=options.status,this.rows=buildSettingsRows({override:options.override,models:options.models,currentSessionModel:options.currentSessionModel,currentThinking:options.currentThinking}),this.selectedIndex=Math.max(0,this.rows.findIndex(row=>row.action===options.selectedAction)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.status?(this.statusText=new Text("",1,0),this.addChild(this.statusText),this.addChild(new Spacer(1))):this.statusText=void 0,this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText(),this.updateList()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title))),this.statusText?.setText(this.theme.fg("muted",this.status??""));let hints=[navigationHint(this.theme,this.keybindings),hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel","back")].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}updateList(){this.listContainer.clear();for(let[index3,row]of this.rows.entries()){let selected=index3===this.selectedIndex,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=selected?this.theme.fg("accent",row.label):this.theme.fg("text",row.label),value2=this.theme.fg("muted",`\u2014 ${row.value}`),checkmark=row.override?this.theme.fg("success"," \u2713"):"";this.listContainer.addChild(new TruncatedText(`${prefix}${label} ${value2}${checkmark}`,1,0))}}moveSelection(offset){this.selectedIndex=(this.selectedIndex+offset+this.rows.length)%this.rows.length,this.updateList()}invalidate(){this.updateStaticText(),this.updateList(),super.invalidate()}handleInput(data){this.keybindings.matches(data,"tui.select.up")?this.moveSelection(-1):this.keybindings.matches(data,"tui.select.down")?this.moveSelection(1):this.keybindings.matches(data,"tui.select.confirm")?this.onDone(this.rows[this.selectedIndex]?.action):this.keybindings.matches(data,"tui.select.cancel")&&this.onDone(void 0)}};async function persistOverride2(ctx,profile,patch){try{return await updateProfileOverride(profile.name,patch,getAgentDir())}catch(error){ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error?error.message:String(error)}`,"error");return}}var AgentsMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.activeScreen&&isFocusable(this.activeScreen)&&(this.activeScreen.focused=value2)}constructor(options){super(),this.route={kind:"profiles"},this.selectedSettingsAction="model",this.saving=!1,this.closed=!1,this._focused=!1,this.tui=options.tui,this.theme=options.theme,this.keybindings=options.keybindings,this.ctx=options.ctx,this.currentThinking=options.currentThinking,this.config=options.config,this.onDone=options.onDone,this.showProfiles()}disposeActiveScreen(){let screen=this.activeScreen;if(this.activeScreen=void 0,!screen)return;let disposable=screen;isFocusable(screen)&&(screen.focused=!1),disposable.dispose?.()}setActiveScreen(screen){this.disposeActiveScreen(),this.clear(),this.activeScreen=screen,this.addChild(screen),isFocusable(screen)&&(screen.focused=this._focused),this.tui.requestRender()}showProfiles(){this.route={kind:"profiles"};let choices=AGENT_PROFILES.map(profile=>({label:AGENT_PROFILE_LABELS[profile.name],value:profile})),initialIndex=choices.findIndex(choice=>choice.value.name===this.selectedProfile?.name);this.setActiveScreen(new ChoiceMenuComponent({theme:this.theme,keybindings:this.keybindings,title:"Agents",choices,initialIndex,cancelDescription:"close",onDone:choice=>{if(!choice){this.onDone();return}this.selectedProfile=choice.value,this.selectedSettingsAction="model",this.showSettings(choice.value)}}))}showSettings(profile,selectedAction=this.selectedSettingsAction){this.selectedProfile=profile,this.selectedSettingsAction=selectedAction,this.route={kind:"settings",profile,selectedAction},this.setActiveScreen(new ProfileSettingsMenuComponent({theme:this.theme,keybindings:this.keybindings,profile,override:this.config.profiles[profile.name],models:this.ctx.modelRegistry.getAvailable(),currentSessionModel:this.ctx.model,currentThinking:this.currentThinking,selectedAction,status:this.saving?"Saving\u2026":void 0,onDone:action=>{if(!action){this.showProfiles();return}this.selectedSettingsAction=action,action==="model"?this.showModelPicker(profile):this.showThinkingPicker(profile)}}))}showModelPicker(profile){this.route={kind:"model",profile};let override=this.config.profiles[profile.name],picker=new ModelPickerComponent({tui:this.tui,theme:this.theme,keybindings:this.keybindings,profile,savedModelId:override?.model,models:this.ctx.modelRegistry.getAvailable(),scopedModels:this.ctx.scopedModels,currentSessionModel:this.ctx.model,onDone:choice=>{if(!choice){this.showSettings(profile,"model");return}this.saveOverride(profile,{model:choice.modelId},"model")}});picker.setRefreshStatus("Refreshing model catalogs\u2026"),this.setActiveScreen(picker),refreshPickerModels(this.ctx,picker)}showThinkingPicker(profile){this.route={kind:"thinking",profile};let override=this.config.profiles[profile.name],choices=[...buildThinkingChoices({currentSessionModel:this.ctx.model,models:this.ctx.modelRegistry.getAvailable(),override,currentThinking:this.currentThinking}).entries()].map(([label,level])=>({label,value:level})),initialIndex=choices.findIndex(choice=>choice.label.endsWith(" \u2713"));this.setActiveScreen(new ChoiceMenuComponent({theme:this.theme,keybindings:this.keybindings,title:`Thinking \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,choices,initialIndex,cancelDescription:"back",onDone:choice=>{if(!choice){this.showSettings(profile,"thinking");return}this.saveOverride(profile,{thinking:choice.value},"thinking")}}))}saveOverride(profile,patch,returnAction){this.saving||(this.saving=!0,this.showSettings(profile,returnAction),persistOverride2(this.ctx,profile,patch).then(config=>this.completeSave(profile,config),()=>this.completeSave(profile,void 0)).catch(()=>{}))}completeSave(profile,config){this.closed||(this.saving=!1,config&&(this.config=config),this.route.kind==="settings"&&this.route.profile.name===profile.name&&this.showSettings(profile,this.route.selectedAction))}handleInput(data){if(!this.saving){this.activeScreen?.handleInput?.(data);return}this.keybindings.matches(data,"tui.select.cancel")&&(this.route.kind==="settings"?this.showProfiles():this.route.kind==="profiles"&&this.onDone())}dispose(){this.closed=!0,this.disposeActiveScreen(),this.clear()}};async function showTuiAgentsCommand(ctx,currentThinking){let config=await loadSubagentConfig(getAgentDir(),message=>ctx.ui.notify(message,"warning"));await ctx.ui.custom((tui,theme2,keybindings,done)=>new AgentsMenuComponent({tui,theme:theme2,keybindings,ctx,currentThinking,config,onDone:()=>done()}))}async function showAgentsCommand(ctx,currentThinking){if(!ctx.hasUI){ctx.ui.notify("/agents requires an interactive UI.","warning");return}ctx.mode==="tui"?await showTuiAgentsCommand(ctx,currentThinking):await showDialogAgentsCommand(ctx,currentThinking)}import{relative as relative8}from"node:path";function runId(batchId,index3){if(!batchId)return`subagent-${index3+1}`;let sanitized=batchId.replace(/[^A-Za-z0-9-]+/gu,"-").replace(/^-+|-+$/gu,""),hash=hashRunId(batchId);return`${sanitized.length>24?`${sanitized.slice(0,24)}-${hash}`:sanitized||`run-${hash}`}-${index3+1}`}function hashRunId(value2){let hash=2166136261;for(let index3=0;index3<value2.length;index3++)hash^=value2.charCodeAt(index3),hash=Math.imul(hash,16777619);return(hash>>>0).toString(36).padStart(6,"0").slice(0,6)}function createRunState(task,index3,batchId,parentCwd){return{id:runId(batchId,index3),agent:task.agent.name,description:task.description,cwd:relative8(parentCwd,task.cwd),model:modelId(task.model),thinking:task.thinking,status:"queued",activities:[],report:"",reportTruncated:!1,usage:emptyUsage3(),version:0}}function toRunDetails(state2){let{version:_version,reportTruncated:_reportTruncated,...details}=state2;return details}function deriveCurrentActivity(state2){if(!(state2.status==="completed"||state2.status==="failed"||state2.status==="aborted")){if(state2.retry)return`Retrying (${state2.retry.attempt}/${state2.retry.maxAttempts})\u2026`;for(let index3=state2.activities.length-1;index3>=0;index3--){let activity=state2.activities[index3];if(activity?.status==="running")return activity.summary}}}function positiveInteger(value2,fallback){return Number.isFinite(value2)?Math.max(1,Math.floor(value2)):fallback}function retryError(error){let normalized=error.replace(/\s+/gu," ").trim();return boundText2(normalized,160).replace(/\s+/gu," ").trim()}function makeRetry(attempt2,maxAttempts,deadline,error){let normalizedAttempt=positiveInteger(attempt2,1);return{attempt:normalizedAttempt,maxAttempts:Math.max(normalizedAttempt,positiveInteger(maxAttempts,normalizedAttempt)),deadline,error:retryError(error)}}function oldestEvictableActivityIndex(activities){let protectedIndexes=new Set;for(let index3=activities.length-1;index3>=0&&protectedIndexes.size<3;index3--){let activity=activities[index3];activity&&isDisplayableActivity(activity)&&protectedIndexes.add(index3)}let unprotected=activities.findIndex((_activity,index3)=>!protectedIndexes.has(index3));return unprotected>=0?unprotected:activities.length>1?0:-1}function activityTextSize(activities){return activities.reduce((total,item)=>total+item.summary.length+(item.resultSummary?.length??0),0)}function enforceActivityLimits(activities){for(;activities.length>80;){let index3=oldestEvictableActivityIndex(activities);if(index3<0)break;activities.splice(index3,1)}for(;activityTextSize(activities)>24576;){let index3=oldestEvictableActivityIndex(activities);if(index3<0)break;activities.splice(index3,1)}}function appendActivity(activities,activity){activities.push(activity),enforceActivityLimits(activities)}function isTerminal(state2){return state2.status==="completed"||state2.status==="failed"||state2.status==="aborted"}function withRevision(state2,mutate){let draft={...state2,activities:state2.activities.map(activity=>({...activity})),usage:{...state2.usage}};return mutate(draft),draft.version=state2.version+1,draft}function clearRetry(draft){draft.retry=void 0}function reduceRun(state2,event){return isTerminal(state2)&&event.type!=="retry_scheduled"?state2:withRevision(state2,draft=>{event.type!=="retry_scheduled"&&clearRetry(draft),applyEvent(draft,event),draft.currentActivity=deriveCurrentActivity(draft)})}function handleSlotAcquired(draft,event){draft.status="running",draft.startedAt=event.startedAt}function handleRetryScheduled(draft,event){let error=draft.error??"Subagent failed before retry.";draft.status="queued",draft.error=void 0,draft.startedAt=void 0,draft.endedAt=void 0,draft.report="",draft.reportTruncated=!1,draft.activities=[],draft.usage.turns=0,draft.usage.toolUses=0,draft.usage.contextTokens=void 0,draft.retry=makeRetry(event.attempt,event.maxAttempts,event.deadline,error)}function handleAutoRetryStart(draft,event){draft.retry=makeRetry(event.attempt,event.maxAttempts,event.deadline,event.error)}function handleTurnEnd(draft){draft.usage.turns++}function handleAssistantMessageSettled(draft,event){addUsage2(draft.usage,event.usage)}function handleToolStarted(draft,event){draft.usage.toolUses++,appendActivity(draft.activities,{id:event.toolCallId,toolName:event.toolName,summary:activitySummary(event.toolName,event.args),status:"running",startedAt:event.startedAt})}function handleToolUpdated(draft,event){let summary=activitySummary(event.toolName,event.args),activity=draft.activities.find(candidate=>candidate.id===event.toolCallId&&candidate.status==="running")??[...draft.activities].reverse().find(candidate=>candidate.status==="running");activity&&(activity.summary=summary,enforceActivityLimits(draft.activities))}function handleToolEnded(draft,event){let activity=draft.activities.find(candidate=>candidate.id===event.toolCallId);activity&&activity.status==="running"&&(activity.status=event.isError?"failed":"succeeded",activity.endedAt=event.endedAt,activity.resultSummary=resultSummary(event.result)||void 0,enforceActivityLimits(draft.activities))}function handleCompactionStarted(draft,event){appendActivity(draft.activities,{id:COMPACTION_ACTIVITY_ID,toolName:COMPACTION_ACTIVITY_ID,summary:"Compacting context\u2026",status:"running",startedAt:event.startedAt})}function handleCompactionEnded(draft,event){let contextTokens=draft.usage.contextTokens;addUsage2(draft.usage,event.usage),draft.usage.contextTokens=contextTokens;let activity=[...draft.activities].reverse().find(candidate=>candidate.id===COMPACTION_ACTIVITY_ID&&candidate.status==="running");activity&&(activity.status=event.error?"failed":"succeeded",activity.endedAt=event.endedAt,activity.summary=compactionSummary(event.tokensBefore,event.tokensAfter),activity.resultSummary=event.error?compactionError(event.error):void 0,enforceActivityLimits(draft.activities))}function handleSettle(draft,event){draft.status=event.verdict,draft.report=boundText2(event.report,32768),draft.reportTruncated=draft.report!==event.report,draft.error=event.error?boundText2(event.error,8192):void 0,draft.endedAt=event.endedAt,draft.retry=void 0}function handleAbortWhileQueued(draft,event){draft.status="aborted",draft.error="Subagent was aborted while queued.",draft.endedAt=event.endedAt,draft.retry=void 0}function handleAbortWhileRetrying(draft,event){draft.status="aborted",draft.error="Subagent was aborted while waiting to retry.",draft.endedAt=event.endedAt,draft.retry=void 0}function applyEvent(draft,event){switch(event.type){case"slot_acquired":handleSlotAcquired(draft,event);break;case"retry_scheduled":handleRetryScheduled(draft,event);break;case"retry_started":break;case"auto_retry_start":handleAutoRetryStart(draft,event);break;case"auto_retry_end":break;case"turn_end":handleTurnEnd(draft);break;case"assistant_message_settled":handleAssistantMessageSettled(draft,event);break;case"tool_started":handleToolStarted(draft,event);break;case"tool_updated":handleToolUpdated(draft,event);break;case"tool_ended":handleToolEnded(draft,event);break;case"compaction_started":handleCompactionStarted(draft,event);break;case"compaction_ended":handleCompactionEnded(draft,event);break;case"settle":handleSettle(draft,event);break;case"abort_while_queued":handleAbortWhileQueued(draft,event);break;case"abort_while_retrying":handleAbortWhileRetrying(draft,event);break}}function versionSum(runs){let total=0;for(let run of runs)total+=run.version;return total}function statusOf(runs){return runs.length===0||runs.some(run=>run.status==="queued"||run.status==="running")?"running":runs.every(run=>run.status==="completed")?"completed":runs.some(run=>run.status==="completed")?"partial":runs.every(run=>run.status==="aborted")?"aborted":"failed"}function isSubagentError(details){return details.status!=="failed"&&details.status!=="aborted"?!1:!details.runs.some(run=>run.status==="completed")}function statusText(details){if(details.runs.length===0)return"Initializing\u2026";let running=details.runs.filter(run=>run.status==="running").length,queued=details.runs.filter(run=>run.status==="queued").length,completed=details.runs.filter(run=>run.status==="completed").length,failed=details.runs.filter(run=>run.status==="failed").length,aborted=details.runs.filter(run=>run.status==="aborted").length,parts=[`${completed}/${details.runs.length} complete`];return running&&parts.push(`${running} running`),queued&&parts.push(`${queued} queued`),failed&&parts.push(`${failed} failed`),aborted&&parts.push(`${aborted} aborted`),parts.join(" \xB7 ")}function statusSummary(details){return statusText(details)}function getSubagentRetryView(run,now=Date.now()){let retry=run.retry;if(!retry||!Number.isFinite(retry.deadline))return;let attempt2=positiveInteger(retry.attempt,1),maxAttempts=Math.max(attempt2,positiveInteger(retry.maxAttempts,attempt2)),currentTime=Number.isFinite(now)?now:retry.deadline;return{attempt:attempt2,maxAttempts,remainingSeconds:Math.max(0,Math.ceil((retry.deadline-currentTime)/1e3)),error:retryError(typeof retry.error=="string"?retry.error:"")}}var RETRY_ERROR_LIMIT=160,FALLBACK_OUTPUT_LIMIT=4e3,OUTPUT_TRUNCATION_NOTICE_PATTERN2=/\s*\[Output truncated(?:: \d+ bytes omitted)?\.\]\s*$/u,ELAPSED_REFRESH_INTERVAL_MS=1e3,FLOW_SEPARATOR=" \xB7 ",FLOW_SEPARATOR_WIDTH=3,SingleLineText=class{constructor(text2){this.text=text2}render(width){return[truncateToWidth(this.text,Math.max(1,width),"...")]}invalidate(){}};function taskPrompt(args,index3,run){return args.tasks?.[index3]?.prompt??run.description}function profileLabel(agent){return AGENT_PROFILE_LABELS[agent]??agent}function formatDuration2(seconds){let roundedSeconds=Math.round(seconds);return roundedSeconds>=60?`${Math.floor(roundedSeconds/60)}m ${roundedSeconds%60}s`:`${seconds.toFixed(seconds<10?1:0)}s`}function elapsed(startedAt,endedAt){if(startedAt!==void 0)return formatDuration2(Math.max(0,((endedAt??Date.now())-startedAt)/1e3))}function runMarker(status,theme2){let marker=statusMarker(status);return theme2.fg(marker.color,marker.glyph)}function displayLine(text2){return plainLine(text2).replace(OUTPUT_TRUNCATION_NOTICE_PATTERN2,"...").trim()}function retryText(run){let retry=getSubagentRetryView(run);if(!retry)return;let state2=retry.remainingSeconds>0?`Retrying (${retry.attempt}/${retry.maxAttempts}) in ${retry.remainingSeconds}s`:`Retrying (${retry.attempt}/${retry.maxAttempts}) now...`,error=truncate4(displayLine(retry.error),RETRY_ERROR_LIMIT);return error?`${state2} \xB7 ${error}`:state2}function latestRunningActivity(run,toolName){for(let index3=run.activities.length-1;index3>=0;index3--){let activity=run.activities[index3];if(activity?.status==="running"&&activity.toolName===toolName)return activity}}function formatTotalTokens(value2){let count=Number.isFinite(value2)?Math.max(0,Math.round(value2)):0;if(count<1e3)return String(count);let divisor=count<999950?1e3:1e6,suffix=divisor===1e3?"k":"M",rounded=Math.round(count/divisor*10)/10;return`${Number.isInteger(rounded)?rounded.toFixed(0):rounded.toFixed(1)}${suffix}`}var MARKER_WIDTH=1;function flowSegment(run,index3,theme2,now){let marker;if(run.status==="running"){let glyph=statusSpinnerFrame(now),pad2=Math.max(0,MARKER_WIDTH-visibleWidth(glyph));marker=theme2.fg("accent",glyph)+(pad2>0?" ".repeat(pad2):"")}else marker=runMarker(run.status,theme2);return`${marker} ${theme2.fg("dim",`#${index3+1}`)} ${theme2.fg("accent",profileLabel(run.agent))}`}var CollapsedFlow=class{constructor(segments){this.segments=segments,this.cellWidth=segments.reduce((max,segment2)=>Math.max(max,visibleWidth(segment2)),1)}render(width){let usable=Math.max(1,width),joined=this.segments.join(FLOW_SEPARATOR);if(visibleWidth(joined)<=usable)return[joined];if(this.cellWidth>usable)return this.segments.map(segment2=>truncateToWidth(segment2,usable,"..."));let columnCount=Math.max(1,Math.floor((usable+FLOW_SEPARATOR_WIDTH)/(this.cellWidth+FLOW_SEPARATOR_WIDTH))),lines=[];for(let start=0;start<this.segments.length;start+=columnCount){let row=this.segments.slice(start,start+columnCount);lines.push(row.map((segment2,index3)=>{if(index3===row.length-1)return segment2;let padding=Math.max(0,this.cellWidth-visibleWidth(segment2));return`${segment2}${padding>0?" ".repeat(padding):""}${FLOW_SEPARATOR}`}).join(""))}return lines}invalidate(){}};function toolCallLabel(count){return`${count} tool call${count===1?"":"s"}`}function runHeader(run,index3,theme2){let separator=theme2.fg("dim"," \xB7 "),duration=elapsed(run.startedAt,run.endedAt)??"0.0s",metrics=[run.model,run.thinking,`${formatTotalTokens(run.usage.totalTokens)} tok`,toolCallLabel(run.usage.toolUses),duration].map(metric=>theme2.fg("muted",metric));return[theme2.fg("accent",theme2.bold(`#${index3+1} ${profileLabel(run.agent)}`)),...metrics].join(separator)}function sectionTitle(title,theme2,color2,suffix){let heading=theme2.fg(color2,theme2.bold(title));return suffix?`${heading}${theme2.fg("dim",` \xB7 ${suffix}`)}`:heading}function activityTitleSuffix(total,shown){return total<=3&&shown>=total?toolCallLabel(total):shown>0?`last ${shown} of ${total} tool calls`:toolCallLabel(total)}function activityLine(activity,theme2){let text2=theme2.fg("toolOutput",activityCallText(activity));return activity.status==="failed"?`${theme2.fg("error","\xD7")} ${text2}`:activity.status==="running"?`${theme2.fg("accent","\u203A")} ${text2}`:` ${text2}`}function addPrompt(container,run,index3,args,theme2){container.addChild(new Text(sectionTitle("Prompt",theme2,"toolTitle"),0,0)),container.addChild(new Text(theme2.fg("toolOutput",taskPrompt(args,index3,run)),2,0))}function addActivity(container,run,theme2){let toolCalls=run.activities.filter(isDisplayableActivity),shown=toolCalls.slice(-3),total=Math.max(run.usage.toolUses,toolCalls.length);if(container.addChild(new Text(sectionTitle("Activity",theme2,"toolTitle",activityTitleSuffix(total,shown.length)),0,0)),shown.length===0){let empty=total===0?"No tool calls yet.":"Activity unavailable.";container.addChild(new Text(theme2.fg("muted",empty),2,0));return}for(let activity of shown)container.addChild(new SingleLineText(activityLine(activity,theme2)))}function outcomeColor(status){return status==="completed"?"success":status==="failed"?"error":status==="aborted"?"warning":"accent"}function outcomeReport(run){if(typeof run.report=="string")return run.report;let legacyOutput=run.finalOutput;return typeof legacyOutput=="string"?legacyOutput:""}function hasOutcome(report){return report.trim().length>0}function addOutcomeMarkdown(container,report,theme2){container.addChild(new Markdown(report,2,0,getMarkdownTheme(),{color:text2=>theme2.fg("toolOutput",text2)}))}function addOutcome(container,run,theme2){let color2=outcomeColor(run.status),report=outcomeReport(run);if(container.addChild(new Text(sectionTitle("Outcome",theme2,color2),0,0)),run.status==="queued"||run.status==="running"){container.addChild(new Text(theme2.fg("muted","Still running..."),2,0));let retry=retryText(run);retry?container.addChild(new Text(theme2.fg("warning",retry),2,0)):latestRunningActivity(run,COMPACTION_ACTIVITY_ID)&&container.addChild(new Text(theme2.fg("accent","Compacting context..."),2,0));return}if(run.status==="completed"){hasOutcome(report)?addOutcomeMarkdown(container,report,theme2):container.addChild(new Text(theme2.fg("muted","No outcome returned."),2,0));return}let verdict=run.status==="failed"?"Failed":"Aborted",reason=run.error?`${verdict}: ${run.error}`:`${verdict}.`;container.addChild(new Text(theme2.fg(color2,reason),2,0)),hasOutcome(report)&&(container.addChild(new Spacer(1)),container.addChild(new Text(theme2.fg("muted","Partial outcome:"),2,0)),addOutcomeMarkdown(container,report,theme2))}function renderRun(run,index3,args,theme2){let container=new Container;return container.addChild(new SingleLineText(runHeader(run,index3,theme2))),container.addChild(new Spacer(1)),addPrompt(container,run,index3,args,theme2),container.addChild(new Spacer(1)),addActivity(container,run,theme2),container.addChild(new Spacer(1)),addOutcome(container,run,theme2),container}function fallbackResult(result2,theme2,isError){let text2=result2.content.find(part=>part.type==="text"),value2=text2?.type==="text"?truncate4(text2.text,FALLBACK_OUTPUT_LIMIT):"(no output)";return new Text(theme2.fg(isError?"error":"muted",value2),0,0)}function desiredRefreshInterval(runs,options){if(options.isPartial)return options.expanded?runs.some(run=>run.status==="running"||run.retry!==void 0)?ELAPSED_REFRESH_INTERVAL_MS:void 0:runs.some(run=>run.status==="running")?STATUS_SPINNER_INTERVAL_MS:void 0}function clearLiveRefresh(state2){state2.refreshTimer!==void 0&&clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0,state2.refreshInterval=void 0}function scheduleLiveRefresh(context,isPartial){let state2=context.state;state2.dispose??=()=>clearLiveRefresh(state2);let interval=desiredRefreshInterval(context.result?.details?.runs??[],{isPartial,expanded:context.expanded});if(interval===void 0){clearLiveRefresh(state2);return}if(state2.refreshTimer!==void 0){if(state2.refreshInterval===interval)return;clearTimeout(state2.refreshTimer)}state2.refreshInterval=interval,state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,state2.refreshInterval=void 0,context.invalidate()},interval),state2.refreshTimer.unref?.()}function renderSubagentCall(args,theme2){let count=Array.isArray(args.tasks)?args.tasks.length:0,title=theme2.fg(count>0?"toolTitle":"error",theme2.bold("Subagent"));return new Text(title,0,0)}function renderSubagentResult(result2,options,theme2,args,isError){let details=result2.details;if(details?.background){let summary=`Handed to background \xB7 ${details.background.id}`,rows=options.expanded?details.runs.map((run,index3)=>`#${index3+1} ${profileLabel(run.agent)} \xB7 ${run.status} at handoff`).join(`
|
|
1601
|
+
`;await mkdir2(dirname24(filePath),{recursive:!0});let tempPath=`${filePath}.${process.pid}.${Date.now()}.tmp`;try{await writeFile3(tempPath,payload,{encoding:"utf8",mode:384}),await rename2(tempPath,filePath)}catch(error){try{await unlink3(tempPath)}catch{}throw error}}async function backUpInvalidConfig(filePath,raw){for(let attempt2=0;attempt2<BACKUP_ATTEMPTS;attempt2++){let suffix=attempt2===0?"":`-${attempt2}`,backupPath=`${filePath}.invalid-${Date.now()}-${process.pid}${suffix}.bak`;try{return await writeFile3(backupPath,raw,{encoding:"utf8",mode:384,flag:"wx"}),backupPath}catch(error){if(error.code==="EEXIST")continue;throw new Error(`Could not back up invalid ${SUBAGENT_CONFIG_FILE}: ${errorMessage4(error)}`)}}throw new Error(`Could not allocate a backup path for invalid ${SUBAGENT_CONFIG_FILE}.`)}async function withSubagentConfigLock(filePath,fn){await mkdir2(dirname24(filePath),{recursive:!0});let release2;try{release2=await import_proper_lockfile5.default.lock(filePath,{realpath:!1,stale:LOCK_STALE_MS,retries:LOCK_RETRY_OPTIONS})}catch(error){throw error.code==="ELOCKED"?new Error(`Timed out waiting to update ${SUBAGENT_CONFIG_FILE}; another Pi process is saving it.`):error}try{return await fn()}finally{await release2()}}async function readConfigForMutation(filePath){let raw;try{raw=await readFile6(filePath,"utf8")}catch(error){if(error.code==="ENOENT")return{config:emptySubagentConfig()};throw error}try{return{config:parseSubagentConfig(raw)}}catch{return{config:emptySubagentConfig(),invalidRaw:raw}}}async function updateProfileOverride(profile,patch,agentDir=getAgentDir()){let filePath=getSubagentConfigPath(agentDir);return withFileMutationQueue2(filePath,()=>withSubagentConfigLock(filePath,async()=>{let{config,invalidRaw}=await readConfigForMutation(filePath),currentOverride=config.profiles[profile],current=currentOverride??{},next={...current};"model"in patch&&(patch.model===void 0?delete next.model:next.model=patch.model),"thinking"in patch&&(patch.thinking===void 0?delete next.thinking:next.thinking=patch.thinking);let hasNext=Object.keys(next).length>0;return(currentOverride!==void 0!==hasNext||current.model!==next.model||current.thinking!==next.thinking)&&(invalidRaw!==void 0&&await backUpInvalidConfig(filePath,invalidRaw),hasNext?config.profiles[profile]=next:delete config.profiles[profile],await writeSubagentConfigFile(filePath,config)),config}))}function modelId(model){return model?`${model.provider}/${model.id}`:"none"}function parseModelSpec(value2){let separator=value2.indexOf("/");return separator>0?{provider:value2.slice(0,separator),id:value2.slice(separator+1)}:{provider:"",id:value2}}function findModel(models,value2){if(value2)return models.find(model=>modelId(model)===value2)}function findAvailableModel(spec,registry){let normalized=spec.trim(),model;if(normalized.includes("/")){let{provider,id}=parseModelSpec(normalized);model=registry.find(provider,id)}else{let matches=registry.getAvailable().filter(candidate=>candidate.id===normalized);if(matches.length===1&&(model=matches[0]),matches.length>1)throw new Error(`Model id "${normalized}" is ambiguous; use provider/model.`)}if(!model)throw new Error(`Model "${normalized}" is not available.`);if(!registry.hasConfiguredAuth(model))throw new Error(`Model "${normalized}" has no configured authentication.`);return model}function effectiveModel(currentSessionModel,models,override){if(override?.model){let saved=findModel(models,override.model);if(saved)return saved}return currentSessionModel}function inheritedThinking(effective,currentThinking){return effective?clampThinkingLevel(effective,currentThinking):currentThinking}function compareModels(left,right){let provider=left.provider.localeCompare(right.provider);return provider!==0?provider:left.id.localeCompare(right.id)}function buildSettingsRows(options){let effective=effectiveModel(options.currentSessionModel,options.models,options.override);return[{action:"model",label:"Model",value:options.override?.model?`override \u2014 ${options.override.model}${findModel(options.models,options.override.model)?"":" [unavailable]"}`:`inherit \u2014 ${modelId(options.currentSessionModel)}`,override:options.override?.model!==void 0},{action:"thinking",label:"Thinking",value:options.override?.thinking?`override \u2014 ${options.override.thinking}`:`inherit \u2014 ${inheritedThinking(effective,options.currentThinking)}`,override:options.override?.thinking!==void 0}]}function buildModelChoices(options){let choices=new Map;choices.set(`inherit (${modelId(options.currentSessionModel)})${options.savedModelId?"":" \u2713"}`,void 0),options.savedModelId&&!findModel(options.models,options.savedModelId)&&choices.set(`${options.savedModelId} [unavailable] \u2713`,options.savedModelId);for(let model of options.models){let id=modelId(model);choices.set(`${id}${options.savedModelId===id?" \u2713":""}`,id)}return choices}function buildThinkingChoices(options){let effective=effectiveModel(options.currentSessionModel,options.models,options.override),levels=effective?getSupportedThinkingLevels(effective):[...THINKING_LEVELS2],inherited=inheritedThinking(effective,options.currentThinking),choices=new Map;choices.set(`inherit (${inherited})${options.override?.thinking?"":" \u2713"}`,void 0);for(let level of levels)choices.set(`${level}${options.override?.thinking===level?" \u2713":""}`,level);return choices}async function persistOverride(ctx,profile,patch){try{return await updateProfileOverride(profile.name,patch,getAgentDir())}catch(error){ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error?error.message:String(error)}`,"error");return}}async function selectProfile(ctx){let labels=AGENT_PROFILES.map(profile=>AGENT_PROFILE_LABELS[profile.name]),label=await ctx.ui.select("Agents",labels);return label===void 0?void 0:AGENT_PROFILES.find(profile=>AGENT_PROFILE_LABELS[profile.name]===label)}async function showDialogSettingsMenu(ctx,profile,override,currentThinking){let options=new Map;for(let row of buildSettingsRows({override,models:ctx.modelRegistry.getAvailable(),currentSessionModel:ctx.model,currentThinking}))options.set(`${row.label} \u2014 ${row.value}`,row.action);let label=await ctx.ui.select(AGENT_PROFILE_LABELS[profile.name],[...options.keys()]);return label===void 0?void 0:options.get(label)}async function showDialogModelPicker(ctx,profile,override){let models=[...ctx.modelRegistry.getAvailable()].sort(compareModels),choices=buildModelChoices({models,currentSessionModel:ctx.model,savedModelId:override?.model}),label=await ctx.ui.select(`Model \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,[...choices.keys()]);return label===void 0?void 0:{modelId:choices.get(label)}}async function showDialogThinkingPicker(ctx,profile,override,currentThinking){let choices=buildThinkingChoices({currentSessionModel:ctx.model,models:ctx.modelRegistry.getAvailable(),override,currentThinking}),label=await ctx.ui.select(`Thinking \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,[...choices.keys()]);return label===void 0?void 0:{level:choices.get(label)}}async function runDialogProfileSettings(ctx,profile,currentThinking){let agentDir=getAgentDir();for(;;){let override=(await loadSubagentConfig(agentDir,message=>ctx.ui.notify(message,"warning"))).profiles[profile.name],action=await showDialogSettingsMenu(ctx,profile,override,currentThinking);if(!action)return;if(action==="model"){let chosen=await showDialogModelPicker(ctx,profile,override);if(!chosen)continue;await persistOverride(ctx,profile,{model:chosen.modelId})}else{let chosen=await showDialogThinkingPicker(ctx,profile,override,currentThinking);if(!chosen)continue;await persistOverride(ctx,profile,{thinking:chosen.level})}}}async function showDialogAgentsCommand(ctx,currentThinking){for(;;){let profile=await selectProfile(ctx);if(!profile)return;await runDialogProfileSettings(ctx,profile,currentThinking)}}function hint(theme2,keybindings,binding,description){let key=keyLabel(binding,{keybindings});return key?`${theme2.fg("dim",key)}${theme2.fg("muted",` ${description}`)}`:""}function navigationHint(theme2,keybindings){let keys=[keyLabel("tui.select.up",{keybindings}),keyLabel("tui.select.down",{keybindings})].filter(Boolean).join("/");return keys?`${theme2.fg("dim",keys)}${theme2.fg("muted"," navigate")}`:""}var ChoiceMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2}constructor(options){super(),this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.choices=options.choices,this.onDone=options.onDone,this.title=options.title,this.cancelDescription=options.cancelDescription,this.selectedIndex=Math.min(Math.max(options.initialIndex??0,0),Math.max(0,options.choices.length-1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText(),this.updateList()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title)));let hints=[navigationHint(this.theme,this.keybindings),hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel",this.cancelDescription)].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}updateList(){this.listContainer.clear();for(let[index3,choice]of this.choices.entries()){let selected=index3===this.selectedIndex,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=this.theme.fg(selected?"accent":"text",choice.label);this.listContainer.addChild(new TruncatedText(`${prefix}${label}`,1,0))}}moveSelection(offset){this.choices.length!==0&&(this.selectedIndex=(this.selectedIndex+offset+this.choices.length)%this.choices.length,this.updateList())}invalidate(){this.updateStaticText(),this.updateList(),super.invalidate()}handleInput(data){if(this.keybindings.matches(data,"tui.select.up"))this.moveSelection(-1);else if(this.keybindings.matches(data,"tui.select.down"))this.moveSelection(1);else if(this.keybindings.matches(data,"tui.select.confirm")){let choice=this.choices[this.selectedIndex];choice&&this.onDone(choice)}else this.keybindings.matches(data,"tui.select.cancel")&&this.onDone(void 0)}};var MAX_VISIBLE_MODELS=10;function modelSearchText(item){return item.modelId===void 0?`inherit ${item.model?getModelSelectorSearchText(item.model):""}`:getModelSelectorSearchText(item)}var ProfileModelListComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.searchInput.focused=value2}constructor(options){super(),this.allChoices=[],this.scopedChoices=[],this.activeChoices=[],this.filteredChoices=[],this.selectedIndex=0,this.statusTone="muted",this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.models=[...options.models],this.currentSessionModel=options.currentSessionModel,this.savedModelId=options.savedModelId,this.scopedModelKeys=new Set(options.scopedModels.map(({model})=>modelId(model))),this.scope=this.scopedModelKeys.size>0?"scoped":"all",this.onDone=options.onDone,this.scopeContainer=new Container,this.addChild(this.scopeContainer),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.rebuildChoices(this.savedModelId??"")}makeInheritChoice(){return{key:"",modelId:void 0,model:this.currentSessionModel,unavailable:!1,provider:this.currentSessionModel?.provider??"",id:"inherit",name:this.currentSessionModel?.name}}makeModelChoice(model){return{key:modelId(model),modelId:modelId(model),model,unavailable:!1,provider:model.provider,id:model.id,name:model.name}}makeUnavailableChoice(modelId2){let parsed=parseModelSpec(modelId2);return{key:modelId2,modelId:modelId2,model:void 0,unavailable:!0,provider:parsed.provider,id:parsed.id,name:void 0}}buildChoices(models){let sorted=[...models].sort(compareModels),availableById=new Map(this.models.map(model=>[modelId(model),model])),choices=[this.makeInheritChoice()];if(this.savedModelId){let saved=availableById.get(this.savedModelId);choices.push(saved?this.makeModelChoice(saved):this.makeUnavailableChoice(this.savedModelId))}for(let model of sorted)modelId(model)!==this.savedModelId&&choices.push(this.makeModelChoice(model));return choices}rebuildChoices(preferredKey){let currentKey=preferredKey??this.filteredChoices[this.selectedIndex]?.key??this.savedModelId??"";this.allChoices=this.buildChoices(this.models);let scopedModels=this.models.filter(model=>this.scopedModelKeys.has(modelId(model)));this.scopedChoices=this.buildChoices(scopedModels),this.activeChoices=this.scope==="scoped"?this.scopedChoices:this.allChoices,this.applyFilter(this.searchInput.getValue(),currentKey,!1),this.updateScopeView()}applyFilter(query,preferredKey,resetSelection=!0){if(this.filteredChoices=query?fuzzyFilter(this.activeChoices,query,modelSearchText):this.activeChoices,preferredKey!==void 0){let preferredIndex=this.filteredChoices.findIndex(choice=>choice.key===preferredKey);this.selectedIndex=preferredIndex>=0?preferredIndex:0}else query&&resetSelection?this.selectedIndex=0:this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredChoices.length-1));this.updateList()}updateScopeView(){if(this.scopeContainer.clear(),this.scopedModelKeys.size===0){this.scopeContainer.addChild(new Text(this.theme.fg("warning","Only showing models from configured providers. Use /login to add providers."),0,0)),this.scopeContainer.addChild(new Spacer(1));return}let all=this.scope==="all"?this.theme.fg("accent","all"):this.theme.fg("muted","all"),scoped=this.scope==="scoped"?this.theme.fg("accent","scoped"):this.theme.fg("muted","scoped");this.scopeContainer.addChild(new Text(`${this.theme.fg("muted","Scope: ")}${all}${this.theme.fg("muted"," | ")}${scoped}`,0,0)),this.scopeContainer.addChild(new Spacer(1))}choiceLabel(choice){if(choice.modelId===void 0){let inherited=choice.model?modelId(choice.model):"none";return`inherit ${this.theme.fg("muted",`(${inherited})`)}`}if(choice.unavailable){let badge=choice.provider?`${choice.provider} \xB7 unavailable`:"unavailable";return`${choice.id} ${this.theme.fg("warning",`[${badge}]`)}`}return`${choice.id} ${this.theme.fg("muted",`[${choice.provider}]`)}`}updateList(){this.listContainer.clear();let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(MAX_VISIBLE_MODELS/2),this.filteredChoices.length-MAX_VISIBLE_MODELS)),endIndex=Math.min(startIndex+MAX_VISIBLE_MODELS,this.filteredChoices.length);for(let index3=startIndex;index3<endIndex;index3++){let choice=this.filteredChoices[index3];if(!choice)continue;let selected=index3===this.selectedIndex,saved=choice.modelId===this.savedModelId,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=this.choiceLabel(choice),styledLabel=selected?this.theme.fg("accent",label):label,checkmark=saved?this.theme.fg("success"," \u2713"):"";this.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`,0,0))}if((startIndex>0||endIndex<this.filteredChoices.length)&&this.listContainer.addChild(new TruncatedText(this.theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredChoices.length})`),0,0)),this.filteredChoices.length===0)this.listContainer.addChild(new Text(this.theme.fg("muted"," No matching models"),0,0));else{let selected=this.filteredChoices[this.selectedIndex];selected?.model?.name&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(this.theme.fg("muted",` Model Name: ${selected.model.name}`),0,0)))}this.statusMessage&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(this.theme.fg(this.statusTone,` ${this.statusMessage}`),0,0)))}moveSelection(offset){this.filteredChoices.length!==0&&(this.selectedIndex=(this.selectedIndex+offset+this.filteredChoices.length)%this.filteredChoices.length,this.updateList())}toggleScope(){if(this.scopedModelKeys.size===0)return;let currentKey=this.filteredChoices[this.selectedIndex]?.key;this.scope=this.scope==="all"?"scoped":"all",this.activeChoices=this.scope==="scoped"?this.scopedChoices:this.allChoices,this.applyFilter(this.searchInput.getValue(),currentKey,!1),this.updateScopeView()}getSelectedChoice(){let selected=this.filteredChoices[this.selectedIndex];if(selected)return{modelId:selected.modelId,model:selected.model,unavailable:selected.unavailable}}updateModels(models){let selectedKey=this.filteredChoices[this.selectedIndex]?.key;this.models=[...models],this.rebuildChoices(selectedKey)}setStatus(message,tone="muted"){this.statusMessage=message,this.statusTone=tone,this.updateList()}invalidate(){this.updateScopeView(),this.updateList(),super.invalidate()}handleInput(data){if(this.keybindings.matches(data,"tui.input.tab"))this.toggleScope();else if(this.keybindings.matches(data,"tui.select.up"))this.moveSelection(-1);else if(this.keybindings.matches(data,"tui.select.down"))this.moveSelection(1);else if(this.keybindings.matches(data,"tui.select.confirm")){let selected=this.getSelectedChoice();selected&&this.onDone(selected)}else this.keybindings.matches(data,"tui.select.cancel")?this.onDone(void 0):(this.searchInput.handleInput(data),this.applyFilter(this.searchInput.getValue()))}};var MODEL_REFRESH_TIMEOUT_MS=15e3,MAX_REFRESH_ERROR_LENGTH=240;function refreshFailureMessage(providerIds){if(providerIds.length===1)return`Could not refresh ${providerIds[0]}; showing cached models.`;let visible=providerIds.slice(0,3),omitted=providerIds.length-visible.length,suffix=omitted>0?`, +${omitted} more`:"";return`Could not refresh ${providerIds.length} model catalogs (${visible.join(", ")}${suffix}); showing cached models.`}var ModelPickerComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.modelList.focused=value2}constructor(options){super(),this.refreshAbortController=new AbortController,this.closed=!1,this._focused=!1,this.tui=options.tui,this.theme=options.theme,this.keybindings=options.keybindings,this.title=`Model \u2014 ${AGENT_PROFILE_LABELS[options.profile.name]}`,this.hasScopedModels=options.scopedModels.length>0,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.modelList=new ProfileModelListComponent({theme:options.theme,keybindings:options.keybindings,models:options.models,scopedModels:options.scopedModels,currentSessionModel:options.currentSessionModel,savedModelId:options.savedModelId,onDone:options.onDone}),this.addChild(this.modelList),this.addChild(new Spacer(1)),this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title)));let hints=[navigationHint(this.theme,this.keybindings),this.hasScopedModels?hint(this.theme,this.keybindings,"tui.input.tab","scope"):"",hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel","back")].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}get refreshSignal(){return this.refreshAbortController.signal}cancelRefresh(){this.refreshAbortController.abort()}get isClosed(){return this.closed}dispose(){this.closed=!0,this.refreshAbortController.abort()}updateModels(models){this.closed||(this.modelList.updateModels(models),this.tui.requestRender())}setRefreshStatus(message,tone="muted"){this.closed||(this.modelList.setStatus(message,tone),this.tui.requestRender())}invalidate(){this.updateStaticText(),super.invalidate()}handleInput(data){this.modelList.handleInput(data)}};async function refreshPickerModels(ctx,picker){let timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,picker.cancelRefresh()},MODEL_REFRESH_TIMEOUT_MS);timeout.unref?.();try{let result2=await refreshModelCatalogs(ctx.modelRuntime,picker.refreshSignal);if(picker.isClosed||picker.refreshSignal.aborted&&!timedOut)return;if(picker.updateModels(ctx.modelRegistry.getAvailable()),result2.aborted&&timedOut){picker.setRefreshStatus("Model refresh timed out; showing cached models.","error");return}let providerIds=[...result2.errors.keys()];if(providerIds.length>0){picker.setRefreshStatus(refreshFailureMessage(providerIds),"error");return}let registryError=ctx.modelRegistry.getError?.();if(registryError){picker.setRefreshStatus(truncate4(registryError,MAX_REFRESH_ERROR_LENGTH),"error");return}picker.setRefreshStatus(void 0)}catch(error){if(picker.isClosed||picker.refreshSignal.aborted&&!timedOut)return;let message=timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`;picker.setRefreshStatus(truncate4(message,MAX_REFRESH_ERROR_LENGTH),"error")}finally{clearTimeout(timeout)}}var ProfileSettingsMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2}constructor(options){super(),this.selectedIndex=0,this._focused=!1,this.theme=options.theme,this.keybindings=options.keybindings,this.onDone=options.onDone,this.title=AGENT_PROFILE_LABELS[options.profile.name],this.status=options.status,this.rows=buildSettingsRows({override:options.override,models:options.models,currentSessionModel:options.currentSessionModel,currentThinking:options.currentThinking}),this.selectedIndex=Math.max(0,this.rows.findIndex(row=>row.action===options.selectedAction)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text("",1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.status?(this.statusText=new Text("",1,0),this.addChild(this.statusText),this.addChild(new Spacer(1))):this.statusText=void 0,this.hintText=new Text("",1,0),this.addChild(this.hintText),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateStaticText(),this.updateList()}updateStaticText(){this.titleText.setText(this.theme.fg("accent",this.theme.bold(this.title))),this.statusText?.setText(this.theme.fg("muted",this.status??""));let hints=[navigationHint(this.theme,this.keybindings),hint(this.theme,this.keybindings,"tui.select.confirm","select"),hint(this.theme,this.keybindings,"tui.select.cancel","back")].filter(Boolean);this.hintText.setText(hints.join(this.theme.fg("muted"," \u2022 ")))}updateList(){this.listContainer.clear();for(let[index3,row]of this.rows.entries()){let selected=index3===this.selectedIndex,prefix=selected?this.theme.fg("accent","\u2192 "):" ",label=selected?this.theme.fg("accent",row.label):this.theme.fg("text",row.label),value2=this.theme.fg("muted",`\u2014 ${row.value}`),checkmark=row.override?this.theme.fg("success"," \u2713"):"";this.listContainer.addChild(new TruncatedText(`${prefix}${label} ${value2}${checkmark}`,1,0))}}moveSelection(offset){this.selectedIndex=(this.selectedIndex+offset+this.rows.length)%this.rows.length,this.updateList()}invalidate(){this.updateStaticText(),this.updateList(),super.invalidate()}handleInput(data){this.keybindings.matches(data,"tui.select.up")?this.moveSelection(-1):this.keybindings.matches(data,"tui.select.down")?this.moveSelection(1):this.keybindings.matches(data,"tui.select.confirm")?this.onDone(this.rows[this.selectedIndex]?.action):this.keybindings.matches(data,"tui.select.cancel")&&this.onDone(void 0)}};async function persistOverride2(ctx,profile,patch){try{return await updateProfileOverride(profile.name,patch,getAgentDir())}catch(error){ctx.ui.notify(`Could not save ${AGENT_PROFILE_LABELS[profile.name]} settings: ${error instanceof Error?error.message:String(error)}`,"error");return}}var AgentsMenuComponent=class extends Container{get focused(){return this._focused}set focused(value2){this._focused=value2,this.activeScreen&&isFocusable(this.activeScreen)&&(this.activeScreen.focused=value2)}constructor(options){super(),this.route={kind:"profiles"},this.selectedSettingsAction="model",this.saving=!1,this.closed=!1,this._focused=!1,this.tui=options.tui,this.theme=options.theme,this.keybindings=options.keybindings,this.ctx=options.ctx,this.currentThinking=options.currentThinking,this.config=options.config,this.onDone=options.onDone,this.showProfiles()}disposeActiveScreen(){let screen=this.activeScreen;if(this.activeScreen=void 0,!screen)return;let disposable=screen;isFocusable(screen)&&(screen.focused=!1),disposable.dispose?.()}setActiveScreen(screen){this.disposeActiveScreen(),this.clear(),this.activeScreen=screen,this.addChild(screen),isFocusable(screen)&&(screen.focused=this._focused),this.tui.requestRender()}showProfiles(){this.route={kind:"profiles"};let choices=AGENT_PROFILES.map(profile=>({label:AGENT_PROFILE_LABELS[profile.name],value:profile})),initialIndex=choices.findIndex(choice=>choice.value.name===this.selectedProfile?.name);this.setActiveScreen(new ChoiceMenuComponent({theme:this.theme,keybindings:this.keybindings,title:"Agents",choices,initialIndex,cancelDescription:"close",onDone:choice=>{if(!choice){this.onDone();return}this.selectedProfile=choice.value,this.selectedSettingsAction="model",this.showSettings(choice.value)}}))}showSettings(profile,selectedAction=this.selectedSettingsAction){this.selectedProfile=profile,this.selectedSettingsAction=selectedAction,this.route={kind:"settings",profile,selectedAction},this.setActiveScreen(new ProfileSettingsMenuComponent({theme:this.theme,keybindings:this.keybindings,profile,override:this.config.profiles[profile.name],models:this.ctx.modelRegistry.getAvailable(),currentSessionModel:this.ctx.model,currentThinking:this.currentThinking,selectedAction,status:this.saving?"Saving\u2026":void 0,onDone:action=>{if(!action){this.showProfiles();return}this.selectedSettingsAction=action,action==="model"?this.showModelPicker(profile):this.showThinkingPicker(profile)}}))}showModelPicker(profile){this.route={kind:"model",profile};let override=this.config.profiles[profile.name],picker=new ModelPickerComponent({tui:this.tui,theme:this.theme,keybindings:this.keybindings,profile,savedModelId:override?.model,models:this.ctx.modelRegistry.getAvailable(),scopedModels:this.ctx.scopedModels,currentSessionModel:this.ctx.model,onDone:choice=>{if(!choice){this.showSettings(profile,"model");return}this.saveOverride(profile,{model:choice.modelId},"model")}});picker.setRefreshStatus("Refreshing model catalogs\u2026"),this.setActiveScreen(picker),refreshPickerModels(this.ctx,picker)}showThinkingPicker(profile){this.route={kind:"thinking",profile};let override=this.config.profiles[profile.name],choices=[...buildThinkingChoices({currentSessionModel:this.ctx.model,models:this.ctx.modelRegistry.getAvailable(),override,currentThinking:this.currentThinking}).entries()].map(([label,level])=>({label,value:level})),initialIndex=choices.findIndex(choice=>choice.label.endsWith(" \u2713"));this.setActiveScreen(new ChoiceMenuComponent({theme:this.theme,keybindings:this.keybindings,title:`Thinking \u2014 ${AGENT_PROFILE_LABELS[profile.name]}`,choices,initialIndex,cancelDescription:"back",onDone:choice=>{if(!choice){this.showSettings(profile,"thinking");return}this.saveOverride(profile,{thinking:choice.value},"thinking")}}))}saveOverride(profile,patch,returnAction){this.saving||(this.saving=!0,this.showSettings(profile,returnAction),persistOverride2(this.ctx,profile,patch).then(config=>this.completeSave(profile,config),()=>this.completeSave(profile,void 0)).catch(()=>{}))}completeSave(profile,config){this.closed||(this.saving=!1,config&&(this.config=config),this.route.kind==="settings"&&this.route.profile.name===profile.name&&this.showSettings(profile,this.route.selectedAction))}handleInput(data){if(!this.saving){this.activeScreen?.handleInput?.(data);return}this.keybindings.matches(data,"tui.select.cancel")&&(this.route.kind==="settings"?this.showProfiles():this.route.kind==="profiles"&&this.onDone())}dispose(){this.closed=!0,this.disposeActiveScreen(),this.clear()}};async function showTuiAgentsCommand(ctx,currentThinking){let config=await loadSubagentConfig(getAgentDir(),message=>ctx.ui.notify(message,"warning"));await ctx.ui.custom((tui,theme2,keybindings,done)=>new AgentsMenuComponent({tui,theme:theme2,keybindings,ctx,currentThinking,config,onDone:()=>done()}))}async function showAgentsCommand(ctx,currentThinking){if(!ctx.hasUI){ctx.ui.notify("/agents requires an interactive UI.","warning");return}ctx.mode==="tui"?await showTuiAgentsCommand(ctx,currentThinking):await showDialogAgentsCommand(ctx,currentThinking)}import{relative as relative8}from"node:path";function runId(batchId,index3){if(!batchId)return`subagent-${index3+1}`;let sanitized=batchId.replace(/[^A-Za-z0-9-]+/gu,"-").replace(/^-+|-+$/gu,""),hash=hashRunId(batchId);return`${sanitized.length>24?`${sanitized.slice(0,24)}-${hash}`:sanitized||`run-${hash}`}-${index3+1}`}function hashRunId(value2){let hash=2166136261;for(let index3=0;index3<value2.length;index3++)hash^=value2.charCodeAt(index3),hash=Math.imul(hash,16777619);return(hash>>>0).toString(36).padStart(6,"0").slice(0,6)}function createRunState(task,index3,batchId,parentCwd){return{id:runId(batchId,index3),agent:task.agent.name,description:task.description,cwd:relative8(parentCwd,task.cwd),model:modelId(task.model),thinking:task.thinking,status:"queued",activities:[],report:"",reportTruncated:!1,usage:emptyUsage3(),version:0}}function toRunDetails(state2){let{version:_version,reportTruncated:_reportTruncated,...details}=state2;return details}function deriveCurrentActivity(state2){if(!(state2.status==="completed"||state2.status==="failed"||state2.status==="aborted")){if(state2.retry)return`Retrying (${state2.retry.attempt}/${state2.retry.maxAttempts})\u2026`;for(let index3=state2.activities.length-1;index3>=0;index3--){let activity=state2.activities[index3];if(activity?.status==="running")return activity.summary}}}function positiveInteger(value2,fallback){return Number.isFinite(value2)?Math.max(1,Math.floor(value2)):fallback}function retryError(error){let normalized=error.replace(/\s+/gu," ").trim();return boundText2(normalized,160).replace(/\s+/gu," ").trim()}function makeRetry(attempt2,maxAttempts,deadline,error){let normalizedAttempt=positiveInteger(attempt2,1);return{attempt:normalizedAttempt,maxAttempts:Math.max(normalizedAttempt,positiveInteger(maxAttempts,normalizedAttempt)),deadline,error:retryError(error)}}function oldestEvictableActivityIndex(activities){let protectedIndexes=new Set;for(let index3=activities.length-1;index3>=0&&protectedIndexes.size<3;index3--){let activity=activities[index3];activity&&isDisplayableActivity(activity)&&protectedIndexes.add(index3)}let unprotected=activities.findIndex((_activity,index3)=>!protectedIndexes.has(index3));return unprotected>=0?unprotected:activities.length>1?0:-1}function activityTextSize(activities){return activities.reduce((total,item)=>total+item.summary.length+(item.resultSummary?.length??0),0)}function enforceActivityLimits(activities){for(;activities.length>80;){let index3=oldestEvictableActivityIndex(activities);if(index3<0)break;activities.splice(index3,1)}for(;activityTextSize(activities)>24576;){let index3=oldestEvictableActivityIndex(activities);if(index3<0)break;activities.splice(index3,1)}}function appendActivity(activities,activity){activities.push(activity),enforceActivityLimits(activities)}function isTerminal(state2){return state2.status==="completed"||state2.status==="failed"||state2.status==="aborted"}function withRevision(state2,mutate){let draft={...state2,activities:state2.activities.map(activity=>({...activity})),usage:{...state2.usage}};return mutate(draft),draft.version=state2.version+1,draft}function clearRetry(draft){draft.retry=void 0}function reduceRun(state2,event){return isTerminal(state2)&&event.type!=="retry_scheduled"?state2:withRevision(state2,draft=>{event.type!=="retry_scheduled"&&clearRetry(draft),applyEvent(draft,event),draft.currentActivity=deriveCurrentActivity(draft)})}function handleSlotAcquired(draft,event){draft.status="running",draft.startedAt=event.startedAt}function handleRetryScheduled(draft,event){let error=draft.error??"Subagent failed before retry.";draft.status="queued",draft.error=void 0,draft.startedAt=void 0,draft.endedAt=void 0,draft.report="",draft.reportTruncated=!1,draft.activities=[],draft.usage.turns=0,draft.usage.toolUses=0,draft.usage.contextTokens=void 0,draft.retry=makeRetry(event.attempt,event.maxAttempts,event.deadline,error)}function handleAutoRetryStart(draft,event){draft.retry=makeRetry(event.attempt,event.maxAttempts,event.deadline,event.error)}function handleTurnEnd(draft){draft.usage.turns++}function handleAssistantMessageSettled(draft,event){addUsage2(draft.usage,event.usage)}function handleToolStarted(draft,event){draft.usage.toolUses++,appendActivity(draft.activities,{id:event.toolCallId,toolName:event.toolName,summary:activitySummary(event.toolName,event.args),status:"running",startedAt:event.startedAt})}function handleToolUpdated(draft,event){let summary=activitySummary(event.toolName,event.args),activity=draft.activities.find(candidate=>candidate.id===event.toolCallId&&candidate.status==="running")??[...draft.activities].reverse().find(candidate=>candidate.status==="running");activity&&(activity.summary=summary,enforceActivityLimits(draft.activities))}function handleToolEnded(draft,event){let activity=draft.activities.find(candidate=>candidate.id===event.toolCallId);activity&&activity.status==="running"&&(activity.status=event.isError?"failed":"succeeded",activity.endedAt=event.endedAt,activity.resultSummary=resultSummary(event.result)||void 0,enforceActivityLimits(draft.activities))}function handleCompactionStarted(draft,event){appendActivity(draft.activities,{id:COMPACTION_ACTIVITY_ID,toolName:COMPACTION_ACTIVITY_ID,summary:"Compacting context\u2026",status:"running",startedAt:event.startedAt})}function handleCompactionEnded(draft,event){let contextTokens=draft.usage.contextTokens;addUsage2(draft.usage,event.usage),draft.usage.contextTokens=contextTokens;let activity=[...draft.activities].reverse().find(candidate=>candidate.id===COMPACTION_ACTIVITY_ID&&candidate.status==="running");activity&&(activity.status=event.error?"failed":"succeeded",activity.endedAt=event.endedAt,activity.summary=compactionSummary(event.tokensBefore,event.tokensAfter),activity.resultSummary=event.error?compactionError(event.error):void 0,enforceActivityLimits(draft.activities))}function handleSettle(draft,event){draft.status=event.verdict,draft.report=boundText2(event.report,32768),draft.reportTruncated=draft.report!==event.report,draft.error=event.error?boundText2(event.error,8192):void 0,draft.endedAt=event.endedAt,draft.retry=void 0}function handleAbortWhileQueued(draft,event){draft.status="aborted",draft.error="Subagent was aborted while queued.",draft.endedAt=event.endedAt,draft.retry=void 0}function handleAbortWhileRetrying(draft,event){draft.status="aborted",draft.error="Subagent was aborted while waiting to retry.",draft.endedAt=event.endedAt,draft.retry=void 0}function applyEvent(draft,event){switch(event.type){case"slot_acquired":handleSlotAcquired(draft,event);break;case"retry_scheduled":handleRetryScheduled(draft,event);break;case"retry_started":break;case"auto_retry_start":handleAutoRetryStart(draft,event);break;case"auto_retry_end":break;case"turn_end":handleTurnEnd(draft);break;case"assistant_message_settled":handleAssistantMessageSettled(draft,event);break;case"tool_started":handleToolStarted(draft,event);break;case"tool_updated":handleToolUpdated(draft,event);break;case"tool_ended":handleToolEnded(draft,event);break;case"compaction_started":handleCompactionStarted(draft,event);break;case"compaction_ended":handleCompactionEnded(draft,event);break;case"settle":handleSettle(draft,event);break;case"abort_while_queued":handleAbortWhileQueued(draft,event);break;case"abort_while_retrying":handleAbortWhileRetrying(draft,event);break}}function versionSum(runs){let total=0;for(let run of runs)total+=run.version;return total}function statusOf(runs){return runs.length===0||runs.some(run=>run.status==="queued"||run.status==="running")?"running":runs.every(run=>run.status==="completed")?"completed":runs.some(run=>run.status==="completed")?"partial":runs.every(run=>run.status==="aborted")?"aborted":"failed"}function isSubagentError(details){return details.status!=="failed"&&details.status!=="aborted"?!1:!details.runs.some(run=>run.status==="completed")}function statusText(details){if(details.runs.length===0)return"Initializing\u2026";let running=details.runs.filter(run=>run.status==="running").length,queued=details.runs.filter(run=>run.status==="queued").length,completed=details.runs.filter(run=>run.status==="completed").length,failed=details.runs.filter(run=>run.status==="failed").length,aborted=details.runs.filter(run=>run.status==="aborted").length,parts=[`${completed}/${details.runs.length} complete`];return running&&parts.push(`${running} running`),queued&&parts.push(`${queued} queued`),failed&&parts.push(`${failed} failed`),aborted&&parts.push(`${aborted} aborted`),parts.join(" \xB7 ")}function statusSummary(details){return statusText(details)}function getSubagentRetryView(run,now=Date.now()){let retry=run.retry;if(!retry||!Number.isFinite(retry.deadline))return;let attempt2=positiveInteger(retry.attempt,1),maxAttempts=Math.max(attempt2,positiveInteger(retry.maxAttempts,attempt2)),currentTime=Number.isFinite(now)?now:retry.deadline;return{attempt:attempt2,maxAttempts,remainingSeconds:Math.max(0,Math.ceil((retry.deadline-currentTime)/1e3)),error:retryError(typeof retry.error=="string"?retry.error:"")}}var RETRY_ERROR_LIMIT=160,FALLBACK_OUTPUT_LIMIT=4e3,OUTPUT_TRUNCATION_NOTICE_PATTERN2=/\s*\[Output truncated(?:: \d+ bytes omitted)?\.\]\s*$/u,ELAPSED_REFRESH_INTERVAL_MS=1e3,FLOW_SEPARATOR=" \xB7 ",FLOW_SEPARATOR_WIDTH=3,SingleLineText=class{constructor(text2){this.text=text2}render(width){return[truncateToWidth(this.text,Math.max(1,width),"...")]}invalidate(){}};function taskPrompt(args,index3,run){return args.tasks?.[index3]?.prompt??run.description}function profileLabel(agent){return AGENT_PROFILE_LABELS[agent]??agent}function formatDuration3(seconds){let roundedSeconds=Math.round(seconds);return roundedSeconds>=60?`${Math.floor(roundedSeconds/60)}m ${roundedSeconds%60}s`:`${seconds.toFixed(seconds<10?1:0)}s`}function elapsed(startedAt,endedAt){if(startedAt!==void 0)return formatDuration3(Math.max(0,((endedAt??Date.now())-startedAt)/1e3))}function runMarker(status,theme2){let marker=statusMarker(status);return theme2.fg(marker.color,marker.glyph)}function displayLine(text2){return plainLine(text2).replace(OUTPUT_TRUNCATION_NOTICE_PATTERN2,"...").trim()}function retryText(run){let retry=getSubagentRetryView(run);if(!retry)return;let state2=retry.remainingSeconds>0?`Retrying (${retry.attempt}/${retry.maxAttempts}) in ${retry.remainingSeconds}s`:`Retrying (${retry.attempt}/${retry.maxAttempts}) now...`,error=truncate4(displayLine(retry.error),RETRY_ERROR_LIMIT);return error?`${state2} \xB7 ${error}`:state2}function latestRunningActivity(run,toolName){for(let index3=run.activities.length-1;index3>=0;index3--){let activity=run.activities[index3];if(activity?.status==="running"&&activity.toolName===toolName)return activity}}function formatTotalTokens(value2){let count=Number.isFinite(value2)?Math.max(0,Math.round(value2)):0;if(count<1e3)return String(count);let divisor=count<999950?1e3:1e6,suffix=divisor===1e3?"k":"M",rounded=Math.round(count/divisor*10)/10;return`${Number.isInteger(rounded)?rounded.toFixed(0):rounded.toFixed(1)}${suffix}`}var MARKER_WIDTH=1;function flowSegment(run,index3,theme2,now){let marker;if(run.status==="running"){let glyph=statusSpinnerFrame(now),pad2=Math.max(0,MARKER_WIDTH-visibleWidth(glyph));marker=theme2.fg("accent",glyph)+(pad2>0?" ".repeat(pad2):"")}else marker=runMarker(run.status,theme2);return`${marker} ${theme2.fg("dim",`#${index3+1}`)} ${theme2.fg("accent",profileLabel(run.agent))}`}var CollapsedFlow=class{constructor(segments){this.segments=segments,this.cellWidth=segments.reduce((max,segment2)=>Math.max(max,visibleWidth(segment2)),1)}render(width){let usable=Math.max(1,width),joined=this.segments.join(FLOW_SEPARATOR);if(visibleWidth(joined)<=usable)return[joined];if(this.cellWidth>usable)return this.segments.map(segment2=>truncateToWidth(segment2,usable,"..."));let columnCount=Math.max(1,Math.floor((usable+FLOW_SEPARATOR_WIDTH)/(this.cellWidth+FLOW_SEPARATOR_WIDTH))),lines=[];for(let start=0;start<this.segments.length;start+=columnCount){let row=this.segments.slice(start,start+columnCount);lines.push(row.map((segment2,index3)=>{if(index3===row.length-1)return segment2;let padding=Math.max(0,this.cellWidth-visibleWidth(segment2));return`${segment2}${padding>0?" ".repeat(padding):""}${FLOW_SEPARATOR}`}).join(""))}return lines}invalidate(){}};function toolCallLabel(count){return`${count} tool call${count===1?"":"s"}`}function runHeader(run,index3,theme2){let separator=theme2.fg("dim"," \xB7 "),duration=elapsed(run.startedAt,run.endedAt)??"0.0s",metrics=[run.model,run.thinking,`${formatTotalTokens(run.usage.totalTokens)} tok`,toolCallLabel(run.usage.toolUses),duration].map(metric=>theme2.fg("muted",metric));return[theme2.fg("accent",theme2.bold(`#${index3+1} ${profileLabel(run.agent)}`)),...metrics].join(separator)}function sectionTitle(title,theme2,color2,suffix){let heading=theme2.fg(color2,theme2.bold(title));return suffix?`${heading}${theme2.fg("dim",` \xB7 ${suffix}`)}`:heading}function activityTitleSuffix(total,shown){return total<=3&&shown>=total?toolCallLabel(total):shown>0?`last ${shown} of ${total} tool calls`:toolCallLabel(total)}function activityLine(activity,theme2){let text2=theme2.fg("toolOutput",activityCallText(activity));return activity.status==="failed"?`${theme2.fg("error","\xD7")} ${text2}`:activity.status==="running"?`${theme2.fg("accent","\u203A")} ${text2}`:` ${text2}`}function addPrompt(container,run,index3,args,theme2){container.addChild(new Text(sectionTitle("Prompt",theme2,"toolTitle"),0,0)),container.addChild(new Text(theme2.fg("toolOutput",taskPrompt(args,index3,run)),2,0))}function addActivity(container,run,theme2){let toolCalls=run.activities.filter(isDisplayableActivity),shown=toolCalls.slice(-3),total=Math.max(run.usage.toolUses,toolCalls.length);if(container.addChild(new Text(sectionTitle("Activity",theme2,"toolTitle",activityTitleSuffix(total,shown.length)),0,0)),shown.length===0){let empty=total===0?"No tool calls yet.":"Activity unavailable.";container.addChild(new Text(theme2.fg("muted",empty),2,0));return}for(let activity of shown)container.addChild(new SingleLineText(activityLine(activity,theme2)))}function outcomeColor(status){return status==="completed"?"success":status==="failed"?"error":status==="aborted"?"warning":"accent"}function outcomeReport(run){if(typeof run.report=="string")return run.report;let legacyOutput=run.finalOutput;return typeof legacyOutput=="string"?legacyOutput:""}function hasOutcome(report){return report.trim().length>0}function addOutcomeMarkdown(container,report,theme2){container.addChild(new Markdown(report,2,0,getMarkdownTheme(),{color:text2=>theme2.fg("toolOutput",text2)}))}function addOutcome(container,run,theme2){let color2=outcomeColor(run.status),report=outcomeReport(run);if(container.addChild(new Text(sectionTitle("Outcome",theme2,color2),0,0)),run.status==="queued"||run.status==="running"){container.addChild(new Text(theme2.fg("muted","Still running..."),2,0));let retry=retryText(run);retry?container.addChild(new Text(theme2.fg("warning",retry),2,0)):latestRunningActivity(run,COMPACTION_ACTIVITY_ID)&&container.addChild(new Text(theme2.fg("accent","Compacting context..."),2,0));return}if(run.status==="completed"){hasOutcome(report)?addOutcomeMarkdown(container,report,theme2):container.addChild(new Text(theme2.fg("muted","No outcome returned."),2,0));return}let verdict=run.status==="failed"?"Failed":"Aborted",reason=run.error?`${verdict}: ${run.error}`:`${verdict}.`;container.addChild(new Text(theme2.fg(color2,reason),2,0)),hasOutcome(report)&&(container.addChild(new Spacer(1)),container.addChild(new Text(theme2.fg("muted","Partial outcome:"),2,0)),addOutcomeMarkdown(container,report,theme2))}function renderRun(run,index3,args,theme2){let container=new Container;return container.addChild(new SingleLineText(runHeader(run,index3,theme2))),container.addChild(new Spacer(1)),addPrompt(container,run,index3,args,theme2),container.addChild(new Spacer(1)),addActivity(container,run,theme2),container.addChild(new Spacer(1)),addOutcome(container,run,theme2),container}function fallbackResult(result2,theme2,isError){let text2=result2.content.find(part=>part.type==="text"),value2=text2?.type==="text"?truncate4(text2.text,FALLBACK_OUTPUT_LIMIT):"(no output)";return new Text(theme2.fg(isError?"error":"muted",value2),0,0)}function desiredRefreshInterval(runs,options){if(options.isPartial)return options.expanded?runs.some(run=>run.status==="running"||run.retry!==void 0)?ELAPSED_REFRESH_INTERVAL_MS:void 0:runs.some(run=>run.status==="running")?STATUS_SPINNER_INTERVAL_MS:void 0}function clearLiveRefresh(state2){state2.refreshTimer!==void 0&&clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0,state2.refreshInterval=void 0}function scheduleLiveRefresh(context,isPartial){let state2=context.state;state2.dispose??=()=>clearLiveRefresh(state2);let interval=desiredRefreshInterval(context.result?.details?.runs??[],{isPartial,expanded:context.expanded});if(interval===void 0){clearLiveRefresh(state2);return}if(state2.refreshTimer!==void 0){if(state2.refreshInterval===interval)return;clearTimeout(state2.refreshTimer)}state2.refreshInterval=interval,state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,state2.refreshInterval=void 0,context.invalidate()},interval),state2.refreshTimer.unref?.()}function renderSubagentCall(args,theme2){let count=Array.isArray(args.tasks)?args.tasks.length:0,title=theme2.fg(count>0?"toolTitle":"error",theme2.bold("Subagent"));return new Text(title,0,0)}function renderSubagentResult(result2,options,theme2,args,isError){let details=result2.details;if(details?.background){let summary=`Handed to background \xB7 ${details.background.id}`,rows=options.expanded?details.runs.map((run,index3)=>`#${index3+1} ${profileLabel(run.agent)} \xB7 ${run.status} at handoff`).join(`
|
|
1602
1602
|
`):"",text2=[summary,rows,"Use /bg for live progress and outcomes."].filter(Boolean).join(`
|
|
1603
1603
|
`);return new Text(theme2.fg("muted",text2),0,0)}if(!details||!Array.isArray(details.runs))return fallbackResult(result2,theme2,isError);if(details.runs.length===0)return new Text(theme2.fg("muted","Starting..."),0,0);let container=new Container;if(!options.expanded){let now=Date.now();return container.addChild(new CollapsedFlow(details.runs.map((run,index3)=>flowSegment(run,index3,theme2,now)))),container}for(let[index3,run]of details.runs.entries())index3>0&&container.addChild(new Spacer(1)),container.addChild(renderRun(run,index3,args,theme2));return container}import{existsSync as existsSync24,realpathSync as realpathSync3,statSync as statSync12}from"node:fs";import{dirname as dirname25,isAbsolute as isAbsolute7,relative as relative9,resolve as resolve14}from"node:path";function normalizeCwdInput(value2){if(value2===void 0)return;let trimmed=value2.trim();if(!trimmed)throw new Error("cwd must not be empty.");return trimmed.startsWith("@")?trimmed.slice(1):trimmed}function isWithin(parent,child){let normalizedParent=process.platform==="win32"?parent.toLowerCase():parent,normalizedChild=process.platform==="win32"?child.toLowerCase():child,rest=relative9(normalizedParent,normalizedChild);return rest===""||rest!==".."&&!rest.startsWith(`..${PATH_SEP}`)&&!isAbsolute7(rest)}var PATH_SEP=process.platform==="win32"?"\\":"/";function nearestExistingParent(candidate){let current=candidate;for(let depth=0;depth<64;depth++){let parent=dirname25(current);if(parent===current)return current;if(existsSync24(parent))return parent;current=parent}return current}function resolveTaskCwd(parentCwd,requestedCwd){let value2=normalizeCwdInput(requestedCwd),candidate=value2!==void 0&&isAbsolute7(value2)?resolve14(value2):resolve14(parentCwd,value2??".");if(!existsSync24(candidate))throw new Error(`${candidate} does not exist; nearest existing parent: ${nearestExistingParent(candidate)}`);if(!statSync12(candidate).isDirectory())throw new Error(`Subagent cwd is not a directory: ${candidate}`);let realParent=realpathSync3(parentCwd),realCandidate=realpathSync3(candidate);return{cwd:realCandidate,insideParent:isWithin(realParent,realCandidate)}}function resolveModel(override,parent){if(override?.model)return findAvailableModel(override.model,parent.modelRegistry);if(!parent.model)throw new Error("The parent session has no active model.");return parent.model}function resolveThinking(override,parent,model){let requested=override?.thinking??parent.thinking;return clampThinkingLevel(model,requested)}var DEFAULT_AGENT_NAME="explorer";function taskLabel2(task){let explicit=task.description?.trim();return explicit||truncate4(firstPlainLine(task.prompt),80)}function subagentGroupTitle(tasks){let labels=tasks.map(task=>taskLabel2(task));return labels.length===1?truncate4(`Subagent \xB7 ${labels[0]}`,100):truncate4(`Subagent \xB7 ${tasks.length} tasks: ${labels.join(", ")}`,100)}async function resolveSubagentTask(task,parentCwd,parent,configAgentDir=getAgentDir(),preloadedConfig){let agentName=task.agent??DEFAULT_AGENT_NAME,agent=AGENT_PROFILES.find(candidate=>candidate.name===agentName);if(!agent){let available=AGENT_PROFILES.map(candidate=>candidate.name).join(", ")||"none";throw new Error(`Unknown agent "${agentName}". Available agents: ${available}.`)}let override=(preloadedConfig??await loadSubagentConfig(configAgentDir)).profiles[agent.name],model=resolveModel(override,parent),{cwd,insideParent}=resolveTaskCwd(parentCwd,task.cwd??void 0);return{agent,description:taskLabel2(task),prompt:task.prompt,cwd,insideParent,model,thinking:resolveThinking(override,parent,model)}}var EMPTY_OUTPUT="(Subagent completed but returned no output.)",BATCH_RESERVE_BYTES=1*1024,JSON_ESCAPE_FACTOR=6;function planBudgets(taskCount){let count=Math.max(1,taskCount),perRunDetails=Math.max(1024,Math.floor((122880-8*1024)/count)),headingReserve=Math.min(256*count,Math.floor(49152/4)),fairShare=Math.floor((49152-headingReserve)/count);return{perRunDetails,perRunDetailsReport:Math.min(32768,Math.max(1024,perRunDetails-7*1024)),perTaskReport:Math.min(32768,Math.max(2048,fairShare)),totalReport:49152}}function detailsSize(details){return Buffer.byteLength(JSON.stringify(details),"utf8")}function selectDetailsActivities(activities){if(activities.length<=12)return activities;let required=new Set;for(let index3=activities.length-1;index3>=0&&required.size<3;index3--){let activity=activities[index3];activity&&isDisplayableActivity(activity)&&required.add(index3)}let selected=new Set;for(let index3=activities.length-12;index3<activities.length;index3++)selected.add(index3);for(let index3 of required)selected.add(index3);let ordered=[...selected].sort((left,right)=>left-right);for(;ordered.length>12;){let removable=ordered.findIndex(index3=>!required.has(index3));if(removable===-1)break;ordered.splice(removable,1)}return ordered.map(index3=>activities[index3])}function boundRuns(details,reportLimit){return{...details,runs:details.runs.map(run=>({...run,cwd:boundText2(run.cwd,1024),currentActivity:run.currentActivity?boundText2(run.currentActivity,512):void 0,retry:run.retry?{...run.retry,error:boundText2(run.retry.error,160)}:void 0,activities:selectDetailsActivities(run.activities).map(activity=>({...activity,summary:boundText2(activity.summary,256),resultSummary:activity.resultSummary?boundText2(activity.resultSummary,256):void 0})),report:boundText2(run.report,reportLimit),error:run.error?boundText2(run.error,1024):void 0}))}}function boundSubagentDetails(details){let plan=planBudgets(details.runs.length),optimistic=boundRuns(details,plan.perRunDetailsReport);if(detailsSize(optimistic)<=122880)return optimistic;let count=Math.max(1,details.runs.length),nonReportBytes=detailsSize(boundRuns(details,0)),residual=122880-nonReportBytes-BATCH_RESERVE_BYTES,likely=Math.min(plan.perRunDetailsReport,Math.max(0,Math.floor(residual/count/2))),likelyBounded=boundRuns(details,likely);if(detailsSize(likelyBounded)<=122880)return likelyBounded;let reportLimit=Math.min(plan.perRunDetailsReport,Math.max(0,Math.floor(residual/count/JSON_ESCAPE_FACTOR)));return boundRuns(details,reportLimit)}function reportSectionTitle(run,index3){return`### ${index3+1}. ${run.description} (${run.agent}) \u2014 ${run.status}`}function reportSectionBody(run){if(run.status==="completed")return run.report||EMPTY_OUTPUT;if(run.status==="failed"||run.status==="aborted"){let verdict=run.status==="aborted"?"Subagent aborted":"Subagent failed",cause=run.error?`: ${run.error}`:".",partial=run.report?`
|
|
1604
1604
|
|
|
@@ -1617,8 +1617,9 @@ ${boundText2(reportSectionBody(run),perTaskBudget)}`);return boundText2(sections
|
|
|
1617
1617
|
{"create": [{"subject": "Wire parser", "description": "Parser handles the config format", "status": "in_progress"}]}
|
|
1618
1618
|
{"update": [{"id": 1, "status": "completed"}, {"id": 2, "status": "in_progress"}]}
|
|
1619
1619
|
{"delete": [3]}`,TODO_PROMPT_SNIPPET="Track multi-step coding work with a small outcome-oriented task list",TODO_PROMPT_GUIDELINES=["Use `todo` for work with three or more meaningful steps, for user-provided task lists, and in long sessions where progress can drift; skip it for trivial single-step tasks and simple Q&A.","Mark the `todo` task you are working on in_progress before starting, and completed only after its description is satisfied. Leave no task in_progress when waiting or when all work is done.","When blocked, leave the `todo` task pending and create a task for the blocker instead of faking completion.","Keep the `todo` list short: list before create to avoid duplicates, work in id order, and delete obsolete tasks promptly."];var TODO_DETAILS_SCHEMA_VERSION=3,StatusSchema=StringEnum(["pending","in_progress","completed"],{description:"Task status: pending for future work, in_progress for the single active task, completed for verified done work. At most one task may be in_progress; setting one demotes any other active task to pending."}),TaskIdSchema=typebox_exports.Integer({minimum:1,description:"Positive task id."}),CreateItemSchema=typebox_exports.Object({subject:typebox_exports.String({maxLength:160,description:"Short imperative task subject; a reviewable unit of work."}),description:typebox_exports.String({maxLength:500,description:"What done means for this task: acceptance criteria or verification detail."}),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),UpdateItemSchema=typebox_exports.Object({id:TaskIdSchema,subject:typebox_exports.Optional(typebox_exports.String({maxLength:160,description:"Replacement subject; blank or omitted keeps the current one."})),description:typebox_exports.Optional(typebox_exports.String({maxLength:500,description:"Replacement description (what done means); blank or omitted keeps the current one."})),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),TodoParamsSchema=typebox_exports.Object({create:typebox_exports.Optional(typebox_exports.Array(CreateItemSchema,{maxItems:20,description:"Tasks to add, created atomically in input order; status defaults to pending."})),update:typebox_exports.Optional(typebox_exports.Array(UpdateItemSchema,{maxItems:20,description:"Task edits by id; blank or omitted fields keep their current values."})),delete:typebox_exports.Optional(typebox_exports.Array(TaskIdSchema,{maxItems:20,description:"Ids to remove from the current list; deleting an id that is already absent is a no-op."}))},{additionalProperties:!1}),EMPTY_TODO_STATE={items:[],nextId:1};var TODO_STATUSES=new Set(["pending","in_progress","completed"]),GROUP_FIELDS=new Set(["create","update","delete"]);function isRecord5(value2){return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)}function isPositiveSafeInteger(value2){return typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>=1}function isTodoStatus(value2){return typeof value2=="string"&&TODO_STATUSES.has(value2)}function dedupeIds(ids){let seen=[];for(let id of ids)seen.includes(id)||seen.push(id);return seen}function normalizeText(value2){return value2.trim().replace(/\s+/g," ")}function validateRequiredText(value2,label,maximum){if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(!normalized)throw new Error(`${label} cannot be empty`);if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}function validateOptionalText(value2,label,maximum){if(value2===void 0)return;if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(normalized){if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}}function validateOptionalStatus(value2,label){if(value2!==void 0){if(!isTodoStatus(value2))throw new Error(`${label} is invalid`);return value2}}function readCreateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("create must be an array");if(raw.length>20)throw new Error(`create exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`create[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`create[${index3}].${key} is not a create field; valid fields: subject, description, status`);let entry={subject:validateRequiredText(item.subject,`create[${index3}].subject`,160),description:validateRequiredText(item.description,`create[${index3}].description`,500)},status=validateOptionalStatus(item.status,`create[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readUpdateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("update must be an array");if(raw.length>20)throw new Error(`update exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`update[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="id"&&key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`update[${index3}].${key} is not an update field; valid fields: id, subject, description, status`);if(!isPositiveSafeInteger(item.id))throw new Error(`update[${index3}].id must be a positive integer`);let entry={id:item.id},subject=validateOptionalText(item.subject,`update[${index3}].subject`,160);subject!==void 0&&(entry.subject=subject);let description=validateOptionalText(item.description,`update[${index3}].description`,500);description!==void 0&&(entry.description=description);let status=validateOptionalStatus(item.status,`update[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readDeleteIds(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("delete must be an array");if(raw.length>20)throw new Error(`delete exceeds ${20} ids`);let ids=[];for(let index3=0;index3<raw.length;index3++){if(!isPositiveSafeInteger(raw[index3]))throw new Error(`delete[${index3}] must be a positive integer id`);ids.push(raw[index3])}return ids}function currentIdsLabel(state2){return state2.items.length===0?"the list is empty":`current ids: ${state2.items.map(item=>`#${item.id}`).join(", ")}`}function cloneTodoState(state2){return{items:state2.items.map(item=>({...item})),nextId:state2.nextId}}function applyTodoPatch(before,params){if(!isRecord5(params))throw new Error("todo params must be an object");for(let key of Object.keys(params))if(!GROUP_FIELDS.has(key))throw new Error(`unknown todo field "${key}"; valid fields: create, update, delete`);let createEntries=readCreateEntries(params.create),updateEntries=readUpdateEntries(params.update),deleteIds=readDeleteIds(params.delete),updatedIds=new Set;for(let entry of updateEntries){if(updatedIds.has(entry.id))throw new Error(`#${entry.id} appears more than once in update`);updatedIds.add(entry.id)}let deleteSet=new Set(deleteIds);for(let entry of updateEntries)if(deleteSet.has(entry.id))throw new Error(`#${entry.id} cannot be in both update and delete`);let activations=[];createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&activations.push(`create[${index3}]`)});for(let entry of updateEntries)entry.status==="in_progress"&&activations.push(`#${entry.id}`);if(activations.length>1)throw new Error(`at most one task may be set in_progress per call; got ${activations.join(" and ")}`);let byId=new Map(before.items.map(item=>[item.id,item]));for(let entry of updateEntries)if(!byId.has(entry.id))throw new Error(`#${entry.id} not found; ${currentIdsLabel(before)}`);if(createEntries.length>0){if(!Number.isSafeInteger(before.nextId)||before.nextId<1)throw new Error("next id is invalid");if(before.nextId>Number.MAX_SAFE_INTEGER-createEntries.length)throw new Error("next id is exhausted")}let deleted=[],absent=[];for(let id of dedupeIds(deleteIds)){let item=byId.get(id);item?deleted.push({id:item.id,subject:item.subject}):absent.push(id)}let items=before.items.filter(item=>!deleteSet.has(item.id));if(updateEntries.length>0){let entriesById=new Map(updateEntries.map(entry=>[entry.id,entry]));items=items.map(item=>{let entry=entriesById.get(item.id);return entry?{id:item.id,subject:entry.subject??item.subject,description:entry.description??item.description,status:entry.status??item.status}:item})}let created=[];if(createEntries.length>0){let newItems=createEntries.map((entry,index3)=>({id:before.nextId+index3,subject:entry.subject,description:entry.description,status:entry.status??"pending"}));for(let item of newItems)created.push(item.id);items=[...items,...newItems]}let demotedId,activatedId;for(let entry of updateEntries)entry.status==="in_progress"&&(activatedId=entry.id);if(activatedId===void 0&&createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&(activatedId=before.nextId+index3)}),activatedId!==void 0){let demoted=items.find(item=>item.id!==activatedId&&item.status==="in_progress");demoted&&(demotedId=demoted.id,items=items.map(item=>item.id===demoted.id?{...item,status:"pending"}:item))}let evicted=[];if(items.length>20){let overflow=items.length-20,evictIds=new Set,touched=new Set([...created,...updatedIds]),completedOldestFirst=items.filter(item=>item.status==="completed"&&!touched.has(item.id)).sort((first,second)=>first.id-second.id);for(let item of completedOldestFirst){if(overflow<=0)break;evictIds.add(item.id),evicted.push({id:item.id,subject:item.subject}),overflow--}if(overflow>0){let completedIds=before.items.filter(item=>item.status==="completed").map(item=>`#${item.id}`);throw new Error(`at most ${20} tasks; complete or delete some first. Patch not applied. Tasks created or updated in this call are not reclaimed. Delete existing tasks in the same patch to free space (remove those ids from update), or complete tasks in a separate call before creating more. Completed ids before this call: ${completedIds.join(", ")||"none"}.`)}items=items.filter(item=>!evictIds.has(item.id))}let updated=items.filter(item=>updatedIds.has(item.id)).map(item=>({id:item.id,from:byId.get(item.id).status,to:item.status})),change={created,updated,deleted,absent,evicted};return demotedId!==void 0&&(change.demotedId=demotedId),{state:{items,nextId:before.nextId+created.length},change}}function buildTodoDetails(change,state2){return{schemaVersion:TODO_DETAILS_SCHEMA_VERSION,change,state:cloneTodoState(state2)}}function requireValidState(value2){let state2=normalizeSnapshotState(value2);if(!state2)throw new Error("todo state is invalid");return state2}function createTodoStore(initial){let state2=requireValidState(initial??EMPTY_TODO_STATE);return{getState(){return cloneTodoState(state2)},replaceState(next){state2=requireValidState(next)},execute(params){let patch=applyTodoPatch(state2,params),details=buildTodoDetails(patch.change,patch.state);return state2=patch.state,details}}}function normalizeSnapshotState(value2){if(!isRecord5(value2)||!Array.isArray(value2.items)||!isPositiveSafeInteger(value2.nextId)||value2.items.length>20)return;let items=[],ids=new Set,maxId=0,activeCount=0;for(let rawItem of value2.items){if(!isRecord5(rawItem))return;let id=rawItem.id;if(!isPositiveSafeInteger(id)||ids.has(id))return;let subject=rawItem.subject,description=rawItem.description,status=rawItem.status;if(typeof subject!="string"||typeof description!="string"||subject!==normalizeText(subject)||description!==normalizeText(description)||!subject||subject.length>160||!description||description.length>500||!isTodoStatus(status))return;ids.add(id),id>maxId&&(maxId=id),status==="in_progress"&&activeCount++,items.push({id,subject,description,status})}if(!(activeCount>1)&&!(value2.nextId<=maxId))return{items,nextId:value2.nextId}}function replayTodosFromBranch(ctx){let branch=Array.from(ctx.sessionManager.getBranch());for(let index3=branch.length-1;index3>=0;index3--)try{let entry=branch[index3];if(!isRecord5(entry)||entry.type!=="message")continue;let message=entry.message;if(!isRecord5(message)||message.role!=="toolResult"||message.toolName!==TODO_TOOL_NAME)continue;let details=message.details;if(!isRecord5(details)||details.schemaVersion!==TODO_DETAILS_SCHEMA_VERSION)continue;let state2=normalizeSnapshotState(details.state);if(state2)return state2}catch{}return cloneTodoState(EMPTY_TODO_STATE)}var STATUS_MARK={pending:"[ ]",in_progress:"[>]",completed:"[x]"},STATUS_COLOR={pending:"dim",in_progress:"warning",completed:"success"},STATUS_RANK={in_progress:0,pending:1,completed:2},WIDGET_HEADER_SEPARATOR=" \xB7 ",WIDGET_ITEM_SEPARATOR=" ";function hasOpenTodos(state2){return state2.items.some(item=>item.status==="pending"||item.status==="in_progress")}function widgetCounts(state2){let counts={active:0,pending:0,completed:0};for(let item of state2.items)item.status==="in_progress"?counts.active++:item.status==="pending"?counts.pending++:counts.completed++;return counts}function widgetSegment(item,subject,theme2){return`${theme2.fg(STATUS_COLOR[item.status],STATUS_MARK[item.status])} ${theme2.fg("accent",`#${item.id}`)} ${theme2.fg("text",subject)}`}function widgetLine(header,segments,overflow){let body=[...segments,...overflow?[overflow]:[]].join(WIDGET_ITEM_SEPARATOR);return body?`${header}${WIDGET_HEADER_SEPARATOR}${body}`:header}function renderWidgetLine(state2,theme2,width){let safeWidth=Math.max(1,width),items=state2.items,candidates=items.filter(item=>item.status!=="completed").sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);if(candidates.length===0)return[];let total=items.length,completed=items.filter(item=>item.status==="completed").length,header=`${theme2.fg("accent","Todos")} ${theme2.fg("dim",`${completed}/${total}`)}`,shown=[],overflow="",bestOverflow=trial=>{let remaining=candidates.length-trial.length,segments2=trial.map(entry=>widgetSegment(entry.item,entry.subject,theme2));if(remaining<=0)return visibleWidth(widgetLine(header,segments2,""))<=safeWidth?"":void 0;let short=theme2.fg("dim",`+${remaining} more`);return visibleWidth(widgetLine(header,segments2,short))<=safeWidth?short:void 0},fallback=()=>{let best=bestOverflow([]);return best!==void 0?[widgetLine(header,[],best)]:visibleWidth(header)<=safeWidth?[header]:[truncateToWidth(header,safeWidth,"\u2026")]};for(let candidate of candidates){let best=bestOverflow([...shown,{item:candidate,subject:candidate.subject}]);if(best!==void 0){shown.push({item:candidate,subject:candidate.subject}),overflow=best;continue}if(candidate.status!=="in_progress")break;let remaining=candidates.length-shown.length-1,suffix=remaining>0?`${WIDGET_ITEM_SEPARATOR}+${remaining} more`:"",prefix=`${header}${WIDGET_HEADER_SEPARATOR}${widgetSegment(candidate,"",theme2)}${suffix}`,available=safeWidth-visibleWidth(prefix);if(available<1)return fallback();shown.push({item:candidate,subject:truncateToWidth(candidate.subject,available,"\u2026")}),overflow=bestOverflow(shown)??""}if(shown.length===0)return fallback();let segments=shown.map(entry=>widgetSegment(entry.item,entry.subject,theme2)),line=widgetLine(header,segments,overflow);return[visibleWidth(line)<=safeWidth?line:truncateToWidth(line,safeWidth,"\u2026")]}function formatTodoList(state2){if(state2.items.length===0)return"No todos.";let counts=widgetCounts(state2),lines=[`Todos: ${counts.active} in progress, ${counts.pending} pending, ${counts.completed} completed`],items=[...state2.items].sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);for(let item of items)lines.push(`${STATUS_MARK[item.status]} #${item.id} ${item.subject}`),lines.push(` ${item.description}`);return lines.join(`
|
|
1620
|
-
`)}var formatCommandList=formatTodoList;function formatIdRange(ids){return ids.length>1&&ids.every((id,index3)=>id===ids[0]+index3)?`#${ids[0]}\u2013#${ids[ids.length-1]}`:ids.map(id=>`#${id}`).join(", ")}function formatTodoContent(change,state2){let parts=[];if(change.created.length>0){let labels=change.created.map(id=>{let item=state2.items.find(entry=>entry.id===id);if(!item)return`#${id}`;let suffix=item.status==="pending"?"":` (${item.status})`;return`#${id}: ${item.subject}${suffix}`}),noun=change.created.length===1?"task":"tasks";parts.push(`Created ${change.created.length} ${noun}: ${labels.join("; ")}`)}for(let entry of change.updated){let item=state2.items.find(candidate=>candidate.id===entry.id),subject=item?`: ${item.subject}`:"",transition=entry.from===entry.to?"":` (${entry.from} -> ${entry.to})`;parts.push(`Updated #${entry.id}${transition}${subject}`)}if(change.demotedId!==void 0&&parts.push(`demoted #${change.demotedId} to pending`),change.deleted.length>0){let noun=change.deleted.length===1?"task":"tasks",labels=change.deleted.map(entry=>`#${entry.id}: ${entry.subject}`);parts.push(`Deleted ${change.deleted.length} ${noun}: ${labels.join("; ")}`)}for(let id of change.absent)parts.push(`#${id} already absent`);if(change.evicted.length>0){let ids=change.evicted.map(entry=>entry.id);parts.push(`auto-removed completed ${formatIdRange(ids)} to stay within ${20}`)}return parts.length===0?formatTodoList(state2):parts.join("; ")}var CALL_ITEMS_MAX=20,CALL_SUBJECT_PREVIEW_COUNT=2,CALL_SUBJECT_PREVIEW_WIDTH=72,CALL_DESCRIPTION_PREVIEW_LENGTH=120,
|
|
1621
|
-
`)}function stateIndex(state2){let array=readArray(safeValue2(state2,"items"),20);if(!array||array.length>20)return;let byId=new Map,counts={inProgress:0,pending:0,completed:0};for(let raw of array.values){let item=safeRecord2(raw);if(!item)continue;let id=safeId(safeValue2(item,"id"));id!==void 0&&!byId.has(id)&&byId.set(id,item);let status=safeStatus(safeValue2(item,"status"));status==="in_progress"?counts.inProgress++:status==="pending"?counts.pending++:status==="completed"&&counts.completed++}return{byId,counts}}function stateSubject(map,id){let item=map.get(id);return item?safeSubject(safeValue2(item,"subject")):""}function idSubjectEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id")),subject=safeSubject(safeValue2(item,"subject"));id===void 0||!subject||entries.push({id,subject})}return entries}function updatedEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id"));if(id===void 0)continue;let entry={id},from=safeStatus(safeValue2(item,"from"));from&&(entry.from=from);let to=safeStatus(safeValue2(item,"to"));to&&(entry.to=to),entries.push(entry)}return entries}function formatTodoGroupSuccess(args,theme2,result2){let parsed=todoDetails(result2.details);if(!parsed)return;let{change,state:state2}=parsed,index3=stateIndex(state2),segments=[],pushVerb=(word,body)=>{let title=segments.length===0?`todo ${word}`:word;segments.push(body?`${theme2.fg("toolTitle",title)} ${body}`:theme2.fg("toolTitle",title))},withPreview=(word,ids,subjects)=>{let text2=formatSubjectPreview(subjects,subjects.length),base=theme2.fg("accent",formatIdRange(ids));pushVerb(word,text2?`${base}${theme2.fg("dim"," \xB7 ")}${theme2.fg("text",text2)}`:base)},created=readIds(safeValue2(change,"created"))??[];created.length>0&&index3&&withPreview("created",created,created.map(id=>stateSubject(index3.byId,id)));for(let entry of updatedEntries(safeValue2(change,"updated"))){let parts=[theme2.fg("accent",`#${entry.id}`)];entry.to&&parts.push(theme2.fg(STATUS_COLOR[entry.to],entry.to));let subject=index3?stateSubject(index3.byId,entry.id):"";subject&&parts.push(theme2.fg("text",truncateToWidth(subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"))),pushVerb("updated",parts.join(" "))}let demotedId=safeId(safeValue2(change,"demotedId"));demotedId!==void 0&&segments.push(theme2.fg("dim",`demoted #${demotedId}`));let deleted=idSubjectEntries(safeValue2(change,"deleted"));deleted.length>0&&withPreview("deleted",deleted.map(entry=>entry.id),deleted.map(entry=>entry.subject));for(let id of readIds(safeValue2(change,"absent"))??[])segments.push(theme2.fg("dim",`#${id} already absent`));let evicted=idSubjectEntries(safeValue2(change,"evicted"));if(evicted.length>0&&segments.push(theme2.fg("dim",`auto-removed ${evicted.map(entry=>`#${entry.id}`).join(", ")}`)),segments.length===0){if(!index3)return;let parts=[];return index3.counts.inProgress>0&&parts.push(`${index3.counts.inProgress} in progress`),index3.counts.pending>0&&parts.push(`${index3.counts.pending} pending`),index3.counts.completed>0&&parts.push(`${index3.counts.completed} completed`),`${theme2.fg("toolTitle","todo list")}: ${theme2.fg("dim",parts.length?parts.join(", "):"no tasks")}`}return segments.join(theme2.fg("dim"," ; "))}function formatTodoGroupCall(args,theme2,context){if(context.isError){let reason="tool failed";try{for(let block of context.result?.content.slice(0,8)??[]){if(block.type!=="text"||typeof block.text!="string")continue;let text2=block.text.replace(/[\u0000-\u001f\u007f-\u009f]/g," ").replace(/\s+/g," ").trim();if(text2){reason=text2.length>GROUP_FAILURE_MAX_LENGTH?`${text2.slice(0,GROUP_FAILURE_MAX_LENGTH-1)}\u2026`:text2;break}}}catch{}return`${formatTodoCall(args,theme2,!1)} ${theme2.fg("error",`failed: ${reason}`)}`}if(!context.isPartial&&context.result){let summary=formatTodoGroupSuccess(args,theme2,context.result);if(summary)return summary}return formatTodoCall(args,theme2,!1)}var WIDGET_KEY="todos",TodoWidget=class{constructor(getState2){this.registered=!1,this.getState=getState2}setUI(ui){this.ui!==ui&&(this.dispose(),this.ui=ui)}update(){if(this.ui){if(!hasOpenTodos(this.getState())){this.unregister();return}if(this.registered){this.tui?.requestRender();return}this.ui.setWidget(WIDGET_KEY,(tui,theme2)=>(this.tui=tui,{render:width=>renderWidgetLine(this.getState(),theme2,width),invalidate:()=>{}}),{placement:"aboveEditor"}),this.registered=!0}}unregister(){this.registered&&(this.ui?.setWidget(WIDGET_KEY,void 0),this.registered=!1,this.tui=void 0)}dispose(){this.unregister(),this.ui=void 0}};function safeReplay(ctx,store){try{store.replaceState(replayTodosFromBranch(ctx))}catch(error){if(!isStaleExtensionContextError(error))throw error}}function todo(pi){let store=createTodoStore(),widget;pi.registerTool({name:TODO_TOOL_NAME,label:TODO_TOOL_LABEL,description:TODO_TOOL_DESCRIPTION,promptSnippet:TODO_PROMPT_SNIPPET,promptGuidelines:TODO_PROMPT_GUIDELINES,parameters:TodoParamsSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},executionMode:"sequential",toolGroup:TODO_TOOL_NAME,async execute(_toolCallId,params,_signal,_onUpdate){let details=store.execute(params);return{content:[{type:"text",text:formatTodoContent(details.change,details.state)}],details}},renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(context.toolGroupSummary?formatTodoGroupCall(args,theme2,context):formatTodoCall(args,theme2,context.expanded,context.result)),text2}}),pi.registerCommand(TODOS_COMMAND_NAME,{description:"Show the complete todo list for the current conversation branch",handler:async(_args,ctx)=>{if(!ctx.hasUI){ctx.ui.notify("/todos requires an interactive UI.","warning");return}ctx.ui.notify(formatCommandList(store.getState()),"info")}}),pi.on("session_start",async(_event,ctx)=>{safeReplay(ctx,store),ctx.hasUI&&(widget??=new TodoWidget(()=>store.getState()),widget.setUI(ctx.ui),widget.update())}),pi.on("session_tree",async(_event,ctx)=>{safeReplay(ctx,store),widget?.update()}),pi.on("session_shutdown",async(_event,_ctx)=>{widget?.dispose(),widget=void 0}),pi.on("tool_execution_end",async event=>{event.toolName!==TODO_TOOL_NAME||event.isError||widget?.update()})}var MINIMAX_CN_HOST="https://api.minimaxi.com",MINIMAX_GLOBAL_HOST="https://api.minimax.io";function trimValue(value2){return value2?.trim()||void 0}async function runtimeApiKey(modelRuntime,providerId){if(modelRuntime)try{return trimValue((await modelRuntime.getAuth(providerId))?.auth.apiKey)}catch{return}}function storedApiKey(providerId,authPath){let credential=readStoredCredential(providerId,authPath);if(!credential||credential.type!=="api_key"||typeof credential.key!="string")return;let key=isCommandConfigValue(credential.key)?resolveConfigValue(credential.key,credential.env):credential.key;return trimValue(key)}async function resolveProviderKey(modelRuntime,authPath,providerId,envVar){return await runtimeApiKey(modelRuntime,providerId)??storedApiKey(providerId,authPath)??trimValue(process.env[envVar])}async function resolveMiniMaxCredential(modelRuntime,authPath){let cnKey=await resolveProviderKey(modelRuntime,authPath,"minimax-cn","MINIMAX_CN_API_KEY");if(cnKey)return{key:cnKey,host:MINIMAX_CN_HOST};let globalKey=await resolveProviderKey(modelRuntime,authPath,"minimax","MINIMAX_API_KEY");if(globalKey)return{key:globalKey,host:trimValue(process.env.MINIMAX_API_HOST)??MINIMAX_GLOBAL_HOST}}async function resolveDeepSeekCredential(modelRuntime,authPath){let key=await resolveProviderKey(modelRuntime,authPath,"deepseek","DEEPSEEK_API_KEY");return key?{key}:void 0}function configuredEngine(credentials){return credentials.minimax&&credentials.deepseek?"dual":credentials.minimax?"minimax":credentials.deepseek?"deepseek":"none"}async function resolveSearchCredentials(modelRuntime,authPath=getAuthPath()){let[minimax,deepseek]=await Promise.all([resolveMiniMaxCredential(modelRuntime,authPath),resolveDeepSeekCredential(modelRuntime,authPath)]);return{minimax,deepseek}}var WEB_SEARCH_TOOL_NAME="web_search",WEB_SEARCH_LABEL="Web Search",WEB_SEARCH_DESCRIPTION="Search the live web through configured MiniMax and DeepSeek providers. When both are available, searches run concurrently and results are deduplicated and fused. Returns up to 12 source URLs with bounded titles and snippets, plus related searches and optional synthesis; partial provider failures still return successful results.",WEB_SEARCH_PROMPT_SNIPPET="Search the live web for current information",WEB_SEARCH_DISABLED_MESSAGE="Web search is disabled: Neither MiniMax nor DeepSeek API Key was found in auth.json or environment variables. Please add credentials via auth.json or environment variables (MINIMAX_API_KEY, DEEPSEEK_API_KEY).";function getEngineLabel(engine){return engine==="dual"?"MiniMax & DeepSeek":engine==="minimax"?"MiniMax":engine==="deepseek"?"DeepSeek":""}function getWebSearchPromptGuidelines(){return["Use `web_search` for current information, recent releases, live documentation, and other freshness-sensitive facts beyond your training cutoff.",`When using \`web_search\` for freshness-sensitive topics, account for the current date (${new Date().toISOString().slice(0,7)}) and include the year in the query when useful.`]}var TRACKING_PARAMS=new Set(["utm_source","utm_medium","utm_campaign","utm_term","utm_content","ref","fbclid","gclid","trk","gi"]);function truncateText2(text2,maxLength){return text2.length<=maxLength?text2:maxLength<=3?text2.slice(0,maxLength):`${text2.slice(0,maxLength-3).trimEnd()}...`}function boundSingleLineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.replace(/\s+/g," ").trim();return normalized?truncateText2(normalized,maxLength):void 0}function boundMultilineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.trim();return normalized?truncateText2(normalized,maxLength):void 0}function normalizeUrl(rawUrl){if(typeof rawUrl!="string")return;let trimmed=rawUrl.trim();if(!(!trimmed||trimmed.length>2048))try{let url=new URL(trimmed);if(url.protocol!=="http:"&&url.protocol!=="https:")return;url.hash="";for(let parameter of TRACKING_PARAMS)url.searchParams.has(parameter)&&url.searchParams.delete(parameter);url.pathname.length>1&&url.pathname.endsWith("/")&&(url.pathname=url.pathname.replace(/\/+$/,""));let normalized=url.toString();return normalized.length<=2048?normalized:void 0}catch{return}}function normalizeHit(hit,source){let url=normalizeUrl(hit.url);if(url)return{title:boundSingleLineText(hit.title,200)??url,url,snippet:boundSingleLineText(hit.snippet,200),date:boundSingleLineText(hit.date,100),sources:[...new Set([...hit.sources,source])]}}function isUrlFallbackTitle(title,url){let normalizedTitle=normalizeUrl(title);return normalizedTitle!==void 0&&normalizedTitle===normalizeUrl(url)}function reciprocalRankScore(candidate){let score=0;for(let rank of candidate.ranks.values())score+=1/(60+rank);return score}function bestRank(candidate){return Math.min(...candidate.ranks.values())}function fuseSearchHits(results){let candidates=new Map,relatedSearches=new Set,deepseekSynthesis;for(let result2 of results){let providerRelated=Array.isArray(result2.relatedSearches)?result2.relatedSearches:[],relatedScanLimit=Math.min(providerRelated.length,64);for(let index3=0;index3<relatedScanLimit&&relatedSearches.size<8;index3++){let normalized=boundSingleLineText(providerRelated[index3],200);normalized&&relatedSearches.add(normalized)}let synthesis=boundMultilineText(result2.synthesisText,6e3);synthesis&&(deepseekSynthesis=synthesis);let providerHits=Array.isArray(result2.hits)?result2.hits:[],hitScanLimit=Math.min(providerHits.length,200);for(let index3=0;index3<hitScanLimit;index3++){let rawHit=providerHits[index3];if(!rawHit)continue;let hit=normalizeHit(rawHit,result2.source);if(!hit)continue;let rank=index3+1,existing=candidates.get(hit.url);if(!existing){candidates.set(hit.url,{hit,ranks:new Map([[result2.source,rank]])});continue}let previousRank=existing.ranks.get(result2.source);(previousRank===void 0||rank<previousRank)&&existing.ranks.set(result2.source,rank);for(let source of hit.sources)existing.hit.sources.includes(source)||existing.hit.sources.push(source);isUrlFallbackTitle(existing.hit.title,existing.hit.url)&&!isUrlFallbackTitle(hit.title,hit.url)&&(existing.hit.title=hit.title),(!existing.hit.snippet||existing.hit.snippet.length<(hit.snippet?.length??0))&&hit.snippet&&(existing.hit.snippet=hit.snippet),!existing.hit.date&&hit.date&&(existing.hit.date=hit.date)}}return{hits:[...candidates.entries()].sort(([leftUrl,left],[rightUrl,right])=>{let scoreDifference=reciprocalRankScore(right)-reciprocalRankScore(left);if(scoreDifference!==0)return scoreDifference;let rankDifference=bestRank(left)-bestRank(right);return rankDifference!==0?rankDifference:leftUrl.localeCompare(rightUrl)}).map(([,candidate])=>candidate.hit).slice(0,12),relatedSearches:relatedSearches.size>0?[...relatedSearches]:void 0,deepseekSynthesis}}function escapeMarkdownText(text2){return text2.replace(/\\/g,"\\\\").replace(/\[/g,"\\[").replace(/\]/g,"\\]").replace(/</g,"\\<").replace(/>/g,"\\>")}function canonicalSources(value2){if(!Array.isArray(value2))return[];let sources=[],scanLimit=Math.min(value2.length,32);for(let index3=0;index3<scanLimit&&sources.length<2;index3++){let source=value2[index3];(source==="MiniMax"||source==="DeepSeek")&&!sources.includes(source)&&sources.push(source)}return sources}function formatHit(value2){if(!value2||typeof value2!="object")return;let hit=value2,url=normalizeUrl(hit.url);if(url)return{title:escapeMarkdownText(boundSingleLineText(hit.title,200)??url),url,snippet:boundSingleLineText(hit.snippet,200),sources:canonicalSources(hit.sources)}}function usableHits(details){let hits=Array.isArray(details.hits)?details.hits:[],formatted=[],scanLimit=Math.min(hits.length,240);for(let index3=0;index3<scanLimit&&formatted.length<12;index3++){let hit=formatHit(hits[index3]);hit&&formatted.push(hit)}return formatted}function formatResultsMarkdown(details){let parts=[],hits=usableHits(details);hits.length>0&&(parts.push(`## Web Sources (${hits.length} found via ${getEngineLabel(details.engine)})
|
|
1620
|
+
`)}var formatCommandList=formatTodoList;function formatIdRange(ids){return ids.length>1&&ids.every((id,index3)=>id===ids[0]+index3)?`#${ids[0]}\u2013#${ids[ids.length-1]}`:ids.map(id=>`#${id}`).join(", ")}function formatTodoContent(change,state2){let parts=[];if(change.created.length>0){let labels=change.created.map(id=>{let item=state2.items.find(entry=>entry.id===id);if(!item)return`#${id}`;let suffix=item.status==="pending"?"":` (${item.status})`;return`#${id}: ${item.subject}${suffix}`}),noun=change.created.length===1?"task":"tasks";parts.push(`Created ${change.created.length} ${noun}: ${labels.join("; ")}`)}for(let entry of change.updated){let item=state2.items.find(candidate=>candidate.id===entry.id),subject=item?`: ${item.subject}`:"",transition=entry.from===entry.to?"":` (${entry.from} -> ${entry.to})`;parts.push(`Updated #${entry.id}${transition}${subject}`)}if(change.demotedId!==void 0&&parts.push(`demoted #${change.demotedId} to pending`),change.deleted.length>0){let noun=change.deleted.length===1?"task":"tasks",labels=change.deleted.map(entry=>`#${entry.id}: ${entry.subject}`);parts.push(`Deleted ${change.deleted.length} ${noun}: ${labels.join("; ")}`)}for(let id of change.absent)parts.push(`#${id} already absent`);if(change.evicted.length>0){let ids=change.evicted.map(entry=>entry.id);parts.push(`auto-removed completed ${formatIdRange(ids)} to stay within ${20}`)}return parts.length===0?formatTodoList(state2):parts.join("; ")}var CALL_ITEMS_MAX=20,CALL_SUBJECT_PREVIEW_COUNT=2,CALL_SUBJECT_PREVIEW_WIDTH=72,CALL_DESCRIPTION_PREVIEW_LENGTH=120,SUMMARY_FAILURE_MAX_LENGTH=120;function safeRecord2(value2){try{return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)?value2:void 0}catch{return}}function safeValue2(record,key){try{return record?.[key]}catch{return}}function safeString(value2){return typeof value2=="string"?value2:void 0}function clipText(value2,max){return safeString(value2)?.trim().replace(/\s+/g," ").slice(0,max)??""}var safeSubject=value2=>clipText(value2,160),safeDescription=value2=>clipText(value2,500);function safeId(value2){return typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>=1?value2:void 0}function safeStatus(value2){let status=safeString(value2);if(status==="pending"||status==="in_progress"||status==="completed")return status}function readArray(value2,limit=CALL_ITEMS_MAX){try{if(!Array.isArray(value2))return;let length=value2.length,values=[];for(let index3=0;index3<Math.min(length,limit);index3++)try{values.push(value2[index3])}catch{values.push(void 0)}return{values,length}}catch{return}}function readIds(value2){let array=readArray(value2);if(!array)return;let ids=[];for(let entry of array.values){let id=safeId(entry);id!==void 0&&ids.push(id)}return ids}function batchCreateItems(value2){let result2=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw);if(!item)continue;let entry={subject:safeSubject(safeValue2(item,"subject")),description:safeDescription(safeValue2(item,"description"))},status=safeStatus(safeValue2(item,"status"));status&&(entry.status=status),result2.push(entry)}return result2}function batchUpdateItems(value2){let result2=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw);if(!item)continue;let entry={subject:safeSubject(safeValue2(item,"subject")),description:safeDescription(safeValue2(item,"description"))},id=safeId(safeValue2(item,"id"));id!==void 0&&(entry.id=id);let status=safeStatus(safeValue2(item,"status"));status&&(entry.status=status),result2.push(entry)}return result2}function descriptionPreview(value2){let text2=value2.replace(/\s+/g," ");return text2.length>CALL_DESCRIPTION_PREVIEW_LENGTH?`${text2.slice(0,CALL_DESCRIPTION_PREVIEW_LENGTH-1)}\u2026`:text2}function formatSubjectPreview(subjects,total){let shown=subjects.filter(Boolean).slice(0,CALL_SUBJECT_PREVIEW_COUNT).map(subject=>truncateToWidth(subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"));if(!shown.length)return"";let hidden=Math.max(0,total-shown.length);return`${shown.join(", ")}${hidden?`, +${hidden} more`:""}`}function todoDetails(value2){let details=safeRecord2(value2);if(!details||safeValue2(details,"schemaVersion")!==TODO_DETAILS_SCHEMA_VERSION)return;let change=safeRecord2(safeValue2(details,"change")),state2=safeRecord2(safeValue2(details,"state"));if(!(!change||!state2))return{change,state:state2}}function createResultIds(result2,count){let details=todoDetails(result2?.details);if(!details)return;let ids=readIds(safeValue2(details.change,"created"));return ids&&ids.length===count&&count>0?ids:void 0}function deleteResultRemoved(result2){let details=todoDetails(result2?.details);return details?idSubjectEntries(safeValue2(details.change,"deleted")):[]}function deleteResultAbsent(result2){let details=todoDetails(result2?.details);return details?readIds(safeValue2(details.change,"absent"))??[]:[]}function formatCallParts(args,theme2,result2){let details=[],segments=[],pushSegment=(verb,body)=>{let title=segments.length===0?`todo ${verb}`:verb;segments.push(body?`${theme2.fg("toolTitle",theme2.bold(title))} ${body}`:theme2.fg("toolTitle",theme2.bold(title)))},hasCreate=args?.create!==void 0,hasUpdate=args?.update!==void 0,hasDelete=args?.delete!==void 0;if(hasCreate){let items=batchCreateItems(args?.create),rawCount=readArray(args?.create)?.length;if(rawCount!==0){let body=[];if(rawCount!==void 0){let count=Math.min(rawCount,CALL_ITEMS_MAX);body.push(theme2.fg("dim",`${count} ${count===1?"task":"tasks"}`));let preview=formatSubjectPreview(items.map(item=>item.subject),count);preview&&body.push(theme2.fg("dim","\xB7"),theme2.fg("text",preview))}pushSegment("create",body.join(" "))}let ids=createResultIds(result2,items.length);for(let[index3,item]of items.entries()){let marker=ids?theme2.fg("accent",`#${ids[index3]}`):theme2.fg("accent",`${index3+1}.`),status=item.status&&item.status!=="pending"?` ${theme2.fg(STATUS_COLOR[item.status],`(${item.status})`)}`:"";details.push(item.subject?`${marker} ${theme2.fg("text",item.subject)}${status}`:marker),item.description&&details.push(` ${theme2.fg("dim",descriptionPreview(item.description))}`)}}if(hasUpdate){let items=batchUpdateItems(args?.update);if(readArray(args?.update)?.length!==0){let entries=[];for(let item of items){let parts=[];item.id!==void 0&&parts.push(theme2.fg("accent",`#${item.id}`)),item.status&&parts.push(theme2.fg(STATUS_COLOR[item.status],item.status)),item.subject&&parts.push(theme2.fg("text",truncateToWidth(item.subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"))),parts.length>0&&entries.push(parts.join(" "))}pushSegment("update",entries.join(theme2.fg("dim",", ")))}for(let item of items)item.description&&details.push(` ${theme2.fg("dim",descriptionPreview(item.description))}`)}if(hasDelete){if(readArray(args?.delete)?.length!==0){let ids=readIds(args?.delete)??[];pushSegment("delete",ids.length>0?theme2.fg("accent",ids.map(id=>`#${id}`).join(", ")):"")}for(let entry of deleteResultRemoved(result2))details.push(`${theme2.fg("accent",`#${entry.id}`)} ${theme2.fg("text",entry.subject)}`);for(let id of deleteResultAbsent(result2))details.push(theme2.fg("dim",`#${id} already absent`))}return segments.length===0&&segments.push(theme2.fg("toolTitle",theme2.bold("todo list"))),{headline:segments.join(theme2.fg("dim"," ; ")),details}}function formatTodoCall(args,theme2,expanded,result2){let{headline,details}=formatCallParts(args,theme2,result2);return!expanded||details.length===0?headline:[headline,...details].join(`
|
|
1621
|
+
`)}function stateIndex(state2){let array=readArray(safeValue2(state2,"items"),20);if(!array||array.length>20)return;let byId=new Map,counts={inProgress:0,pending:0,completed:0};for(let raw of array.values){let item=safeRecord2(raw);if(!item)continue;let id=safeId(safeValue2(item,"id"));id!==void 0&&!byId.has(id)&&byId.set(id,item);let status=safeStatus(safeValue2(item,"status"));status==="in_progress"?counts.inProgress++:status==="pending"?counts.pending++:status==="completed"&&counts.completed++}return{byId,counts}}function stateSubject(map,id){let item=map.get(id);return item?safeSubject(safeValue2(item,"subject")):""}function idSubjectEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id")),subject=safeSubject(safeValue2(item,"subject"));id===void 0||!subject||entries.push({id,subject})}return entries}function updatedEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id"));if(id===void 0)continue;let entry={id},from=safeStatus(safeValue2(item,"from"));from&&(entry.from=from);let to=safeStatus(safeValue2(item,"to"));to&&(entry.to=to),entries.push(entry)}return entries}function formatTodoSuccessSummary(args,theme2,result2){let parsed=todoDetails(result2.details);if(!parsed)return;let{change,state:state2}=parsed,index3=stateIndex(state2),segments=[],pushVerb=(word,body)=>{let title=segments.length===0?`todo ${word}`:word;segments.push(body?`${theme2.fg("toolTitle",title)} ${body}`:theme2.fg("toolTitle",title))},withPreview=(word,ids,subjects)=>{let text2=formatSubjectPreview(subjects,subjects.length),base=theme2.fg("accent",formatIdRange(ids));pushVerb(word,text2?`${base}${theme2.fg("dim"," \xB7 ")}${theme2.fg("text",text2)}`:base)},created=readIds(safeValue2(change,"created"))??[];created.length>0&&index3&&withPreview("created",created,created.map(id=>stateSubject(index3.byId,id)));for(let entry of updatedEntries(safeValue2(change,"updated"))){let parts=[theme2.fg("accent",`#${entry.id}`)];entry.to&&parts.push(theme2.fg(STATUS_COLOR[entry.to],entry.to));let subject=index3?stateSubject(index3.byId,entry.id):"";subject&&parts.push(theme2.fg("text",truncateToWidth(subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"))),pushVerb("updated",parts.join(" "))}let demotedId=safeId(safeValue2(change,"demotedId"));demotedId!==void 0&&segments.push(theme2.fg("dim",`demoted #${demotedId}`));let deleted=idSubjectEntries(safeValue2(change,"deleted"));deleted.length>0&&withPreview("deleted",deleted.map(entry=>entry.id),deleted.map(entry=>entry.subject));for(let id of readIds(safeValue2(change,"absent"))??[])segments.push(theme2.fg("dim",`#${id} already absent`));let evicted=idSubjectEntries(safeValue2(change,"evicted"));if(evicted.length>0&&segments.push(theme2.fg("dim",`auto-removed ${evicted.map(entry=>`#${entry.id}`).join(", ")}`)),segments.length===0){if(!index3)return;let parts=[];return index3.counts.inProgress>0&&parts.push(`${index3.counts.inProgress} in progress`),index3.counts.pending>0&&parts.push(`${index3.counts.pending} pending`),index3.counts.completed>0&&parts.push(`${index3.counts.completed} completed`),`${theme2.fg("toolTitle","todo list")}: ${theme2.fg("dim",parts.length?parts.join(", "):"no tasks")}`}return segments.join(theme2.fg("dim"," ; "))}function formatTodoSummary(args,theme2,context){if(context.isError){let reason="tool failed";try{for(let block of context.result?.content.slice(0,8)??[]){if(block.type!=="text"||typeof block.text!="string")continue;let text2=block.text.replace(/[\u0000-\u001f\u007f-\u009f]/g," ").replace(/\s+/g," ").trim();if(text2){reason=text2.length>SUMMARY_FAILURE_MAX_LENGTH?`${text2.slice(0,SUMMARY_FAILURE_MAX_LENGTH-1)}\u2026`:text2;break}}}catch{}return`${formatTodoCall(args,theme2,!1)} ${theme2.fg("error",`failed: ${reason}`)}`}if(!context.isPartial&&context.result){let summary=formatTodoSuccessSummary(args,theme2,context.result);if(summary)return summary}return formatTodoCall(args,theme2,!1)}var WIDGET_KEY="todos",TodoWidget=class{constructor(getState2){this.registered=!1,this.getState=getState2}setUI(ui){this.ui!==ui&&(this.dispose(),this.ui=ui)}update(){if(this.ui){if(!hasOpenTodos(this.getState())){this.unregister();return}if(this.registered){this.tui?.requestRender();return}this.ui.setWidget(WIDGET_KEY,(tui,theme2)=>(this.tui=tui,{render:width=>renderWidgetLine(this.getState(),theme2,width),invalidate:()=>{}}),{placement:"aboveEditor"}),this.registered=!0}}unregister(){this.registered&&(this.ui?.setWidget(WIDGET_KEY,void 0),this.registered=!1,this.tui=void 0)}dispose(){this.unregister(),this.ui=void 0}};function safeReplay(ctx,store){try{store.replaceState(replayTodosFromBranch(ctx))}catch(error){if(!isStaleExtensionContextError(error))throw error}}function todo(pi){let store=createTodoStore(),widget;pi.registerTool({name:TODO_TOOL_NAME,label:TODO_TOOL_LABEL,description:TODO_TOOL_DESCRIPTION,promptSnippet:TODO_PROMPT_SNIPPET,promptGuidelines:TODO_PROMPT_GUIDELINES,parameters:TodoParamsSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},executionMode:"sequential",async execute(_toolCallId,params,_signal,_onUpdate){let details=store.execute(params);return{content:[{type:"text",text:formatTodoContent(details.change,details.state)}],details}},renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(context.expanded?formatTodoCall(args,theme2,!0,context.result):formatTodoSummary(args,theme2,context)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0),output=result2.content.flatMap(block=>block.type==="text"?[block.text]:[]).join(`
|
|
1622
|
+
`);return text2.setText(options.expanded?theme2.fg("toolOutput",output):""),text2}}),pi.registerCommand(TODOS_COMMAND_NAME,{description:"Show the complete todo list for the current conversation branch",handler:async(_args,ctx)=>{if(!ctx.hasUI){ctx.ui.notify("/todos requires an interactive UI.","warning");return}ctx.ui.notify(formatCommandList(store.getState()),"info")}}),pi.on("session_start",async(_event,ctx)=>{safeReplay(ctx,store),ctx.hasUI&&(widget??=new TodoWidget(()=>store.getState()),widget.setUI(ctx.ui),widget.update())}),pi.on("session_tree",async(_event,ctx)=>{safeReplay(ctx,store),widget?.update()}),pi.on("session_shutdown",async(_event,_ctx)=>{widget?.dispose(),widget=void 0}),pi.on("tool_execution_end",async event=>{event.toolName!==TODO_TOOL_NAME||event.isError||widget?.update()})}var MINIMAX_CN_HOST="https://api.minimaxi.com",MINIMAX_GLOBAL_HOST="https://api.minimax.io";function trimValue(value2){return value2?.trim()||void 0}async function runtimeApiKey(modelRuntime,providerId){if(modelRuntime)try{return trimValue((await modelRuntime.getAuth(providerId))?.auth.apiKey)}catch{return}}function storedApiKey(providerId,authPath){let credential=readStoredCredential(providerId,authPath);if(!credential||credential.type!=="api_key"||typeof credential.key!="string")return;let key=isCommandConfigValue(credential.key)?resolveConfigValue(credential.key,credential.env):credential.key;return trimValue(key)}async function resolveProviderKey(modelRuntime,authPath,providerId,envVar){return await runtimeApiKey(modelRuntime,providerId)??storedApiKey(providerId,authPath)??trimValue(process.env[envVar])}async function resolveMiniMaxCredential(modelRuntime,authPath){let cnKey=await resolveProviderKey(modelRuntime,authPath,"minimax-cn","MINIMAX_CN_API_KEY");if(cnKey)return{key:cnKey,host:MINIMAX_CN_HOST};let globalKey=await resolveProviderKey(modelRuntime,authPath,"minimax","MINIMAX_API_KEY");if(globalKey)return{key:globalKey,host:trimValue(process.env.MINIMAX_API_HOST)??MINIMAX_GLOBAL_HOST}}async function resolveDeepSeekCredential(modelRuntime,authPath){let key=await resolveProviderKey(modelRuntime,authPath,"deepseek","DEEPSEEK_API_KEY");return key?{key}:void 0}function configuredEngine(credentials){return credentials.minimax&&credentials.deepseek?"dual":credentials.minimax?"minimax":credentials.deepseek?"deepseek":"none"}async function resolveSearchCredentials(modelRuntime,authPath=getAuthPath()){let[minimax,deepseek]=await Promise.all([resolveMiniMaxCredential(modelRuntime,authPath),resolveDeepSeekCredential(modelRuntime,authPath)]);return{minimax,deepseek}}var WEB_SEARCH_TOOL_NAME="web_search",WEB_SEARCH_LABEL="Web Search",WEB_SEARCH_DESCRIPTION="Search the live web through configured MiniMax and DeepSeek providers. When both are available, searches run concurrently and results are deduplicated and fused. Returns up to 12 source URLs with bounded titles and snippets, plus related searches and optional synthesis; partial provider failures still return successful results.",WEB_SEARCH_PROMPT_SNIPPET="Search the live web for current information",WEB_SEARCH_DISABLED_MESSAGE="Web search is disabled: Neither MiniMax nor DeepSeek API Key was found in auth.json or environment variables. Please add credentials via auth.json or environment variables (MINIMAX_API_KEY, DEEPSEEK_API_KEY).";function getEngineLabel(engine){return engine==="dual"?"MiniMax & DeepSeek":engine==="minimax"?"MiniMax":engine==="deepseek"?"DeepSeek":""}function getWebSearchPromptGuidelines(){return["Use `web_search` for current information, recent releases, live documentation, and other freshness-sensitive facts beyond your training cutoff.",`When using \`web_search\` for freshness-sensitive topics, account for the current date (${new Date().toISOString().slice(0,7)}) and include the year in the query when useful.`]}var TRACKING_PARAMS=new Set(["utm_source","utm_medium","utm_campaign","utm_term","utm_content","ref","fbclid","gclid","trk","gi"]);function truncateText2(text2,maxLength){return text2.length<=maxLength?text2:maxLength<=3?text2.slice(0,maxLength):`${text2.slice(0,maxLength-3).trimEnd()}...`}function boundSingleLineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.replace(/\s+/g," ").trim();return normalized?truncateText2(normalized,maxLength):void 0}function boundMultilineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.trim();return normalized?truncateText2(normalized,maxLength):void 0}function normalizeUrl(rawUrl){if(typeof rawUrl!="string")return;let trimmed=rawUrl.trim();if(!(!trimmed||trimmed.length>2048))try{let url=new URL(trimmed);if(url.protocol!=="http:"&&url.protocol!=="https:")return;url.hash="";for(let parameter of TRACKING_PARAMS)url.searchParams.has(parameter)&&url.searchParams.delete(parameter);url.pathname.length>1&&url.pathname.endsWith("/")&&(url.pathname=url.pathname.replace(/\/+$/,""));let normalized=url.toString();return normalized.length<=2048?normalized:void 0}catch{return}}function normalizeHit(hit,source){let url=normalizeUrl(hit.url);if(url)return{title:boundSingleLineText(hit.title,200)??url,url,snippet:boundSingleLineText(hit.snippet,200),date:boundSingleLineText(hit.date,100),sources:[...new Set([...hit.sources,source])]}}function isUrlFallbackTitle(title,url){let normalizedTitle=normalizeUrl(title);return normalizedTitle!==void 0&&normalizedTitle===normalizeUrl(url)}function reciprocalRankScore(candidate){let score=0;for(let rank of candidate.ranks.values())score+=1/(60+rank);return score}function bestRank(candidate){return Math.min(...candidate.ranks.values())}function fuseSearchHits(results){let candidates=new Map,relatedSearches=new Set,deepseekSynthesis;for(let result2 of results){let providerRelated=Array.isArray(result2.relatedSearches)?result2.relatedSearches:[],relatedScanLimit=Math.min(providerRelated.length,64);for(let index3=0;index3<relatedScanLimit&&relatedSearches.size<8;index3++){let normalized=boundSingleLineText(providerRelated[index3],200);normalized&&relatedSearches.add(normalized)}let synthesis=boundMultilineText(result2.synthesisText,6e3);synthesis&&(deepseekSynthesis=synthesis);let providerHits=Array.isArray(result2.hits)?result2.hits:[],hitScanLimit=Math.min(providerHits.length,200);for(let index3=0;index3<hitScanLimit;index3++){let rawHit=providerHits[index3];if(!rawHit)continue;let hit=normalizeHit(rawHit,result2.source);if(!hit)continue;let rank=index3+1,existing=candidates.get(hit.url);if(!existing){candidates.set(hit.url,{hit,ranks:new Map([[result2.source,rank]])});continue}let previousRank=existing.ranks.get(result2.source);(previousRank===void 0||rank<previousRank)&&existing.ranks.set(result2.source,rank);for(let source of hit.sources)existing.hit.sources.includes(source)||existing.hit.sources.push(source);isUrlFallbackTitle(existing.hit.title,existing.hit.url)&&!isUrlFallbackTitle(hit.title,hit.url)&&(existing.hit.title=hit.title),(!existing.hit.snippet||existing.hit.snippet.length<(hit.snippet?.length??0))&&hit.snippet&&(existing.hit.snippet=hit.snippet),!existing.hit.date&&hit.date&&(existing.hit.date=hit.date)}}return{hits:[...candidates.entries()].sort(([leftUrl,left],[rightUrl,right])=>{let scoreDifference=reciprocalRankScore(right)-reciprocalRankScore(left);if(scoreDifference!==0)return scoreDifference;let rankDifference=bestRank(left)-bestRank(right);return rankDifference!==0?rankDifference:leftUrl.localeCompare(rightUrl)}).map(([,candidate])=>candidate.hit).slice(0,12),relatedSearches:relatedSearches.size>0?[...relatedSearches]:void 0,deepseekSynthesis}}function escapeMarkdownText(text2){return text2.replace(/\\/g,"\\\\").replace(/\[/g,"\\[").replace(/\]/g,"\\]").replace(/</g,"\\<").replace(/>/g,"\\>")}function canonicalSources(value2){if(!Array.isArray(value2))return[];let sources=[],scanLimit=Math.min(value2.length,32);for(let index3=0;index3<scanLimit&&sources.length<2;index3++){let source=value2[index3];(source==="MiniMax"||source==="DeepSeek")&&!sources.includes(source)&&sources.push(source)}return sources}function formatHit(value2){if(!value2||typeof value2!="object")return;let hit=value2,url=normalizeUrl(hit.url);if(url)return{title:escapeMarkdownText(boundSingleLineText(hit.title,200)??url),url,snippet:boundSingleLineText(hit.snippet,200),sources:canonicalSources(hit.sources)}}function usableHits(details){let hits=Array.isArray(details.hits)?details.hits:[],formatted=[],scanLimit=Math.min(hits.length,240);for(let index3=0;index3<scanLimit&&formatted.length<12;index3++){let hit=formatHit(hits[index3]);hit&&formatted.push(hit)}return formatted}function formatResultsMarkdown(details){let parts=[],hits=usableHits(details);hits.length>0&&(parts.push(`## Web Sources (${hits.length} found via ${getEngineLabel(details.engine)})
|
|
1622
1623
|
`),hits.forEach((hit,index3)=>{let sourceTag=hit.sources.length>1?` \u2014 *(found by ${hit.sources.join(" & ")})*`:"";parts.push(`${index3+1}. **[${hit.title}](<${hit.url}>)**${sourceTag}`),hit.snippet&&parts.push(` - ${escapeMarkdownText(hit.snippet)}`)}),parts.push(""));let synthesis=boundMultilineText(details.deepseekSynthesis,6e3);synthesis&&(parts.push(`## DeepSeek Search Synthesis
|
|
1623
1624
|
`),parts.push(escapeMarkdownText(synthesis)),parts.push(""));let relatedSearches=[],historicalRelated=Array.isArray(details.relatedSearches)?details.relatedSearches:[],relatedScanLimit=Math.min(historicalRelated.length,64);for(let index3=0;index3<relatedScanLimit&&relatedSearches.length<8;index3++){let related=boundSingleLineText(historicalRelated[index3],200);related&&relatedSearches.push(related)}return relatedSearches.length>0&&(parts.push(`## Related Searches
|
|
1624
1625
|
`),parts.push(relatedSearches.map(related=>`- ${escapeMarkdownText(related)}`).join(`
|
|
@@ -1719,4 +1720,4 @@ Options:
|
|
|
1719
1720
|
`))});try{switch(options.command){case"install":return await packageManager.installAndPersist(source,{local:options.local}),console.log(source_default.green(`Installed ${source}`)),!0;case"remove":return await packageManager.removeAndPersist(source,{local:options.local})?(console.log(source_default.green(`Removed ${source}`)),!0):(console.error(source_default.red(`No matching package found for ${source}`)),process.exitCode=1,!0);case"list":{let configuredPackages=packageManager.listConfiguredPackages(),userPackages=configuredPackages.filter(pkg2=>pkg2.scope==="user"),projectPackages=configuredPackages.filter(pkg2=>pkg2.scope==="project");if(configuredPackages.length===0)return console.log(source_default.dim("No packages installed.")),!0;let formatPackage=pkg2=>{let display=pkg2.filtered?`${pkg2.source} (filtered)`:pkg2.source;console.log(` ${display}`),pkg2.installedPath&&console.log(source_default.dim(` ${pkg2.installedPath}`))};if(userPackages.length>0){console.log(source_default.bold("User packages:"));for(let pkg2 of userPackages)formatPackage(pkg2)}if(projectPackages.length>0){userPackages.length>0&&console.log(),console.log(source_default.bold("Project packages:"));for(let pkg2 of projectPackages)formatPackage(pkg2)}return!0}case"update":{let target=options.updateTarget??{type:"self"};if(options.showExtensionsSkippedNote&&console.log(source_default.dim(`Extensions are skipped. Run ${APP_NAME} update --extensions to update extensions.`)),updateTargetIncludesExtensions(target)){let updateSource=target.type==="extensions"?target.source:void 0;await packageManager.update(updateSource),console.log(updateSource?source_default.green(`Updated ${updateSource}`):source_default.green("Updated packages"))}if(updateTargetIncludesSelf(target)){let managedInstallRoot=getActiveManagedInstallRoot();if(managedInstallRoot&&options.force)return console.error(source_default.red(`Managed ${APP_NAME} installations do not support --force; rerun the installer to repair this installation.`)),process.exitCode=1,!0;let selfUpdatePlan=await getSelfUpdatePlan(options.force);if(!selfUpdatePlan.shouldRun)return!0;if(managedInstallRoot){selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{console.log(source_default.dim(`Updating managed ${APP_NAME} installation...`)),await runManagedSelfUpdate(managedInstallRoot,selfUpdatePlan.version)}catch(error){let message=error instanceof Error?error.message:"Unknown managed update error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}return console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`)),!0}let installMethod=detectInstallMethod();if(process.platform==="win32"&&installMethod!=="npm"&&installMethod!=="pnpm")return console.error(source_default.red(`${APP_NAME} self-update on Windows is only supported for npm and pnpm installs.`)),console.error(source_default.dim(`Detected install method: ${installMethod}. Update ${APP_NAME} manually.`)),process.exitCode=1,!0;let selfUpdateTarget={packageName:selfUpdatePlan.packageName,installSpec:selfUpdatePlan.installSpec},selfUpdateCommand=getSelfUpdateCommand(PACKAGE_NAME,selfUpdateNpmCommand,selfUpdateTarget);if(!selfUpdateCommand)return printSelfUpdateUnavailable(selfUpdateNpmCommand,selfUpdateTarget),process.exitCode=1,!0;selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{installMethod==="npm"&&prepareWindowsNpmSelfUpdate(),await runSelfUpdate(selfUpdateCommand)}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),installMethod==="pnpm"&&printPnpmSelfUpdateMetadataHint(),printSelfUpdateFallback(selfUpdateCommand),process.exitCode=1,!0}console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`))}return!0}}}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}}var EXTENSION_LOAD_FAILURE_HINT=`Hint: Start without extensions using "${APP_NAME} -ne".`;async function readPipedStdin(){if(!process.stdin.isTTY)return new Promise(resolve17=>{let data="";process.stdin.setEncoding("utf8"),process.stdin.on("data",chunk=>{data+=chunk}),process.stdin.on("end",()=>{resolve17(data.trim()||void 0)}),process.stdin.resume()})}function reportDiagnostics(diagnostics){for(let diagnostic of diagnostics){let color2=diagnostic.type==="error"?source_default.red:diagnostic.type==="warning"?source_default.yellow:source_default.dim,prefix=diagnostic.type==="error"?"Error: ":diagnostic.type==="warning"?"Warning: ":"";console.error(color2(`${prefix}${diagnostic.message}`))}}function isTruthyEnvFlag2(value2){return value2?value2==="1"||value2.toLowerCase()==="true"||value2.toLowerCase()==="yes":!1}function resolveAppMode(parsed,stdinIsTTY,stdoutIsTTY){return parsed.mode==="rpc"?"rpc":parsed.mode==="json"?"json":parsed.print||!stdinIsTTY||!stdoutIsTTY?"print":"interactive"}function toPrintOutputMode(appMode){return appMode==="json"?"json":"text"}function isPlainRuntimeMetadataCommand(parsed){return!parsed.print&&parsed.mode===void 0&&(parsed.help===!0||parsed.listModels!==void 0)}async function runAuthCommand(args){if(isAuthCommandHelp(args))return printAuthCommandHelp(),!0;let command;try{command=parseAuthCommand(args)}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to parse auth command";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}if(!command)return!1;let parsed=parseArgs(command.args);if(parsed.unknownFlags.size>0){let option=parsed.unknownFlags.keys().next().value;return console.error(source_default.red(`Unknown option --${option} for "${getAuthCommandName(command.kind)}".`)),console.error(source_default.dim(`Use "${APP_NAME} --help" or "${getAuthCommandUsage(command.kind)}".`)),process.exitCode=1,!0}try{if(parsed.diagnostics.length>0)throw new AuthCommandError(parsed.diagnostics.map(diagnostic=>diagnostic.message).join(`
|
|
1720
1721
|
`));if(command.kind!=="check"){let signal=AbortSignal.timeout(15e3),modelRuntime=await ModelRuntime.create({allowModelNetwork:!1,signal}),credential2=await resolveCredentialForPrint(parsed,modelRuntime,command.kind,command.minExpiryMs,signal);return process.stdout.write(`${credential2}
|
|
1721
1722
|
`),!0}let requestedAuth=validateAuthCommandArgs(parsed,command.kind),result2,credential;try{let credentials=command.noRefresh?new ReadOnlyAuthStorage:AuthStorage.create(),modelRuntime=await createAuthCheckModelRuntime(credentials);result2=await checkProviderAuth(parsed,modelRuntime,{refresh:!command.noRefresh}),command.credentials&&result2.status==="ready"&&(credential=await getProviderCredential(result2.provider,modelRuntime,credentials,{refresh:!command.noRefresh}),credential||(result2={status:"not_ready",provider:result2.provider,reason:"credential_not_available"}))}catch{result2={status:"invalid",provider:requestedAuth.provider??requestedAuth.model,reason:"invalid_state"}}let output=command.json?JSON.stringify({...result2,...credential?{credentials:credential}:{}}):credential??result2.status;process.stdout.write(`${output}
|
|
1722
|
-
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve17=>{let rl=createInterface4({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve17(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value2=>isLocalPath(value2)?resolvePath(value2,cwd):value2)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings();let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),setThemeJsonValidator(validateThemeJson),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve17=>setTimeout(resolve17,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve17=>process.stdout.once("drain",resolve17)),process.stderr.writableLength>0&&await new Promise(resolve17=>process.stderr.once("drain",resolve17));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,DefaultPackageManager,SettingsManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,BackgroundService,parseFrontmatter,stripFrontmatter,createSyntheticSourceInfo,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,dist_exports2,serializeConversation2 as serializeConversation,DEFAULT_COMPACTION_SETTINGS2 as DEFAULT_COMPACTION_SETTINGS,calculateContextTokens2 as calculateContextTokens,getLastAssistantUsage2 as getLastAssistantUsage,shouldCompact2 as shouldCompact,estimateTokens3 as estimateTokens,findTurnStartIndex2 as findTurnStartIndex,findCutPoint2 as findCutPoint,generateSummary2 as generateSummary,generateSummaryWithUsage2 as generateSummaryWithUsage,compact2 as compact,collectEntriesForBranchSummary2 as collectEntriesForBranchSummary,prepareBranchEntries2 as prepareBranchEntries,generateBranchSummary2 as generateBranchSummary,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,truncateToVisualLines,createLocalBashOperations,createBashToolDefinition,createBashTool2 as createBashTool,generateUnifiedPatch2 as generateUnifiedPatch,generateDiffString2 as generateDiffString,withFileMutationQueue2 as withFileMutationQueue,renderDiff,createEditToolDefinition,createEditTool2 as createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool2 as createReadTool,createWriteToolDefinition,createWriteTool2 as createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,copyToClipboard,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|
|
1723
|
+
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve17=>{let rl=createInterface4({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve17(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value2=>isLocalPath(value2)?resolvePath(value2,cwd):value2)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings();let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),setThemeJsonValidator(validateThemeJson),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve17=>setTimeout(resolve17,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve17=>process.stdout.once("drain",resolve17)),process.stderr.writableLength>0&&await new Promise(resolve17=>process.stderr.once("drain",resolve17));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,DefaultPackageManager,SettingsManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,BackgroundService,parseFrontmatter,stripFrontmatter,createSyntheticSourceInfo,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,dist_exports2,serializeConversation2 as serializeConversation,DEFAULT_COMPACTION_SETTINGS2 as DEFAULT_COMPACTION_SETTINGS,calculateContextTokens2 as calculateContextTokens,getLastAssistantUsage2 as getLastAssistantUsage,shouldCompact2 as shouldCompact,estimateTokens3 as estimateTokens,findTurnStartIndex2 as findTurnStartIndex,findCutPoint2 as findCutPoint,generateSummary2 as generateSummary,generateSummaryWithUsage2 as generateSummaryWithUsage,compact2 as compact,collectEntriesForBranchSummary2 as collectEntriesForBranchSummary,prepareBranchEntries2 as prepareBranchEntries,generateBranchSummary2 as generateBranchSummary,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,truncateToVisualLines,createLocalBashOperations,createBashToolDefinition,createBashTool2 as createBashTool,generateUnifiedPatch2 as generateUnifiedPatch,generateDiffString2 as generateDiffString,withFileMutationQueue2 as withFileMutationQueue,renderDiff,createEditToolDefinition,createEditTool2 as createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool2 as createReadTool,createWriteToolDefinition,createWriteTool2 as createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,copyToClipboard,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,ToolExecutionComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|