@korallis/k-pi 0.2.0 → 0.2.1

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.
@@ -593,7 +593,7 @@ Please report this to https://github.com/markedjs/marked.`,e){let s="<p>An error
593
593
  `)}collectKittyImageIds(lines){let ids=new Set;for(let line of lines)for(let id of extractKittyImageIds(line))ids.add(id);return ids}deleteKittyImages(ids){let buffer="";for(let id of ids)buffer+=deleteKittyImage(id);return buffer}getKittyImageReservedRows(lines,index3,maxIndex=lines.length-1){let rows=extractKittyImageRows(lines[index3]??"");if(rows<=1)return 1;let maxRows=Math.min(rows,maxIndex-index3+1,lines.length-index3),reservedRows=1;for(;reservedRows<maxRows;){let line=lines[index3+reservedRows]??"";if(isImageLine(line)||visibleWidth(line)>0)break;reservedRows++}return reservedRows}expandChangedRangeForKittyImages(firstChanged,lastChanged,newLines){let expandedFirstChanged=firstChanged,expandedLastChanged=lastChanged,expandForLines=lines=>{for(let i=0;i<lines.length;i++){if(extractKittyImageIds(lines[i]).length===0)continue;let blockEnd=i+this.getKittyImageReservedRows(lines,i)-1;(i>=firstChanged||i<=lastChanged&&blockEnd>=firstChanged)&&(expandedFirstChanged=Math.min(expandedFirstChanged,i),expandedLastChanged=Math.max(expandedLastChanged,blockEnd))}};return expandForLines(this.previousLines),expandForLines(newLines),{firstChanged:expandedFirstChanged,lastChanged:expandedLastChanged}}deleteChangedKittyImages(firstChanged,lastChanged){if(firstChanged<0||lastChanged<firstChanged)return"";let ids=new Set,maxLine=Math.min(lastChanged,this.previousLines.length-1);for(let i=firstChanged;i<=maxLine;i++)for(let id of extractKittyImageIds(this.previousLines[i]??""))ids.add(id);return this.deleteKittyImages(ids)}doRender(){if(this.stopped)return;let width=this.terminal.columns,height=this.terminal.rows,widthChanged=this.previousWidth!==0&&this.previousWidth!==width,heightChanged=this.previousHeight!==0&&this.previousHeight!==height,previousBufferLength=this.previousHeight>0?this.previousViewportTop+this.previousHeight:height,prevViewportTop=heightChanged?Math.max(0,previousBufferLength-height):this.previousViewportTop,viewportTop=prevViewportTop,hardwareCursorRow=this.hardwareCursorRow,computeLineDiff=targetRow=>{let currentScreenRow=hardwareCursorRow-prevViewportTop;return targetRow-viewportTop-currentScreenRow},newLines=this.render(width);this.hasOverlayEntries&&(newLines=this.compositeOverlays(newLines,width,height));let cursorPos=this.extractCursorPosition(newLines,height);newLines=this.applyLineResets(newLines);let fullRender=clear=>{this.fullRedrawCount+=1;let output2=new BoundedTerminalWriter(data=>this.terminal.write(data));output2.append("\x1B[?2026h"),clear&&(output2.append(this.deleteKittyImages(this.previousKittyImageIds)),output2.append("\x1B[2J\x1B[H\x1B[3J"));for(let i=0;i<newLines.length;i++){i>0&&output2.append(`\r
594
594
  `);let line=newLines[i],imageReservedRows=isImageLine(line)?this.getKittyImageReservedRows(newLines,i):1;if(imageReservedRows>1&&imageReservedRows<=height){for(let row=1;row<imageReservedRows;row++)output2.append(`\r
595
595
  `);output2.append(`\x1B[${imageReservedRows-1}A`),output2.append(line),output2.append(`\x1B[${imageReservedRows-1}B`),i+=imageReservedRows-1;continue}output2.append(line)}output2.append("\x1B[?2026l"),output2.flush(),this.cursorRow=Math.max(0,newLines.length-1),this.hardwareCursorRow=this.cursorRow,clear?this.maxLinesRendered=newLines.length:this.maxLinesRendered=Math.max(this.maxLinesRendered,newLines.length);let bufferLength=Math.max(height,newLines.length);this.previousViewportTop=Math.max(0,bufferLength-height),this.positionHardwareCursor(cursorPos,newLines.length),this.previousLines=newLines,this.previousKittyImageIds=this.collectKittyImageIds(newLines),this.previousWidth=width,this.previousHeight=height},debugRedraw=process.env.PI_DEBUG_REDRAW==="1",logRedraw=reason=>{if(!debugRedraw)return;let logPath=path4.join(this.logDirectory,"pi-debug.log"),msg=`[${new Date().toISOString()}] fullRender: ${reason} (prev=${this.previousLines.length}, new=${newLines.length}, height=${height})
596
- `;fs2.mkdirSync(path4.dirname(logPath),{recursive:!0}),fs2.appendFileSync(logPath,msg)};if(this.previousLines.length===0&&!widthChanged&&!heightChanged){logRedraw("first render"),fullRender(!1);return}if(widthChanged){logRedraw(`terminal width changed (${this.previousWidth} -> ${width})`),fullRender(!0);return}if(heightChanged&&!isTermuxSession()){logRedraw(`terminal height changed (${this.previousHeight} -> ${height})`),fullRender(!0);return}if(this.getClearOnShrink()&&newLines.length<this.maxLinesRendered&&!this.hasOverlayEntries){logRedraw(`clearOnShrink (maxLinesRendered=${this.maxLinesRendered})`),fullRender(!0);return}let firstChanged=-1,lastChanged=-1,maxLines=Math.max(newLines.length,this.previousLines.length);for(let i=0;i<maxLines;i++){let oldLine=i<this.previousLines.length?this.previousLines[i]:"",newLine=i<newLines.length?newLines[i]:"";oldLine!==newLine&&(firstChanged===-1&&(firstChanged=i),lastChanged=i)}let appendedLines=newLines.length>this.previousLines.length;if(appendedLines&&(firstChanged===-1&&(firstChanged=this.previousLines.length),lastChanged=newLines.length-1),firstChanged!==-1){let expandedRange=this.expandChangedRangeForKittyImages(firstChanged,lastChanged,newLines);firstChanged=expandedRange.firstChanged,lastChanged=expandedRange.lastChanged}let appendStart=appendedLines&&firstChanged===this.previousLines.length&&firstChanged>0;if(firstChanged===-1){this.positionHardwareCursor(cursorPos,newLines.length),this.previousViewportTop=prevViewportTop,this.previousHeight=height;return}if(firstChanged>=newLines.length){if(this.previousLines.length>newLines.length){let output2=new BoundedTerminalWriter(data=>this.terminal.write(data));output2.append("\x1B[?2026h"),output2.append(this.deleteChangedKittyImages(firstChanged,lastChanged));let targetRow=Math.max(0,newLines.length-1);if(targetRow<prevViewportTop){logRedraw(`deleted lines moved viewport up (${targetRow} < ${prevViewportTop})`),fullRender(!0);return}let lineDiff3=computeLineDiff(targetRow);lineDiff3>0?output2.append(`\x1B[${lineDiff3}B`):lineDiff3<0&&output2.append(`\x1B[${-lineDiff3}A`),output2.append("\r");let extraLines=this.previousLines.length-newLines.length;if(extraLines>height){logRedraw(`extraLines > height (${extraLines} > ${height})`),fullRender(!0);return}let clearStartOffset=newLines.length===0?0:1;extraLines>0&&clearStartOffset>0&&output2.append(`\x1B[${clearStartOffset}B`);for(let i=0;i<extraLines;i++)output2.append("\r\x1B[2K"),i<extraLines-1&&output2.append("\x1B[1B");let moveBack=Math.max(0,extraLines-1+clearStartOffset);moveBack>0&&output2.append(`\x1B[${moveBack}A`),output2.append("\x1B[?2026l"),output2.flush(),this.cursorRow=targetRow,this.hardwareCursorRow=targetRow}this.positionHardwareCursor(cursorPos,newLines.length),this.previousLines=newLines,this.previousKittyImageIds=this.collectKittyImageIds(newLines),this.previousWidth=width,this.previousHeight=height,this.previousViewportTop=prevViewportTop;return}if(firstChanged<prevViewportTop){logRedraw(`firstChanged < viewportTop (${firstChanged} < ${prevViewportTop})`),fullRender(!0);return}let output=new BoundedTerminalWriter(data=>this.terminal.write(data));output.append("\x1B[?2026h"),output.append(this.deleteChangedKittyImages(firstChanged,lastChanged));let prevViewportBottom=prevViewportTop+height-1,moveTargetRow=appendStart?firstChanged-1:firstChanged;if(moveTargetRow>prevViewportBottom){let currentScreenRow=Math.max(0,Math.min(height-1,hardwareCursorRow-prevViewportTop)),moveToBottom=height-1-currentScreenRow;moveToBottom>0&&output.append(`\x1B[${moveToBottom}B`);let scroll=moveTargetRow-prevViewportBottom;output.append(`\r
596
+ `;fs2.mkdirSync(path4.dirname(logPath),{recursive:!0}),fs2.appendFileSync(logPath,msg)};if(this.previousLines.length===0&&!widthChanged&&!heightChanged){logRedraw("first render"),fullRender(!1);return}if(widthChanged){logRedraw(`terminal width changed (${this.previousWidth} -> ${width})`),fullRender(!0);return}if(heightChanged&&!isTermuxSession()){logRedraw(`terminal height changed (${this.previousHeight} -> ${height})`),fullRender(!0);return}if(newLines.length>height&&this.previousLines.length<=height){logRedraw(`live region growing past screen height (${newLines.length} > ${height})`),fullRender(!0);return}if(this.getClearOnShrink()&&newLines.length<this.maxLinesRendered&&!this.hasOverlayEntries){logRedraw(`clearOnShrink (maxLinesRendered=${this.maxLinesRendered})`),fullRender(!0);return}let firstChanged=-1,lastChanged=-1,maxLines=Math.max(newLines.length,this.previousLines.length);for(let i=0;i<maxLines;i++){let oldLine=i<this.previousLines.length?this.previousLines[i]:"",newLine=i<newLines.length?newLines[i]:"";oldLine!==newLine&&(firstChanged===-1&&(firstChanged=i),lastChanged=i)}let appendedLines=newLines.length>this.previousLines.length;if(appendedLines&&(firstChanged===-1&&(firstChanged=this.previousLines.length),lastChanged=newLines.length-1),firstChanged!==-1){let expandedRange=this.expandChangedRangeForKittyImages(firstChanged,lastChanged,newLines);firstChanged=expandedRange.firstChanged,lastChanged=expandedRange.lastChanged}let appendStart=appendedLines&&firstChanged===this.previousLines.length&&firstChanged>0;if(firstChanged===-1){this.positionHardwareCursor(cursorPos,newLines.length),this.previousViewportTop=prevViewportTop,this.previousHeight=height;return}if(firstChanged>=newLines.length){if(this.previousLines.length>newLines.length){let output2=new BoundedTerminalWriter(data=>this.terminal.write(data));output2.append("\x1B[?2026h"),output2.append(this.deleteChangedKittyImages(firstChanged,lastChanged));let targetRow=Math.max(0,newLines.length-1);if(targetRow<prevViewportTop){logRedraw(`deleted lines moved viewport up (${targetRow} < ${prevViewportTop})`),fullRender(!0);return}let lineDiff3=computeLineDiff(targetRow);lineDiff3>0?output2.append(`\x1B[${lineDiff3}B`):lineDiff3<0&&output2.append(`\x1B[${-lineDiff3}A`),output2.append("\r");let extraLines=this.previousLines.length-newLines.length;if(extraLines>height){logRedraw(`extraLines > height (${extraLines} > ${height})`),fullRender(!0);return}let clearStartOffset=newLines.length===0?0:1;extraLines>0&&clearStartOffset>0&&output2.append(`\x1B[${clearStartOffset}B`);for(let i=0;i<extraLines;i++)output2.append("\r\x1B[2K"),i<extraLines-1&&output2.append("\x1B[1B");let moveBack=Math.max(0,extraLines-1+clearStartOffset);moveBack>0&&output2.append(`\x1B[${moveBack}A`),output2.append("\x1B[?2026l"),output2.flush(),this.cursorRow=targetRow,this.hardwareCursorRow=targetRow}this.positionHardwareCursor(cursorPos,newLines.length),this.previousLines=newLines,this.previousKittyImageIds=this.collectKittyImageIds(newLines),this.previousWidth=width,this.previousHeight=height,this.previousViewportTop=prevViewportTop;return}if(firstChanged<prevViewportTop){logRedraw(`firstChanged < viewportTop (${firstChanged} < ${prevViewportTop})`),fullRender(!0);return}let output=new BoundedTerminalWriter(data=>this.terminal.write(data));output.append("\x1B[?2026h"),output.append(this.deleteChangedKittyImages(firstChanged,lastChanged));let prevViewportBottom=prevViewportTop+height-1,moveTargetRow=appendStart?firstChanged-1:firstChanged;if(moveTargetRow>prevViewportBottom){let currentScreenRow=Math.max(0,Math.min(height-1,hardwareCursorRow-prevViewportTop)),moveToBottom=height-1-currentScreenRow;moveToBottom>0&&output.append(`\x1B[${moveToBottom}B`);let scroll=moveTargetRow-prevViewportBottom;output.append(`\r
597
597
  `.repeat(scroll)),prevViewportTop+=scroll,viewportTop+=scroll,hardwareCursorRow=moveTargetRow}let lineDiff2=computeLineDiff(moveTargetRow);lineDiff2>0?output.append(`\x1B[${lineDiff2}B`):lineDiff2<0&&output.append(`\x1B[${-lineDiff2}A`),output.append(appendStart?`\r
598
598
  `:"\r");let renderEnd=Math.min(lastChanged,newLines.length-1);for(let i=firstChanged;i<=renderEnd;i++){i>firstChanged&&output.append(`\r
599
599
  `);let line=newLines[i],isImage=isImageLine(line),imageReservedRows=isImage?this.getKittyImageReservedRows(newLines,i,renderEnd):1;if(imageReservedRows>1){let imageStartScreenRow=i-viewportTop;if(imageStartScreenRow<0||imageStartScreenRow+imageReservedRows>height){logRedraw(`kitty image pre-clear would scroll (${imageStartScreenRow} + ${imageReservedRows} > ${height})`),fullRender(!0);return}output.append("\x1B[2K");for(let row=1;row<imageReservedRows;row++)output.append(`\r
@@ -1078,7 +1078,7 @@ ${processed.hints.join(`
1078
1078
  [${remaining} more lines in file. Use offset=${nextOffset} to continue.]`}else outputText=truncation.content;return{content:[{type:"text",text:outputText}],details}}}}var writeSchema=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"})});function createWriteTool(){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.",parameters:writeSchema,async execute(_toolCallId,{path:path14,content},signal,_onUpdate,{env:env2}){let absolutePath=await resolveToolPath(env2,path14,signal);return withFileMutationQueue(env2,absolutePath,async()=>{if(signal?.aborted)throw new Error("Operation aborted");if(getOrThrow(await env2.writeFile(absolutePath,content,signal)),signal?.aborted)throw new Error("Operation aborted");return{content:[{type:"text",text:`Successfully wrote ${content.length} bytes to ${path14}`}],details:void 0}})}}}var ProxyMessageEventStream=class extends EventStream{constructor(){super(event=>event.type==="done"||event.type==="error",event=>{if(event.type==="done")return event.message;if(event.type==="error")return event.error;throw new Error("Unexpected event type")})}};function buildProxyRequestOptions(options){return{temperature:options.temperature,samplingParams:options.samplingParams,maxTokens:options.maxTokens,reasoning:options.reasoning,cacheRetention:options.cacheRetention,sessionId:options.sessionId,headers:options.headers,metadata:options.metadata,transport:options.transport,thinkingBudgets:options.thinkingBudgets,maxRetryDelayMs:options.maxRetryDelayMs}}function streamProxy(model2,context,options){let stream2=new ProxyMessageEventStream;return(async()=>{let partial={role:"assistant",stopReason:"pending",content:[],api:model2.api,provider:model2.provider,model:model2.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()},reader,abortHandler=()=>{reader&&reader.cancel("Request aborted by user").catch(()=>{})};options.signal&&options.signal.addEventListener("abort",abortHandler);try{let response=await fetch(`${options.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${options.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model:model2,context,options:buildProxyRequestOptions(options)}),signal:options.signal});if(!response.ok){let errorMessage2=`Proxy error: ${response.status} ${response.statusText}`;try{let errorData=await response.json();errorData.error&&(errorMessage2=`Proxy error: ${errorData.error}`)}catch{}throw new Error(errorMessage2)}reader=response.body.getReader();let decoder=new TextDecoder,buffer="";for(;;){let{done,value}=await reader.read();if(done)break;if(options.signal?.aborted)throw new Error("Request aborted by user");buffer+=decoder.decode(value,{stream:!0});let lines=buffer.split(`
1079
1079
  `);buffer=lines.pop()||"";for(let line of lines)if(line.startsWith("data: ")){let data=line.slice(6).trim();if(data){let proxyEvent=JSON.parse(data),event=processProxyEvent(proxyEvent,partial);event&&stream2.push(event)}}}if(options.signal?.aborted)throw new Error("Request aborted by user");stream2.end()}catch(error){let errorMessage2=error instanceof Error?error.message:String(error),reason=options.signal?.aborted?"aborted":"error";partial.stopReason=reason,partial.errorMessage=errorMessage2,stream2.push({type:"error",reason,error:partial}),stream2.end()}finally{options.signal&&options.signal.removeEventListener("abort",abortHandler)}})(),stream2}function processProxyEvent(proxyEvent,partial){switch(proxyEvent.type){case"start":return{type:"start",partial};case"text_start":return partial.content[proxyEvent.contentIndex]={type:"text",text:""},{type:"text_start",contentIndex:proxyEvent.contentIndex,partial};case"text_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="text")return content.text+=proxyEvent.delta,{type:"text_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received text_delta for non-text content")}case"text_end":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="text")return content.textSignature=proxyEvent.contentSignature,{type:"text_end",contentIndex:proxyEvent.contentIndex,content:content.text,partial};throw new Error("Received text_end for non-text content")}case"thinking_start":return partial.content[proxyEvent.contentIndex]={type:"thinking",thinking:""},{type:"thinking_start",contentIndex:proxyEvent.contentIndex,partial};case"thinking_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="thinking")return content.thinking+=proxyEvent.delta,{type:"thinking_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received thinking_delta for non-thinking content")}case"thinking_end":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="thinking")return content.thinkingSignature=proxyEvent.contentSignature,{type:"thinking_end",contentIndex:proxyEvent.contentIndex,content:content.thinking,partial};throw new Error("Received thinking_end for non-thinking content")}case"toolcall_start":return partial.content[proxyEvent.contentIndex]={type:"toolCall",id:proxyEvent.id,name:proxyEvent.toolName,arguments:{},partialJson:""},{type:"toolcall_start",contentIndex:proxyEvent.contentIndex,partial};case"toolcall_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="toolCall")return content.partialJson+=proxyEvent.delta,content.arguments=parseStreamingJson(content.partialJson)||{},partial.content[proxyEvent.contentIndex]={...content},{type:"toolcall_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received toolcall_delta for non-toolCall content")}case"toolcall_end":{let content=partial.content[proxyEvent.contentIndex];return content?.type==="toolCall"?(Object.assign(content,proxyEvent.toolCall),delete content.partialJson,{type:"toolcall_end",contentIndex:proxyEvent.contentIndex,toolCall:content,partial}):void 0}case"done":return partial.stopReason=proxyEvent.reason,partial.usage=proxyEvent.usage,{type:"done",reason:proxyEvent.reason,message:partial};case"error":return partial.stopReason=proxyEvent.reason,partial.errorMessage=proxyEvent.errorMessage,partial.usage=proxyEvent.usage,{type:"error",reason:proxyEvent.reason,error:partial};default:{let _exhaustiveCheck=proxyEvent;console.warn(`Unhandled proxy event type: ${proxyEvent.type}`);return}}}function defaultSearchText(_metadata,entry,label){return label===void 0?JSON.stringify(entry):`${JSON.stringify(entry)} ${label}`}async function*scanReadableEntries(readable,metadata,options,query={}){let projectText=options.projectText??defaultSearchText,pageSize=query.limit??options.pageSize??100,afterSeq=query.afterSeq??0,entryTypes=query.entryTypes===void 0?void 0:new Set(query.entryTypes);for(;;){let entries=await readable.findEntries({order:"oldestFirst",limit:pageSize,cursor:{afterSeq},type:query.entryTypes?.length===1?query.entryTypes[0]:void 0});if(entries.length===0)break;for(let entry of entries){if(entryTypes!==void 0&&!entryTypes.has(entry.type))continue;let label=await readable.getLabel(entry.id);yield{entryId:entry.id,seq:entry.seq,type:entry.type,timestamp:entry.timestamp,text:projectText(metadata,entry,label),fields:label===void 0?void 0:{label}}}if(afterSeq=entries[entries.length-1]?.seq??afterSeq,entries.length<pageSize)break}}async function*scanningEntries(readable,options={}){yield*scanReadableEntries(readable,await readable.getMetadata(),options)}async function*arraySource(readables){yield*readables}function readablesFor(source2,options){return typeof source2=="function"?source2(options):arraySource(source2)}function defaultMatch(queryText,candidate){return candidate.text.toLowerCase().includes(queryText)}function throwIfAborted(signal){if(!signal?.aborted)return;if(signal.reason instanceof Error)throw signal.reason;let error=new Error("The operation was aborted");throw error.name="AbortError",error}function createDefaultScanningHit(metadata,candidate){return{sessionId:metadata.id,entryId:candidate.entryId,timestamp:candidate.timestamp,snippet:candidate.text}}function createScanningSessionSearch(source2,options={}){let createHit=options.createHit??((metadata,candidate)=>createDefaultScanningHit(metadata,candidate));return{async*search(text,searchOptions={}){let normalizedText=text.trim().toLowerCase();if(!normalizedText||searchOptions.limit!==void 0&&searchOptions.limit<=0||searchOptions.entryTypes?.length===0)return;let hitCount=0,seenSessionIds=new Set,entryTypes=searchOptions.entryTypes===void 0?void 0:new Set(searchOptions.entryTypes),sourceOptions=options.sourceOptions?.(normalizedText,searchOptions);for await(let readable of readablesFor(source2,sourceOptions)){throwIfAborted(searchOptions.signal);let metadata=await readable.getMetadata();if(seenSessionIds.has(metadata.id))throw new Error(`Duplicate sessionId: ${metadata.id}`);seenSessionIds.add(metadata.id);for await(let candidate of scanReadableEntries(readable,metadata,options,{entryTypes:searchOptions.entryTypes}))if(throwIfAborted(searchOptions.signal),!(entryTypes!==void 0&&!entryTypes.has(candidate.type)||!(options.match?.(normalizedText,candidate,metadata)??defaultMatch(normalizedText,candidate)))&&(yield createHit(metadata,candidate),hitCount+=1,searchOptions.limit!==void 0&&hitCount>=searchOptions.limit))return}}}}var oauth_exports={};import{createRequire as createRequire5}from"node:module";var require3=createRequire5(import.meta.url),createJitiImpl;function createJiti(...args){return createJitiImpl??=require3("jiti").createJiti,createJitiImpl(...args)}import{EventEmitter as EventEmitter2}from"node:events";function createEventBus(){let emitter=new EventEmitter2;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()}}}import{spawn as spawn3}from"node:child_process";async function execCommand(command,args,cwd,options){return new Promise(resolve26=>{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),resolve26({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve26({stdout,stderr,code:1,killed})})})}import{readFileSync as readFileSync4}from"node:fs";var RESOURCE_FIELDS=["extensions","skills","prompts","themes"];function isObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function readPiManifest(packageJsonPath){try{let pkg2=JSON.parse(stripBom(readFileSync4(packageJsonPath,"utf-8")));if(!isObject2(pkg2)||!isObject2(pkg2.pi))return null;let manifest={};for(let field2 of RESOURCE_FIELDS){let entries=pkg2.pi[field2];Array.isArray(entries)&&entries.every(entry=>typeof entry=="string")&&(manifest[field2]=entries)}return manifest}catch{return null}}function createSourceInfo(path14,metadata){return{path:path14,source:metadata.source,scope:metadata.scope,origin:metadata.origin,baseDir:metadata.baseDir}}function createSyntheticSourceInfo(path14,options){return{path:path14,source:options.source,scope:options.scope??"temporary",origin:options.origin??"top-level",baseDir:options.baseDir}}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(`
1080
1080
  --- ${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)}
1081
- `)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var VIRTUAL_MODULES={typebox:build_exports,"typebox/compile":compile_exports,"typebox/value":value_exports2,"@sinclair/typebox":build_exports,"@sinclair/typebox/compile":compile_exports,"@sinclair/typebox/value":value_exports2,"@earendil-works/pi-agent-core":dist_exports2,"@earendil-works/pi-tui":dist_exports,"@earendil-works/pi-ai":compat_exports,"@earendil-works/pi-ai/compat":compat_exports,"@earendil-works/pi-ai/oauth":oauth_exports,"@earendil-works/pi-ai/providers/all":all_exports,"@earendil-works/pi-coding-agent":dist_exports3,"@mariozechner/pi-agent-core":dist_exports2,"@mariozechner/pi-tui":dist_exports,"@mariozechner/pi-ai":compat_exports,"@mariozechner/pi-ai/compat":compat_exports,"@mariozechner/pi-ai/oauth":oauth_exports,"@mariozechner/pi-ai/providers/all":all_exports,"@mariozechner/pi-coding-agent":dist_exports3},require4=createRequire6(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isBundledNode=!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",_aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require4.resolve("typebox"),typeboxCompileEntry=require4.resolve("typebox/compile"),typeboxValueEntry=require4.resolve("typebox/value"),packagesRoot=path7.resolve(__dirname2,"../../../../"),resolveWorkspaceOrImport=(workspaceRelativePath,specifier)=>{let workspacePath=path7.join(packagesRoot,workspaceRelativePath);return fs5.existsSync(workspacePath)?workspacePath:fileURLToPath5(import.meta.resolve(specifier))},piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveWorkspaceOrImport("agent/dist/index.js","@earendil-works/pi-agent-core"),piTuiEntry=resolveWorkspaceOrImport("tui/dist/index.js","@earendil-works/pi-tui"),piAiCompatEntry=resolveWorkspaceOrImport("ai/dist/compat.js","@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveWorkspaceOrImport("ai/dist/oauth.js","@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveWorkspaceOrImport("ai/dist/providers/all.js","@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":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:(provider2,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider:provider2,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 list=extension.handlers.get(event)??[];list.push(handler),extension.handlers.set(event,list)},registerTool(tool){assertActive(),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(model2){return assertActive(),runtime.setModel(model2)},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,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);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 factory=await createJiti(import.meta.url,{moduleCache:!1,...isBunBinary||isNodeSeaBinary||isBundledNode?{virtualModules:VIRTUAL_MODULES,tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:VIRTUAL_MODULES,tsconfigPaths:!0}:{alias:getAliases()}}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source2=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:source2,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 resolveExtensionEntries(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=resolveExtensionEntries(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=resolveExtensionEntries(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS=["app.interrupt","app.clear","app.exit","app.suspend","app.thinking.cycle","app.model.cycleForward","app.model.cycleBackward","app.model.select","app.tools.expand","app.thinking.toggle","app.editor.external","app.message.copy","app.message.followUp","tui.input.submit","tui.select.confirm","tui.select.cancel","tui.input.copy","tui.editor.deleteToLineEnd"],buildBuiltinKeybindings=resolvedKeybindings=>{let builtinKeybindings={};for(let[keybinding,keys]of Object.entries(resolvedKeybindings)){if(keys===void 0)continue;let keyList=Array.isArray(keys)?keys:[keys],restrictOverride=RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS.includes(keybinding);for(let key of keyList){let normalizedKey=key.toLowerCase();builtinKeybindings[normalizedKey]?.restrictOverride&&!restrictOverride||(builtinKeybindings[normalizedKey]={keybinding,restrictOverride})}}return builtinKeybindings};async function emitSessionShutdownEvent(extensionRunner,event){return extensionRunner.hasHandlers("session_shutdown")?(await extensionRunner.emit(event),!0):!1}async function emitProjectTrustEvent(extensionsResult,event,ctx){let errors=[];for(let ext2 of extensionsResult.extensions){let handlers=ext2.handlers.get("project_trust");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult.trusted==="undecided")continue;return{result:handlerResult,errors}}catch(error){errors.push({extensionPath:ext2.path,event:event.type,error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:void 0})}}return{errors}}var noOpUIContext={select:async()=>{},confirm:async()=>!1,input:async()=>{},notify:()=>{},onTerminalInput:()=>()=>{},setStatus:()=>{},setWorkingMessage:()=>{},setWorkingVisible:()=>{},setWorkingIndicator:()=>{},setHiddenThinkingLabel:()=>{},setWidget:()=>{},setFooter:()=>{},setHeader:()=>{},setTitle:()=>{},custom:async()=>{},pasteToEditor:()=>{},setEditorText:()=>{},getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:()=>{},setEditorComponent:()=>{},getEditorComponent:()=>{},get theme(){return theme},getAllThemes:()=>[],getTheme:()=>{},setTheme:_theme=>({success:!1,error:"UI not available"}),getToolsExpanded:()=>!1,setToolsExpanded:()=>{}},ExtensionRunner=class{constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.mode="print",this.errorListeners=new Set,this.getModel=()=>{},this.getScopedModels=()=>[],this.isIdleFn=()=>!0,this.isProjectTrustedFn=()=>!0,this.getSignalFn=()=>{},this.waitForIdleFn=async()=>{},this.abortFn=()=>{},this.hasPendingMessagesFn=()=>!1,this.getContextUsageFn=()=>{},this.compactFn=()=>{},this.getSystemPromptFn=()=>"",this.getSystemPromptOptionsFn=()=>({cwd:this.cwd}),this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{},this.shutdownHandler=()=>{},this.shortcutDiagnostics=[],this.commandDiagnostics=[],this.uiPromptDepth=0,this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions,contextActions,providerActions){this.runtime.sendMessage=actions.sendMessage,this.runtime.sendUserMessage=actions.sendUserMessage,this.runtime.appendEntry=actions.appendEntry,this.runtime.setSessionName=actions.setSessionName,this.runtime.getSessionName=actions.getSessionName,this.runtime.setLabel=actions.setLabel,this.runtime.getActiveTools=actions.getActiveTools,this.runtime.getAllTools=actions.getAllTools,this.runtime.setActiveTools=actions.setActiveTools,this.runtime.refreshTools=actions.refreshTools,this.runtime.getCommands=actions.getCommands,this.runtime.setModel=actions.setModel,this.runtime.getThinkingLevel=actions.getThinkingLevel,this.runtime.setThinkingLevel=actions.setThinkingLevel,this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>({cwd:this.cwd}));for(let{name,config,extensionPath}of this.runtime.pendingProviderRegistrations)try{providerActions?.registerProvider?providerActions.registerProvider(name,config):this.modelRegistry.registerProvider(name,config)}catch(err2){this.emitError({extensionPath,event:"register_provider",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}this.runtime.pendingProviderRegistrations=[];for(let{provider:provider2,extensionPath}of this.runtime.pendingNativeProviderRegistrations)try{providerActions?.registerNativeProvider?providerActions.registerNativeProvider(provider2):this.modelRegistry.registerProvider(provider2)}catch(err2){this.emitError({extensionPath,event:"register_provider",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}this.runtime.pendingNativeProviderRegistrations=[],this.runtime.registerProvider=(name,config)=>{if(providerActions?.registerProvider){providerActions.registerProvider(name,config);return}this.modelRegistry.registerProvider(name,config)},this.runtime.registerNativeProvider=provider2=>{if(providerActions?.registerNativeProvider){providerActions.registerNativeProvider(provider2);return}this.modelRegistry.registerProvider(provider2)},this.runtime.unregisterProvider=name=>{if(providerActions?.unregisterProvider){providerActions.unregisterProvider(name);return}this.modelRegistry.unregisterProvider(name)}}bindCommandContext(actions){if(actions){this.waitForIdleFn=actions.waitForIdle,this.newSessionHandler=actions.newSession,this.forkHandler=actions.fork,this.navigateTreeHandler=actions.navigateTree,this.switchSessionHandler=actions.switchSession,this.reloadHandler=actions.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(err2){throw finish(),err2}}emitUIPromptEvent(event){queueMicrotask(()=>{this.emit(event)})}getUIContext(){return this.uiContext}hasUI(){return this.uiContext!==noOpUIContext}getExtensionPaths(){return this.extensions.map(e=>e.path)}getAllRegisteredTools(){let toolsByName=new Map;for(let ext2 of this.extensions)for(let tool of ext2.tools.values())toolsByName.has(tool.definition.name)||toolsByName.set(tool.definition.name,tool);return Array.from(toolsByName.values())}getToolDefinition(toolName){for(let ext2 of this.extensions){let tool=ext2.tools.get(toolName);if(tool)return tool.definition}}getFlags(){let allFlags=new Map;for(let ext2 of this.extensions)for(let[name,flag]of ext2.flags)allFlags.has(name)||allFlags.set(name,flag);return allFlags}setFlagValue(name,value){this.runtime.flagValues.set(name,value)}getFlagValues(){return new Map(this.runtime.flagValues)}getShortcuts(resolvedKeybindings){this.shortcutDiagnostics=[];let builtinKeybindings=buildBuiltinKeybindings(resolvedKeybindings),extensionShortcuts=new Map,addDiagnostic=(message,extensionPath)=>{this.shortcutDiagnostics.push({type:"warning",message,path:extensionPath}),this.hasUI()||console.warn(message)};for(let ext2 of this.extensions)for(let[key,shortcut]of ext2.shortcuts){let normalizedKey=key.toLowerCase(),builtInKeybinding=builtinKeybindings[normalizedKey];if(builtInKeybinding?.restrictOverride===!0){addDiagnostic(`Extension shortcut '${key}' from ${shortcut.extensionPath} conflicts with built-in shortcut. Skipping.`,shortcut.extensionPath);continue}builtInKeybinding?.restrictOverride===!1&&addDiagnostic(`Extension shortcut conflict: '${key}' is built-in shortcut for ${builtInKeybinding.keybinding} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath);let existingExtensionShortcut=extensionShortcuts.get(normalizedKey);existingExtensionShortcut&&addDiagnostic(`Extension shortcut conflict: '${key}' registered by both ${existingExtensionShortcut.extensionPath} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath),extensionShortcuts.set(normalizedKey,shortcut)}return extensionShortcuts}getShortcutDiagnostics(){return this.shortcutDiagnostics}invalidate(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()."){this.staleMessage||(this.staleMessage=message,this.runtime.invalidate(message))}assertActive(){if(this.staleMessage)throw new Error(this.staleMessage)}onError(listener){return this.errorListeners.add(listener),()=>this.errorListeners.delete(listener)}emitError(error){for(let listener of this.errorListeners)listener(error)}hasHandlers(eventType){for(let ext2 of this.extensions){let handlers=ext2.handlers.get(eventType);if(handlers&&handlers.length>0)return!0}return!1}getMessageRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.messageRenderers.get(customType);if(renderer)return renderer}}getMarkdownTransformers(){return this.extensions.flatMap(ext2=>ext2.markdownTransformer?[ext2.markdownTransformer]:[])}getEntryRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.entryRenderers?.get(customType);if(renderer)return renderer}}resolveRegisteredCommands(){let commands=[],counts=new Map;for(let ext2 of this.extensions)for(let command of ext2.commands.values())commands.push(command),counts.set(command.name,(counts.get(command.name)??0)+1);let seen=new Map,takenInvocationNames=new Set;return commands.map(command=>{let occurrence=(seen.get(command.name)??0)+1;seen.set(command.name,occurrence);let invocationName=(counts.get(command.name)??0)>1?`${command.name}:${occurrence}`:command.name;if(takenInvocationNames.has(invocationName)){let suffix=occurrence;do suffix++,invocationName=`${command.name}:${suffix}`;while(takenInvocationNames.has(invocationName))}return takenInvocationNames.add(invocationName),{...command,invocationName}})}getModelRegistry(){return this.modelRegistry}getRegisteredCommands(){return this.commandDiagnostics=[],this.resolveRegisteredCommands()}getCommandDiagnostics(){return this.commandDiagnostics}getCommand(name){return this.resolveRegisteredCommands().find(command=>command.invocationName===name)}shutdown(){this.shutdownHandler()}getActiveTools(){return this.assertActive(),this.runtime.getActiveTools()}createContext(){let runner=this,getModel2=this.getModel,getScopedModels=this.getScopedModels;return{get ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}createCommandContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));return context.getSystemPromptOptions=()=>(this.assertActive(),this.getSystemPromptOptionsFn()),context.waitForIdle=()=>(this.assertActive(),this.waitForIdleFn()),context.newSession=options=>(this.assertActive(),this.newSessionHandler(options)),context.fork=(entryId,options)=>(this.assertActive(),this.forkHandler(entryId,options)),context.navigateTree=(targetId,options)=>(this.assertActive(),this.navigateTreeHandler(targetId,options)),context.switchSession=(sessionPath,options)=>(this.assertActive(),this.switchSessionHandler(sessionPath,options)),context.reload=()=>(this.assertActive(),this.reloadHandler()),context}isSessionBeforeEvent(event){return event.type==="session_before_switch"||event.type==="session_before_fork"||event.type==="session_before_compact"||event.type==="session_before_tree"}async emit(event){let ctx=this.createContext(),result;for(let ext2 of this.extensions){let handlers=ext2.handlers.get(event.type);if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(this.isSessionBeforeEvent(event)&&handlerResult&&(result=handlerResult,result.cancel))return result}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:event.type,error:message,stack})}}return result}async emitMessageEnd(event){let ctx=this.createContext(),currentMessage=event.message,modified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("message_end");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let currentEvent={...event,message:currentMessage},handlerResult=await handler(currentEvent,ctx);if(!handlerResult?.message)continue;if(handlerResult.message.role!==currentMessage.role){this.emitError({extensionPath:ext2.path,event:"message_end",error:"message_end handlers must return a message with the same role"});continue}currentMessage=handlerResult.message,modified=!0}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"message_end",error:message,stack})}}return modified?currentMessage:void 0}async emitToolResult(event){let ctx=this.createContext(),currentEvent={...event},modified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("tool_result");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(currentEvent,ctx);if(!handlerResult)continue;handlerResult.content!==void 0&&(currentEvent.content=handlerResult.content,modified=!0),handlerResult.details!==void 0&&(currentEvent.details=handlerResult.details,modified=!0),handlerResult.isError!==void 0&&(currentEvent.isError=handlerResult.isError,modified=!0),handlerResult.usage!==void 0&&(currentEvent.usage=handlerResult.usage,modified=!0)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"tool_result",error:message,stack})}}if(modified)return{content:currentEvent.content,details:currentEvent.details,isError:currentEvent.isError,usage:currentEvent.usage}}async emitToolCall(event){let ctx=this.createContext(),result;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("tool_call");if(!(!handlers||handlers.length===0))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result=handlerResult,result.block))return result}}return result}async emitUserBash(event){let ctx=this.createContext();for(let ext2 of this.extensions){let handlers=ext2.handlers.get("user_bash");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult)return handlerResult}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"user_bash",error:message,stack})}}}async emitContext(messages){let ctx=this.createContext(),currentMessages=structuredClone(messages);for(let ext2 of this.extensions){let handlers=ext2.handlers.get("context");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"context",messages:currentMessages},ctx);handlerResult&&handlerResult.messages&&(currentMessages=handlerResult.messages)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context",error:message,stack})}}return currentMessages}async emitBeforeProviderRequest(payload){let ctx=this.createContext(),currentPayload=payload;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_provider_request");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"before_provider_request",payload:currentPayload},ctx);handlerResult!==void 0&&(currentPayload=handlerResult)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_request",error:message,stack})}}return currentPayload}async emitBeforeProviderHeaders(headers,requestId){let ctx=this.createContext();for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_provider_headers");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{await handler({type:"before_provider_headers",headers,requestId},ctx)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_headers",error:message,stack})}}return headers}async emitBeforeAgentStart(prompt,images,systemPrompt,systemPromptOptions){let currentSystemPrompt=systemPrompt,ctx=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));ctx.getSystemPrompt=()=>(this.assertActive(),currentSystemPrompt);let messages=[],systemPromptModified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_agent_start");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"before_agent_start",prompt,images,systemPrompt:currentSystemPrompt,systemPromptOptions},ctx);if(handlerResult){let result=handlerResult;result.message&&messages.push(result.message),result.systemPrompt!==void 0&&(currentSystemPrompt=result.systemPrompt,systemPromptModified=!0)}}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_agent_start",error:message,stack})}}if(messages.length>0||systemPromptModified)return{messages:messages.length>0?messages:void 0,systemPrompt:systemPromptModified?currentSystemPrompt:void 0}}async emitResourcesDiscover(cwd,reason){let ctx=this.createContext(),skillPaths=[],promptPaths=[],themePaths=[];for(let ext2 of this.extensions){let handlers=ext2.handlers.get("resources_discover");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let result=await handler({type:"resources_discover",cwd,reason},ctx);result?.skillPaths?.length&&skillPaths.push(...result.skillPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result?.promptPaths?.length&&promptPaths.push(...result.promptPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result?.themePaths?.length&&themePaths.push(...result.themePaths.map(path14=>({path:path14,extensionPath:ext2.path})))}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"resources_discover",error:message,stack})}}return{skillPaths,promptPaths,themePaths}}async emitInput(text,images,source2,streamingBehavior){let ctx=this.createContext(),currentText=text,currentImages=images;for(let ext2 of this.extensions)for(let handler of ext2.handlers.get("input")??[])try{let result=await handler({type:"input",text:currentText,images:currentImages,source:source2,streamingBehavior},ctx);if(result?.action==="handled")return result;result?.action==="transform"&&(currentText=result.text,currentImages=result.images??currentImages)}catch(err2){this.emitError({extensionPath:ext2.path,event:"input",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}return currentText!==text||currentImages!==images?{action:"transform",text:currentText,images:currentImages}:{action:"continue"}}};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}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,constrainedSampling:definition.constrainedSampling,prepareArguments:definition.prepareArguments,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){let tool=wrapToolDefinition(registeredTool.definition,()=>runner.createContext()),execute=tool.execute;return{...tool,execute:async(toolCallId,params,signal,onUpdate)=>{let activeBefore=runner.getActiveTools(),result=await execute(toolCallId,params,signal,onUpdate),activeAfter=runner.getActiveTools();if(!activeBefore.every(name=>activeAfter.includes(name)))return result;let beforeNames=new Set(activeBefore),addedToolNames=activeAfter.filter(name=>!beforeNames.has(name));return addedToolNames.length===0?result:{...result,addedToolNames:[...new Set([...result.addedToolNames??[],...addedToolNames])]}}}}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import{execSync as execSync2,spawnSync as spawnSync2}from"child_process";var commandResultCache=new Map,ENV_VAR_NAME_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,ENV_VAR_NAME_PREFIX_RE=/^[A-Za-z_][A-Za-z0-9_]*/;function appendLiteral(parts,value){if(!value)return;let previousPart=parts[parts.length-1];if(previousPart?.type==="literal"){previousPart.value+=value;return}parts.push({type:"literal",value})}function parseConfigValueTemplate(config){let parts=[],index3=0;for(;index3<config.length;){let dollarIndex=config.indexOf("$",index3);if(dollarIndex<0){appendLiteral(parts,config.slice(index3));break}appendLiteral(parts,config.slice(index3,dollarIndex));let nextChar=config[dollarIndex+1];if(nextChar==="$"||nextChar==="!"){appendLiteral(parts,nextChar),index3=dollarIndex+2;continue}if(nextChar==="{"){let endIndex=config.indexOf("}",dollarIndex+2);if(endIndex<0){appendLiteral(parts,"$"),index3=dollarIndex+1;continue}let name=config.slice(dollarIndex+2,endIndex);ENV_VAR_NAME_RE.test(name)?parts.push({type:"env",name}):appendLiteral(parts,config.slice(dollarIndex,endIndex+1)),index3=endIndex+1;continue}let match2=config.slice(dollarIndex+1).match(ENV_VAR_NAME_PREFIX_RE);if(match2){parts.push({type:"env",name:match2[0]}),index3=dollarIndex+1+match2[0].length;continue}appendLiteral(parts,"$"),index3=dollarIndex+1}return parts}function parseConfigValueReference(config){return config.startsWith("!")?{type:"command",config}:{type:"template",parts:parseConfigValueTemplate(config)}}function resolveEnvConfigValue(name,env2){return env2?.[name]||process.env[name]||void 0}function getTemplateEnvVarNames(parts){let names2=[];for(let part of parts)part.type!=="env"||names2.includes(part.name)||names2.push(part.name);return names2}function resolveTemplate(parts,env2){let resolved="";for(let part of parts){if(part.type==="literal"){resolved+=part.value;continue}let envValue=resolveEnvConfigValue(part.name,env2);if(envValue===void 0)return;resolved+=envValue}return resolved}function getConfigValueEnvVarNames(config){let reference=parseConfigValueReference(config);return reference.type==="template"?getTemplateEnvVarNames(reference.parts):[]}function getMissingConfigValueEnvVarNames(config,env2){return getConfigValueEnvVarNames(config).filter(name=>resolveEnvConfigValue(name,env2)===void 0)}function isCommandConfigValue(config){return parseConfigValueReference(config).type==="command"}function isConfigValueConfigured(config,env2){return getMissingConfigValueEnvVarNames(config,env2).length===0}function resolveConfigValue(config,env2){let reference=parseConfigValueReference(config);return reference.type==="command"?executeCommand(reference.config):resolveTemplate(reference.parts,env2)}function executeWithConfiguredShell(command){try{let{shell,args,commandTransport}=getShellConfig(),commandFromStdin=commandTransport==="stdin",result=spawnSync2(shell,commandFromStdin?args:[...args,command],{encoding:"utf-8",input:commandFromStdin?command:void 0,timeout:1e4,stdio:[commandFromStdin?"pipe":"ignore","pipe","ignore"],shell:!1,windowsHide:!0});return result.error?result.error.code==="ENOENT"?{executed:!1,value:void 0}:{executed:!0,value:void 0}:result.status!==0?{executed:!0,value:void 0}:{executed:!0,value:(result.stdout??"").trim()||void 0}}catch{return{executed:!1,value:void 0}}}function executeWithDefaultShell(command){try{return execSync2(command,{encoding:"utf-8",timeout:1e4,stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function executeCommandUncached(commandConfig){let command=commandConfig.slice(1);return process.platform==="win32"?(()=>{let configuredResult=executeWithConfiguredShell(command);return configuredResult.executed?configuredResult.value:executeWithDefaultShell(command)})():executeWithDefaultShell(command)}function executeCommand(commandConfig){if(commandResultCache.has(commandConfig))return commandResultCache.get(commandConfig);let result=executeCommandUncached(commandConfig);return commandResultCache.set(commandConfig,result),result}function resolveConfigValueUncached(config,env2){let reference=parseConfigValueReference(config);return reference.type==="command"?executeCommandUncached(reference.config):resolveTemplate(reference.parts,env2)}function resolveConfigValueOrThrow(config,description,env2){let resolvedValue=resolveConfigValueUncached(config,env2);if(resolvedValue!==void 0)return resolvedValue;let reference=parseConfigValueReference(config);if(reference.type==="command")throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);if(reference.type==="template"){let missingEnvVars=getMissingConfigValueEnvVarNames(config,env2);if(missingEnvVars.length===1)throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);if(missingEnvVars.length>1)throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`)}throw new Error(`Failed to resolve ${description}`)}function resolveHeadersOrThrow(headers,description,env2){if(!headers)return;let resolved={};for(let[key,value]of Object.entries(headers))resolved[key]=resolveConfigValueOrThrow(value,`${description} header "${key}"`,env2);return Object.keys(resolved).length>0?resolved:void 0}function mergeCompat(base,override){if(!override)return base;let merged={...base,...override},baseNested=base,overrideNested=override,mergedNested=merged;for(let key of["openRouterRouting","vercelGatewayRouting","chatTemplateKwargs","chatTemplateArgs"]){let baseValue=baseNested?.[key],overrideValue=overrideNested[key];(typeof baseValue=="object"&&baseValue!==null||typeof overrideValue=="object"&&overrideValue!==null)&&(mergedNested[key]={...baseValue,...overrideValue})}return merged}function applyModelOverride(model2,override){return{...model2,name:override.name??model2.name,reasoning:override.reasoning??model2.reasoning,thinkingLevelMap:override.thinkingLevelMap?{...model2.thinkingLevelMap,...override.thinkingLevelMap}:model2.thinkingLevelMap,input:override.input??model2.input,cost:override.cost?{input:override.cost.input??model2.cost.input,output:override.cost.output??model2.cost.output,cacheRead:override.cost.cacheRead??model2.cost.cacheRead,cacheWrite:override.cost.cacheWrite??model2.cost.cacheWrite,tiers:override.cost.tiers??model2.cost.tiers}:model2.cost,contextWindow:override.contextWindow??model2.contextWindow,maxTokens:override.maxTokens??model2.maxTokens,samplingParams:override.samplingParams?{...model2.samplingParams,...override.samplingParams}:model2.samplingParams,compat:mergeCompat(model2.compat,override.compat)}}function modelFromJson(providerId,definition,providerConfig,defaults2){let api=definition.api??providerConfig.api??defaults2?.api;if(!api)throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);let baseUrl=definition.baseUrl??providerConfig.baseUrl??defaults2?.baseUrl;if(!baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);if(definition.contextWindow!==void 0&&definition.contextWindow<=0)throw new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);if(definition.maxTokens!==void 0&&definition.maxTokens<=0)throw new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);return{id:definition.id,name:definition.name??definition.id,api,provider:providerId,baseUrl,reasoning:definition.reasoning??!1,thinkingLevelMap:definition.thinkingLevelMap,input:definition.input??["text"],cost:definition.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:definition.contextWindow??128e3,maxTokens:definition.maxTokens??16384,samplingParams:definition.samplingParams,headers:void 0,compat:mergeCompat(providerConfig.compat,definition.compat)}}function applyModelsJson(providerId,baseModels,config){if(!config)return[...baseModels];if(config.oauth&&!config.baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when "oauth" is set.`);let hasOverrides=config.modelOverrides&&Object.keys(config.modelOverrides).length>0;if(!config.models?.length&&!config.baseUrl&&!config.headers&&!config.compat&&!hasOverrides&&!config.apiKey&&!config.oauth&&config.authHeader===void 0)throw new Error(`Provider ${providerId}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);let models=baseModels.map(model2=>({...model2,baseUrl:config.oauth==="radius"?model2.baseUrl:config.baseUrl??model2.baseUrl,compat:mergeCompat(model2.compat,config.compat)}));for(let definition of config.models??[]){let existingIndex=models.findIndex(model3=>model3.id===definition.id),defaults2=existingIndex>=0?models[existingIndex]:models[0],model2=modelFromJson(providerId,definition,config,defaults2);existingIndex>=0?models[existingIndex]=model2:models.push(model2)}return models}function applyExtension(providerId,models,config){return config?config.models?config.models.map(definition=>{let defaults2=models.find(model2=>model2.id===definition.id)??models[0],api=definition.api??config.api??defaults2?.api;if(!api)throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);let baseUrl=definition.baseUrl??config.baseUrl??defaults2?.baseUrl;if(!baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);return{...definition,api,provider:providerId,baseUrl,headers:void 0}}):config.baseUrl?models.map(model2=>({...model2,baseUrl:config.baseUrl})):[...models]:[...models]}function adaptOAuth(config){return{name:config.name,isSubscription:config.isSubscription,login:async callbacks=>({...await config.login({onAuth:info=>callbacks.notify({type:"auth_url",...info}),onDeviceCode:info=>callbacks.notify({type:"device_code",...info}),onPrompt:prompt=>callbacks.prompt({type:"text",...prompt}),onProgress:message=>callbacks.notify({type:"progress",message}),onManualCodeInput:()=>callbacks.prompt({type:"manual_code",message:"Paste the authorization code"}),onSelect:prompt=>callbacks.prompt({type:"select",...prompt}),signal:callbacks.signal}),type:"oauth"}),refresh:async(credential,signal)=>({...await config.refreshToken(credential,signal),type:"oauth"}),toAuth:async credential=>({apiKey:config.getApiKey(credential)})}}function withConfiguredAuth(auth,headers,authHeader){let mergedHeaders=auth.headers||headers?{...auth.headers,...headers}:void 0;if(authHeader){if(!auth.apiKey)throw new Error("authHeader requires a resolved API key");mergedHeaders={...mergedHeaders,Authorization:`Bearer ${auth.apiKey}`}}return{...auth,headers:mergedHeaders}}function configuredApiKey(config,extension){return extension?.apiKey??config?.apiKey}function configuredHeaders(config,extension){if(!(!config?.headers&&!extension?.headers))return{...config?.headers,...extension?.headers}}async function configContextEnv(values,ctx,explicit){let env2={...explicit};for(let name of new Set(values.flatMap(getConfigValueEnvVarNames))){if(env2[name]!==void 0)continue;let value=await ctx.env(name);value!==void 0&&(env2[name]=value)}return Object.keys(env2).length>0?env2:void 0}function composeApiKeyAuth(providerId,base,config,extension){let inherited=base?.auth.apiKey,rawKey=configuredApiKey(config,extension),oauth=extension?.oauth??base?.auth.oauth;if(!inherited&&rawKey===void 0&&oauth)return;let rawHeaders=configuredHeaders(config,extension),authHeader=extension?.authHeader??config?.authHeader??!1;return{name:inherited?.name??"API key",login:inherited?.login??(async interaction=>({type:"api_key",key:await interaction.prompt({type:"secret",message:"Enter API key"})})),check:async input=>{if(input.credential){if(inherited?.check)return inherited.check(input);if(input.credential.key)return{type:"api_key",source:"stored credential"};let resolved2=await inherited?.resolve(input);return resolved2?{type:"api_key",source:resolved2.source}:void 0}if(rawKey!==void 0){if(isCommandConfigValue(rawKey))return{type:"api_key",source:"configured API key"};let envNames=getConfigValueEnvVarNames(rawKey);for(let name of envNames)if(await input.ctx.env(name)===void 0)return;return{type:"api_key",source:"configured API key"}}if(inherited?.check)return inherited.check(input);let resolved=await inherited?.resolve(input);return resolved?{type:"api_key",source:resolved.source}:void 0},resolve:async input=>{let result;if(input.credential)result=inherited?await inherited.resolve(input):input.credential.key?{auth:{apiKey:input.credential.key},env:input.credential.env,source:"stored credential"}:void 0;else if(rawKey!==void 0){let env2=await configContextEnv([rawKey],input.ctx),key=resolveConfigValueOrThrow(rawKey,`API key for provider "${providerId}"`,env2);result=inherited?await inherited.resolve({...input,credential:{type:"api_key",key}}):{auth:{apiKey:key},source:"configured API key"}}else result=await inherited?.resolve(input);if(!result)return;let explicitEnv={...input.credential?.env??{},...result.env??{}},headerEnv=await configContextEnv(Object.values(rawHeaders??{}),input.ctx,explicitEnv),headers=resolveHeadersOrThrow(rawHeaders,`provider "${providerId}"`,headerEnv);return{...result,auth:withConfiguredAuth(result.auth,headers,authHeader)}}}}function composeOAuthAuth(providerId,base,config,extension){let oauth=extension?.oauth?adaptOAuth(extension.oauth):base?.auth.oauth;if(!oauth)return;let rawHeaders=configuredHeaders(config,extension),authHeader=extension?.authHeader??config?.authHeader??!1;return{...oauth,toAuth:async credential=>{let auth=await oauth.toAuth(credential),env2=credential.env,headers=resolveHeadersOrThrow(rawHeaders,`provider "${providerId}"`,typeof env2=="object"&&env2!==null?env2:void 0);return withConfiguredAuth(auth,headers,authHeader)}}}function rawModelHeaders(model2,config,extension){let definition=config?.models?.find(entry=>entry.id===model2.id),extensionModel=extension?.models?.find(entry=>entry.id===model2.id),headers={...config?.modelOverrides?.[model2.id]?.headers,...definition?.headers,...extensionModel?.headers};return Object.keys(headers).length>0?headers:void 0}function validateExtensionProvider(providerId,base,modelsConfig,extension){if(extension.streamSimple&&!extension.api)throw new Error(`Provider ${providerId}: "api" is required when registering streamSimple.`);applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],modelsConfig),extension)}function composeModelProvider(providerId,base,modelConfig,extension){let config=modelConfig.getProvider(providerId),extensionOAuthCredential,refreshedExtensionModels,currentExtension=()=>extension&&refreshedExtensionModels?{...extension,models:refreshedExtensionModels}:extension,getModels2=()=>{let models=applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],config),currentExtension());return extensionOAuthCredential&&extension?.oauth?.modifyModels&&(models=extension.oauth.modifyModels(models,extensionOAuthCredential)),models.map(model2=>{let override=config?.modelOverrides?.[model2.id];return override?applyModelOverride(model2,override):model2})};getModels2();let apiKey=composeApiKeyAuth(providerId,base,config,extension),oauth=composeOAuthAuth(providerId,base,config,extension);if(!apiKey&&!oauth)throw new Error(`Provider ${providerId}: no authentication method configured.`);let supportsBaseApi=model2=>base?.getModels().some(entry=>entry.api===model2.api)??!1,streamWith=(model2,context,options,simple)=>lazyStream(model2,async()=>{if(extension?.streamSimple&&model2.api===extension.api)return extension.streamSimple(model2,context,options);if(base&&supportsBaseApi(model2))return simple?base.streamSimple(model2,context,options):base.stream(model2,context,options);let api=getApiProvider(model2.api);if(!api)throw new Error(`No API provider registered for api: ${model2.api}`);return simple?api.streamSimple(model2,context,options):api.stream(model2,context,options)}),provider2={id:providerId,name:extension?.name??config?.name??base?.name??extension?.oauth?.name??providerId,baseUrl:extension?.baseUrl??config?.baseUrl??base?.baseUrl,headers:base?.headers,auth:{...apiKey?{apiKey}:{},...oauth?{oauth}:{}},getModels:getModels2,refreshModels:base?.refreshModels||extension?.refreshModels||extension?.oauth?.modifyModels?async context=>{await base?.refreshModels?.(context);let refreshed;if(extension?.refreshModels&&(refreshed=await extension.refreshModels(context)),context.signal.aborted)return;let oauthCredential=context.credential?.type==="oauth"?context.credential:void 0;await context.publish({update:()=>{refreshed&&(applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],config),{...extension,models:refreshed}),refreshedExtensionModels=refreshed),extensionOAuthCredential=oauthCredential}})}:void 0,filterModels:base?.filterModels?(models,credential)=>base.filterModels(models,credential):void 0,stream:(model2,context,options)=>streamWith(model2,context,options,!1),streamSimple:(model2,context,options)=>streamWith(model2,context,options,!0)},fetchDeferred=base?.fetchDeferred;fetchDeferred&&(provider2.fetchDeferred=(model2,handle,options)=>fetchDeferred(model2,handle,options));let cancelDeferred=base?.cancelDeferred;return cancelDeferred&&(provider2.cancelDeferred=(model2,handle,options)=>cancelDeferred(model2,handle,options)),provider2}function resolveConfiguredModelHeaders(model2,config,extension,env2){return resolveHeadersOrThrow(rawModelHeaders(model2,config,extension),`model "${model2.provider}/${model2.id}"`,env2)}function resolveCompatibilityRequestConfig(model2,config,extension){let configured=resolveHeadersOrThrow({...configuredHeaders(config,extension),...rawModelHeaders(model2,config,extension)},`model "${model2.provider}/${model2.id}"`);return{headers:model2.headers||configured?{...model2.headers,...configured}:void 0,authHeader:extension?.authHeader??config?.authHeader??!1}}function configuredRequestAuthStatus(config,extension){let value=configuredApiKey(config,extension);if(value===void 0)return;if(isCommandConfigValue(value))return{configured:!0,source:"models_json_command"};let names2=getConfigValueEnvVarNames(value);return names2.length>0?isConfigValueConfigured(value)?{configured:!0,source:"environment",label:names2.join(", ")}:{configured:!1}:{configured:!0,source:extension?.apiKey!==void 0?"fallback":"models_json_key"}}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider2,modelId){return this.runtime.getModel(provider2,modelId)}hasConfiguredAuth(model2){return this.runtime.hasConfiguredAuth(model2.provider)}async getApiKeyAndHeaders(model2){try{let resolution=await this.runtime.getAuth(model2);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model2);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model2.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 "${model2.provider}"`:message}}}getProviderAuthStatus(provider2){return this.runtime.getProviderAuthStatus(provider2)}getProvider(provider2){return this.runtime.getProvider(provider2)}complete(model2,context,options){return this.runtime.complete(model2,context,options)}getProviderDisplayName(provider2){return this.runtime.getProvider(provider2)?.name??provider2}getProviderAuth(provider2){return this.runtime.getAuth(provider2)}async getApiKeyForProvider(provider2){try{return(await this.runtime.getAuth(provider2))?.auth.apiKey}catch{return}}isUsingOAuth(model2){return this.runtime.isUsingOAuth(model2.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()}};import{existsSync as existsSync7,readdirSync as readdirSync5,readFileSync as readFileSync5,statSync as statSync6}from"fs";import{basename as basename4,dirname as dirname7,join as join17,resolve as resolve4,sep as sep3}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 value=defaultTarget==="@"||defaultTarget==="ARGUMENTS"?allArgs:args[parseInt(defaultTarget,10)-1];return value||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){try{let rawContent=readFileSync5(filePath,"utf-8"),{frontmatter,body}=parseFrontmatter(rawContent),name=basename4(filePath).replace(/\.md$/,""),description=frontmatter.description||"";if(!description){let firstLine=body.split(`
1081
+ `)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var VIRTUAL_MODULES={typebox:build_exports,"typebox/compile":compile_exports,"typebox/value":value_exports2,"@sinclair/typebox":build_exports,"@sinclair/typebox/compile":compile_exports,"@sinclair/typebox/value":value_exports2,"@earendil-works/pi-agent-core":dist_exports2,"@earendil-works/pi-tui":dist_exports,"@earendil-works/pi-ai":compat_exports,"@earendil-works/pi-ai/compat":compat_exports,"@earendil-works/pi-ai/oauth":oauth_exports,"@earendil-works/pi-ai/providers/all":all_exports,"@earendil-works/pi-coding-agent":dist_exports3,"@mariozechner/pi-agent-core":dist_exports2,"@mariozechner/pi-tui":dist_exports,"@mariozechner/pi-ai":compat_exports,"@mariozechner/pi-ai/compat":compat_exports,"@mariozechner/pi-ai/oauth":oauth_exports,"@mariozechner/pi-ai/providers/all":all_exports,"@mariozechner/pi-coding-agent":dist_exports3},require4=createRequire6(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isBundledNode=!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",_aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require4.resolve("typebox"),typeboxCompileEntry=require4.resolve("typebox/compile"),typeboxValueEntry=require4.resolve("typebox/value"),packagesRoot=path7.resolve(__dirname2,"../../../../"),resolveWorkspaceOrImport=(workspaceRelativePath,specifier)=>{let workspacePath=path7.join(packagesRoot,workspaceRelativePath);return fs5.existsSync(workspacePath)?workspacePath:fileURLToPath5(import.meta.resolve(specifier))},piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveWorkspaceOrImport("agent/dist/index.js","@earendil-works/pi-agent-core"),piTuiEntry=resolveWorkspaceOrImport("tui/dist/index.js","@earendil-works/pi-tui"),piAiCompatEntry=resolveWorkspaceOrImport("ai/dist/compat.js","@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveWorkspaceOrImport("ai/dist/oauth.js","@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveWorkspaceOrImport("ai/dist/providers/all.js","@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":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:(provider2,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider:provider2,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 list=extension.handlers.get(event)??[];list.push(handler),extension.handlers.set(event,list)},registerTool(tool){assertActive(),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(model2){return assertActive(),runtime.setModel(model2)},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,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);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 factory=await createJiti(import.meta.url,{moduleCache:!1,...isBunBinary||isNodeSeaBinary||isBundledNode?{virtualModules:VIRTUAL_MODULES,tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:VIRTUAL_MODULES,tsconfigPaths:!0}:{alias:getAliases()}}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source2=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:source2,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 resolveExtensionEntries(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=resolveExtensionEntries(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=resolveExtensionEntries(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS=["app.interrupt","app.clear","app.exit","app.suspend","app.thinking.cycle","app.model.cycleForward","app.model.cycleBackward","app.model.select","app.tools.expand","app.thinking.toggle","app.editor.external","app.message.copy","app.message.followUp","tui.input.submit","tui.select.confirm","tui.select.cancel","tui.input.copy","tui.editor.deleteToLineEnd"],buildBuiltinKeybindings=resolvedKeybindings=>{let builtinKeybindings={};for(let[keybinding,keys]of Object.entries(resolvedKeybindings)){if(keys===void 0)continue;let keyList=Array.isArray(keys)?keys:[keys],restrictOverride=RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS.includes(keybinding);for(let key of keyList){let normalizedKey=key.toLowerCase();builtinKeybindings[normalizedKey]?.restrictOverride&&!restrictOverride||(builtinKeybindings[normalizedKey]={keybinding,restrictOverride})}}return builtinKeybindings};async function emitSessionShutdownEvent(extensionRunner,event){return extensionRunner.hasHandlers("session_shutdown")?(await extensionRunner.emit(event),!0):!1}async function emitProjectTrustEvent(extensionsResult,event,ctx){let errors=[];for(let ext2 of extensionsResult.extensions){let handlers=ext2.handlers.get("project_trust");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult.trusted==="undecided")continue;return{result:handlerResult,errors}}catch(error){errors.push({extensionPath:ext2.path,event:event.type,error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:void 0})}}return{errors}}var noOpUIContext={select:async()=>{},confirm:async()=>!1,input:async()=>{},notify:()=>{},onTerminalInput:()=>()=>{},setStatus:()=>{},setWorkingMessage:()=>{},setWorkingVisible:()=>{},setWorkingIndicator:()=>{},setHiddenThinkingLabel:()=>{},setWidget:()=>{},setFooter:()=>{},setHeader:()=>{},setTitle:()=>{},custom:async()=>{},pasteToEditor:()=>{},setEditorText:()=>{},getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:()=>{},setEditorComponent:()=>{},getEditorComponent:()=>{},get theme(){return theme},getAllThemes:()=>[],getTheme:()=>{},setTheme:_theme=>({success:!1,error:"UI not available"}),getToolsExpanded:()=>!1,setToolsExpanded:()=>{}},ExtensionRunner=class{constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.mode="print",this.errorListeners=new Set,this.getModel=()=>{},this.getScopedModels=()=>[],this.isIdleFn=()=>!0,this.isProjectTrustedFn=()=>!0,this.getSignalFn=()=>{},this.waitForIdleFn=async()=>{},this.abortFn=()=>{},this.hasPendingMessagesFn=()=>!1,this.getContextUsageFn=()=>{},this.compactFn=()=>{},this.getSystemPromptFn=()=>"",this.getSystemPromptOptionsFn=()=>({cwd:this.cwd}),this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{},this.shutdownHandler=()=>{},this.shortcutDiagnostics=[],this.commandDiagnostics=[],this.uiPromptDepth=0,this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions,contextActions,providerActions){this.runtime.sendMessage=actions.sendMessage,this.runtime.sendUserMessage=actions.sendUserMessage,this.runtime.appendEntry=actions.appendEntry,this.runtime.setSessionName=actions.setSessionName,this.runtime.getSessionName=actions.getSessionName,this.runtime.setLabel=actions.setLabel,this.runtime.getActiveTools=actions.getActiveTools,this.runtime.getAllTools=actions.getAllTools,this.runtime.setActiveTools=actions.setActiveTools,this.runtime.refreshTools=actions.refreshTools,this.runtime.getCommands=actions.getCommands,this.runtime.setModel=actions.setModel,this.runtime.getThinkingLevel=actions.getThinkingLevel,this.runtime.setThinkingLevel=actions.setThinkingLevel,this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>({cwd:this.cwd}));for(let{name,config,extensionPath}of this.runtime.pendingProviderRegistrations)try{providerActions?.registerProvider?providerActions.registerProvider(name,config):this.modelRegistry.registerProvider(name,config)}catch(err2){this.emitError({extensionPath,event:"register_provider",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}this.runtime.pendingProviderRegistrations=[];for(let{provider:provider2,extensionPath}of this.runtime.pendingNativeProviderRegistrations)try{providerActions?.registerNativeProvider?providerActions.registerNativeProvider(provider2):this.modelRegistry.registerProvider(provider2)}catch(err2){this.emitError({extensionPath,event:"register_provider",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}this.runtime.pendingNativeProviderRegistrations=[],this.runtime.registerProvider=(name,config)=>{if(providerActions?.registerProvider){providerActions.registerProvider(name,config);return}this.modelRegistry.registerProvider(name,config)},this.runtime.registerNativeProvider=provider2=>{if(providerActions?.registerNativeProvider){providerActions.registerNativeProvider(provider2);return}this.modelRegistry.registerProvider(provider2)},this.runtime.unregisterProvider=name=>{if(providerActions?.unregisterProvider){providerActions.unregisterProvider(name);return}this.modelRegistry.unregisterProvider(name)}}bindCommandContext(actions){if(actions){this.waitForIdleFn=actions.waitForIdle,this.newSessionHandler=actions.newSession,this.forkHandler=actions.fork,this.navigateTreeHandler=actions.navigateTree,this.switchSessionHandler=actions.switchSession,this.reloadHandler=actions.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(err2){throw finish(),err2}}emitUIPromptEvent(event){queueMicrotask(()=>{this.emit(event)})}getUIContext(){return this.uiContext}hasUI(){return this.uiContext!==noOpUIContext}getExtensionPaths(){return this.extensions.map(e=>e.path)}getAllRegisteredTools(){let toolsByName=new Map;for(let ext2 of this.extensions)for(let tool of ext2.tools.values())toolsByName.has(tool.definition.name)||toolsByName.set(tool.definition.name,tool);return Array.from(toolsByName.values())}getToolDefinition(toolName){for(let ext2 of this.extensions){let tool=ext2.tools.get(toolName);if(tool)return tool.definition}}getFlags(){let allFlags=new Map;for(let ext2 of this.extensions)for(let[name,flag]of ext2.flags)allFlags.has(name)||allFlags.set(name,flag);return allFlags}setFlagValue(name,value){this.runtime.flagValues.set(name,value)}getFlagValues(){return new Map(this.runtime.flagValues)}getShortcuts(resolvedKeybindings){this.shortcutDiagnostics=[];let builtinKeybindings=buildBuiltinKeybindings(resolvedKeybindings),extensionShortcuts=new Map,addDiagnostic=(message,extensionPath)=>{this.shortcutDiagnostics.push({type:"warning",message,path:extensionPath}),this.hasUI()||console.warn(message)};for(let ext2 of this.extensions)for(let[key,shortcut]of ext2.shortcuts){let normalizedKey=key.toLowerCase(),builtInKeybinding=builtinKeybindings[normalizedKey];if(builtInKeybinding?.restrictOverride===!0){addDiagnostic(`Extension shortcut '${key}' from ${shortcut.extensionPath} conflicts with built-in shortcut. Skipping.`,shortcut.extensionPath);continue}builtInKeybinding?.restrictOverride===!1&&addDiagnostic(`Extension shortcut conflict: '${key}' is built-in shortcut for ${builtInKeybinding.keybinding} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath);let existingExtensionShortcut=extensionShortcuts.get(normalizedKey);existingExtensionShortcut&&addDiagnostic(`Extension shortcut conflict: '${key}' registered by both ${existingExtensionShortcut.extensionPath} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath),extensionShortcuts.set(normalizedKey,shortcut)}return extensionShortcuts}getShortcutDiagnostics(){return this.shortcutDiagnostics}invalidate(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()."){this.staleMessage||(this.staleMessage=message,this.runtime.invalidate(message))}assertActive(){if(this.staleMessage)throw new Error(this.staleMessage)}onError(listener){return this.errorListeners.add(listener),()=>this.errorListeners.delete(listener)}emitError(error){for(let listener of this.errorListeners)listener(error)}hasHandlers(eventType){for(let ext2 of this.extensions){let handlers=ext2.handlers.get(eventType);if(handlers&&handlers.length>0)return!0}return!1}getMessageRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.messageRenderers.get(customType);if(renderer)return renderer}}getMarkdownTransformers(){return this.extensions.flatMap(ext2=>ext2.markdownTransformer?[ext2.markdownTransformer]:[])}getEntryRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.entryRenderers?.get(customType);if(renderer)return renderer}}resolveRegisteredCommands(){let commands=[],counts=new Map;for(let ext2 of this.extensions)for(let command of ext2.commands.values())commands.push(command),counts.set(command.name,(counts.get(command.name)??0)+1);let seen=new Map,takenInvocationNames=new Set;return commands.map(command=>{let occurrence=(seen.get(command.name)??0)+1;seen.set(command.name,occurrence);let invocationName=(counts.get(command.name)??0)>1?`${command.name}:${occurrence}`:command.name;if(takenInvocationNames.has(invocationName)){let suffix=occurrence;do suffix++,invocationName=`${command.name}:${suffix}`;while(takenInvocationNames.has(invocationName))}return takenInvocationNames.add(invocationName),{...command,invocationName}})}getModelRegistry(){return this.modelRegistry}getRegisteredCommands(){return this.commandDiagnostics=[],this.resolveRegisteredCommands()}getCommandDiagnostics(){return this.commandDiagnostics}getCommand(name){return this.resolveRegisteredCommands().find(command=>command.invocationName===name)}shutdown(){this.shutdownHandler()}getActiveTools(){return this.assertActive(),this.runtime.getActiveTools()}createContext(){let runner=this,getModel2=this.getModel,getScopedModels=this.getScopedModels;return{get ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}createCommandContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));return context.getSystemPromptOptions=()=>(this.assertActive(),this.getSystemPromptOptionsFn()),context.waitForIdle=()=>(this.assertActive(),this.waitForIdleFn()),context.newSession=options=>(this.assertActive(),this.newSessionHandler(options)),context.fork=(entryId,options)=>(this.assertActive(),this.forkHandler(entryId,options)),context.navigateTree=(targetId,options)=>(this.assertActive(),this.navigateTreeHandler(targetId,options)),context.switchSession=(sessionPath,options)=>(this.assertActive(),this.switchSessionHandler(sessionPath,options)),context.reload=()=>(this.assertActive(),this.reloadHandler()),context}isSessionBeforeEvent(event){return event.type==="session_before_switch"||event.type==="session_before_fork"||event.type==="session_before_compact"||event.type==="session_before_tree"}async emit(event){let ctx=this.createContext(),result;for(let ext2 of this.extensions){let handlers=ext2.handlers.get(event.type);if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(this.isSessionBeforeEvent(event)&&handlerResult&&(result=handlerResult,result.cancel))return result}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:event.type,error:message,stack})}}return result}async emitMessageEnd(event){let ctx=this.createContext(),currentMessage=event.message,modified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("message_end");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let currentEvent={...event,message:currentMessage},handlerResult=await handler(currentEvent,ctx);if(!handlerResult?.message)continue;if(handlerResult.message.role!==currentMessage.role){this.emitError({extensionPath:ext2.path,event:"message_end",error:"message_end handlers must return a message with the same role"});continue}currentMessage=handlerResult.message,modified=!0}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"message_end",error:message,stack})}}return modified?currentMessage:void 0}async emitToolResult(event){let ctx=this.createContext(),currentEvent={...event},modified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("tool_result");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(currentEvent,ctx);if(!handlerResult)continue;handlerResult.content!==void 0&&(currentEvent.content=handlerResult.content,modified=!0),handlerResult.details!==void 0&&(currentEvent.details=handlerResult.details,modified=!0),handlerResult.isError!==void 0&&(currentEvent.isError=handlerResult.isError,modified=!0),handlerResult.usage!==void 0&&(currentEvent.usage=handlerResult.usage,modified=!0)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"tool_result",error:message,stack})}}if(modified)return{content:currentEvent.content,details:currentEvent.details,isError:currentEvent.isError,usage:currentEvent.usage}}async emitToolCall(event){let ctx=this.createContext(),result;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("tool_call");if(!(!handlers||handlers.length===0))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result=handlerResult,result.block))return result}}return result}async emitUserBash(event){let ctx=this.createContext();for(let ext2 of this.extensions){let handlers=ext2.handlers.get("user_bash");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult)return handlerResult}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"user_bash",error:message,stack})}}}async emitContext(messages){let ctx=this.createContext(),currentMessages=structuredClone(messages);for(let ext2 of this.extensions){let handlers=ext2.handlers.get("context");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"context",messages:currentMessages},ctx);handlerResult&&handlerResult.messages&&(currentMessages=handlerResult.messages)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context",error:message,stack})}}return currentMessages}async emitBeforeProviderRequest(payload){let ctx=this.createContext(),currentPayload=payload;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_provider_request");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"before_provider_request",payload:currentPayload},ctx);handlerResult!==void 0&&(currentPayload=handlerResult)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_request",error:message,stack})}}return currentPayload}async emitBeforeProviderHeaders(headers,requestId){let ctx=this.createContext();for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_provider_headers");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{await handler({type:"before_provider_headers",headers,requestId},ctx)}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_headers",error:message,stack})}}return headers}async emitBeforeAgentStart(prompt,images,systemPrompt,systemPromptOptions){let currentSystemPrompt=systemPrompt,ctx=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));ctx.getSystemPrompt=()=>(this.assertActive(),currentSystemPrompt);let messages=[],systemPromptModified=!1;for(let ext2 of this.extensions){let handlers=ext2.handlers.get("before_agent_start");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let handlerResult=await handler({type:"before_agent_start",prompt,images,systemPrompt:currentSystemPrompt,systemPromptOptions},ctx);if(handlerResult){let result=handlerResult;result.message&&messages.push(result.message),result.systemPrompt!==void 0&&(currentSystemPrompt=result.systemPrompt,systemPromptModified=!0)}}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_agent_start",error:message,stack})}}if(messages.length>0||systemPromptModified)return{messages:messages.length>0?messages:void 0,systemPrompt:systemPromptModified?currentSystemPrompt:void 0}}async emitResourcesDiscover(cwd,reason){let ctx=this.createContext(),skillPaths=[],promptPaths=[],themePaths=[];for(let ext2 of this.extensions){let handlers=ext2.handlers.get("resources_discover");if(!(!handlers||handlers.length===0))for(let handler of handlers)try{let result=await handler({type:"resources_discover",cwd,reason},ctx);result?.skillPaths?.length&&skillPaths.push(...result.skillPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result?.promptPaths?.length&&promptPaths.push(...result.promptPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result?.themePaths?.length&&themePaths.push(...result.themePaths.map(path14=>({path:path14,extensionPath:ext2.path})))}catch(err2){let message=err2 instanceof Error?err2.message:String(err2),stack=err2 instanceof Error?err2.stack:void 0;this.emitError({extensionPath:ext2.path,event:"resources_discover",error:message,stack})}}return{skillPaths,promptPaths,themePaths}}async emitInput(text,images,source2,streamingBehavior){let ctx=this.createContext(),currentText=text,currentImages=images;for(let ext2 of this.extensions)for(let handler of ext2.handlers.get("input")??[])try{let result=await handler({type:"input",text:currentText,images:currentImages,source:source2,streamingBehavior},ctx);if(result?.action==="handled")return result;result?.action==="transform"&&(currentText=result.text,currentImages=result.images??currentImages)}catch(err2){this.emitError({extensionPath:ext2.path,event:"input",error:err2 instanceof Error?err2.message:String(err2),stack:err2 instanceof Error?err2.stack:void 0})}return currentText!==text||currentImages!==images?{action:"transform",text:currentText,images:currentImages}:{action:"continue"}}};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}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,constrainedSampling:definition.constrainedSampling,prepareArguments:definition.prepareArguments,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){let tool=wrapToolDefinition(registeredTool.definition,()=>runner.createContext()),execute=tool.execute;return{...tool,execute:async(toolCallId,params,signal,onUpdate)=>{let activeBefore=runner.getActiveTools(),result=await execute(toolCallId,params,signal,onUpdate),activeAfter=runner.getActiveTools();if(!activeBefore.every(name=>activeAfter.includes(name)))return result;let beforeNames=new Set(activeBefore),addedToolNames=activeAfter.filter(name=>!beforeNames.has(name));return addedToolNames.length===0?result:{...result,addedToolNames:[...new Set([...result.addedToolNames??[],...addedToolNames])]}}}}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import{execSync as execSync2,spawnSync as spawnSync2}from"child_process";var commandResultCache=new Map,ENV_VAR_NAME_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,ENV_VAR_NAME_PREFIX_RE=/^[A-Za-z_][A-Za-z0-9_]*/;function appendLiteral(parts,value){if(!value)return;let previousPart=parts[parts.length-1];if(previousPart?.type==="literal"){previousPart.value+=value;return}parts.push({type:"literal",value})}function parseConfigValueTemplate(config){let parts=[],index3=0;for(;index3<config.length;){let dollarIndex=config.indexOf("$",index3);if(dollarIndex<0){appendLiteral(parts,config.slice(index3));break}appendLiteral(parts,config.slice(index3,dollarIndex));let nextChar=config[dollarIndex+1];if(nextChar==="$"||nextChar==="!"){appendLiteral(parts,nextChar),index3=dollarIndex+2;continue}if(nextChar==="{"){let endIndex=config.indexOf("}",dollarIndex+2);if(endIndex<0){appendLiteral(parts,"$"),index3=dollarIndex+1;continue}let name=config.slice(dollarIndex+2,endIndex);ENV_VAR_NAME_RE.test(name)?parts.push({type:"env",name}):appendLiteral(parts,config.slice(dollarIndex,endIndex+1)),index3=endIndex+1;continue}let match2=config.slice(dollarIndex+1).match(ENV_VAR_NAME_PREFIX_RE);if(match2){parts.push({type:"env",name:match2[0]}),index3=dollarIndex+1+match2[0].length;continue}appendLiteral(parts,"$"),index3=dollarIndex+1}return parts}function parseConfigValueReference(config){return config.startsWith("!")?{type:"command",config}:{type:"template",parts:parseConfigValueTemplate(config)}}function resolveEnvConfigValue(name,env2){return env2?.[name]||process.env[name]||void 0}function getTemplateEnvVarNames(parts){let names2=[];for(let part of parts)part.type!=="env"||names2.includes(part.name)||names2.push(part.name);return names2}function resolveTemplate(parts,env2){let resolved="";for(let part of parts){if(part.type==="literal"){resolved+=part.value;continue}let envValue=resolveEnvConfigValue(part.name,env2);if(envValue===void 0)return;resolved+=envValue}return resolved}function getConfigValueEnvVarNames(config){let reference=parseConfigValueReference(config);return reference.type==="template"?getTemplateEnvVarNames(reference.parts):[]}function getMissingConfigValueEnvVarNames(config,env2){return getConfigValueEnvVarNames(config).filter(name=>resolveEnvConfigValue(name,env2)===void 0)}function isCommandConfigValue(config){return parseConfigValueReference(config).type==="command"}function isConfigValueConfigured(config,env2){return getMissingConfigValueEnvVarNames(config,env2).length===0}function resolveConfigValue(config,env2){let reference=parseConfigValueReference(config);return reference.type==="command"?executeCommand(reference.config):resolveTemplate(reference.parts,env2)}function executeWithConfiguredShell(command){try{let{shell,args,commandTransport}=getShellConfig(),commandFromStdin=commandTransport==="stdin",result=spawnSync2(shell,commandFromStdin?args:[...args,command],{encoding:"utf-8",input:commandFromStdin?command:void 0,timeout:1e4,stdio:[commandFromStdin?"pipe":"ignore","pipe","ignore"],shell:!1,windowsHide:!0});return result.error?result.error.code==="ENOENT"?{executed:!1,value:void 0}:{executed:!0,value:void 0}:result.status!==0?{executed:!0,value:void 0}:{executed:!0,value:(result.stdout??"").trim()||void 0}}catch{return{executed:!1,value:void 0}}}function executeWithDefaultShell(command){try{return execSync2(command,{encoding:"utf-8",timeout:1e4,stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{return}}function executeCommandUncached(commandConfig){let command=commandConfig.slice(1);return process.platform==="win32"?(()=>{let configuredResult=executeWithConfiguredShell(command);return configuredResult.executed?configuredResult.value:executeWithDefaultShell(command)})():executeWithDefaultShell(command)}function executeCommand(commandConfig){if(commandResultCache.has(commandConfig))return commandResultCache.get(commandConfig);let result=executeCommandUncached(commandConfig);return commandResultCache.set(commandConfig,result),result}function resolveConfigValueUncached(config,env2){let reference=parseConfigValueReference(config);return reference.type==="command"?executeCommandUncached(reference.config):resolveTemplate(reference.parts,env2)}function resolveConfigValueOrThrow(config,description,env2){let resolvedValue=resolveConfigValueUncached(config,env2);if(resolvedValue!==void 0)return resolvedValue;let reference=parseConfigValueReference(config);if(reference.type==="command")throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);if(reference.type==="template"){let missingEnvVars=getMissingConfigValueEnvVarNames(config,env2);if(missingEnvVars.length===1)throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);if(missingEnvVars.length>1)throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`)}throw new Error(`Failed to resolve ${description}`)}function resolveHeadersOrThrow(headers,description,env2){if(!headers)return;let resolved={};for(let[key,value]of Object.entries(headers))resolved[key]=resolveConfigValueOrThrow(value,`${description} header "${key}"`,env2);return Object.keys(resolved).length>0?resolved:void 0}function mergeCompat(base,override){if(!override)return base;let merged={...base,...override},baseNested=base,overrideNested=override,mergedNested=merged;for(let key of["openRouterRouting","vercelGatewayRouting","chatTemplateKwargs","chatTemplateArgs"]){let baseValue=baseNested?.[key],overrideValue=overrideNested[key];(typeof baseValue=="object"&&baseValue!==null||typeof overrideValue=="object"&&overrideValue!==null)&&(mergedNested[key]={...baseValue,...overrideValue})}return merged}function applyModelOverride(model2,override){return{...model2,name:override.name??model2.name,reasoning:override.reasoning??model2.reasoning,thinkingLevelMap:override.thinkingLevelMap?{...model2.thinkingLevelMap,...override.thinkingLevelMap}:model2.thinkingLevelMap,input:override.input??model2.input,cost:override.cost?{input:override.cost.input??model2.cost.input,output:override.cost.output??model2.cost.output,cacheRead:override.cost.cacheRead??model2.cost.cacheRead,cacheWrite:override.cost.cacheWrite??model2.cost.cacheWrite,tiers:override.cost.tiers??model2.cost.tiers}:model2.cost,contextWindow:override.contextWindow??model2.contextWindow,maxTokens:override.maxTokens??model2.maxTokens,samplingParams:override.samplingParams?{...model2.samplingParams,...override.samplingParams}:model2.samplingParams,compat:mergeCompat(model2.compat,override.compat)}}function modelFromJson(providerId,definition,providerConfig,defaults2){let api=definition.api??providerConfig.api??defaults2?.api;if(!api)throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);let baseUrl=definition.baseUrl??providerConfig.baseUrl??defaults2?.baseUrl;if(!baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);if(definition.contextWindow!==void 0&&definition.contextWindow<=0)throw new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);if(definition.maxTokens!==void 0&&definition.maxTokens<=0)throw new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);return{id:definition.id,name:definition.name??definition.id,api,provider:providerId,baseUrl,reasoning:definition.reasoning??!1,thinkingLevelMap:definition.thinkingLevelMap,input:definition.input??["text"],cost:definition.cost??{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:definition.contextWindow??128e3,maxTokens:definition.maxTokens??16384,samplingParams:definition.samplingParams,headers:void 0,compat:mergeCompat(providerConfig.compat,definition.compat)}}function applyModelsJson(providerId,baseModels,config){if(!config)return[...baseModels];if(config.oauth&&!config.baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when "oauth" is set.`);let hasOverrides=config.modelOverrides&&Object.keys(config.modelOverrides).length>0;if(!config.models?.length&&!config.baseUrl&&!config.headers&&!config.compat&&!hasOverrides&&!config.apiKey&&!config.oauth&&config.authHeader===void 0)throw new Error(`Provider ${providerId}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);let models=baseModels.map(model2=>({...model2,baseUrl:config.oauth==="radius"?model2.baseUrl:config.baseUrl??model2.baseUrl,compat:mergeCompat(model2.compat,config.compat)}));for(let definition of config.models??[]){let existingIndex=models.findIndex(model3=>model3.id===definition.id),defaults2=existingIndex>=0?models[existingIndex]:models[0],model2=modelFromJson(providerId,definition,config,defaults2);existingIndex>=0?models[existingIndex]=model2:models.push(model2)}return models}function applyExtension(providerId,models,config){return config?config.models?config.models.map(definition=>{let defaults2=models.find(model2=>model2.id===definition.id)??models[0],api=definition.api??config.api??defaults2?.api;if(!api)throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);let baseUrl=definition.baseUrl??config.baseUrl??defaults2?.baseUrl;if(!baseUrl)throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);return{...definition,api,provider:providerId,baseUrl,headers:void 0}}):config.baseUrl?models.map(model2=>({...model2,baseUrl:config.baseUrl})):[...models]:[...models]}function adaptOAuth(config){return{name:config.name,isSubscription:config.isSubscription,login:async callbacks=>({...await config.login({onAuth:info=>callbacks.notify({type:"auth_url",...info}),onDeviceCode:info=>callbacks.notify({type:"device_code",...info}),onPrompt:prompt=>callbacks.prompt({type:"text",...prompt}),onProgress:message=>callbacks.notify({type:"progress",message}),onManualCodeInput:()=>callbacks.prompt({type:"manual_code",message:"Paste the authorization code"}),onSelect:prompt=>callbacks.prompt({type:"select",...prompt}),signal:callbacks.signal}),type:"oauth"}),refresh:async(credential,signal)=>({...await config.refreshToken(credential,signal),type:"oauth"}),toAuth:async credential=>({apiKey:config.getApiKey(credential)})}}function withConfiguredAuth(auth,headers,authHeader){let mergedHeaders=auth.headers||headers?{...auth.headers,...headers}:void 0;if(authHeader){if(!auth.apiKey)throw new Error("authHeader requires a resolved API key");mergedHeaders={...mergedHeaders,Authorization:`Bearer ${auth.apiKey}`}}return{...auth,headers:mergedHeaders}}function configuredApiKey(config,extension){return extension?.apiKey??config?.apiKey}function configuredHeaders(config,extension){if(!(!config?.headers&&!extension?.headers))return{...config?.headers,...extension?.headers}}async function configContextEnv(values,ctx,explicit){let env2={...explicit};for(let name of new Set(values.flatMap(getConfigValueEnvVarNames))){if(env2[name]!==void 0)continue;let value=await ctx.env(name);value!==void 0&&(env2[name]=value)}return Object.keys(env2).length>0?env2:void 0}function composeApiKeyAuth(providerId,base,config,extension){let inherited=base?.auth.apiKey,rawKey=configuredApiKey(config,extension),oauth=extension?.oauth??base?.auth.oauth;if(!inherited&&rawKey===void 0&&oauth)return;let rawHeaders=configuredHeaders(config,extension),authHeader=extension?.authHeader??config?.authHeader??!1;return{name:inherited?.name??"API key",login:inherited?.login??(async interaction=>({type:"api_key",key:await interaction.prompt({type:"secret",message:"Enter API key"})})),check:async input=>{if(input.credential){if(inherited?.check)return inherited.check(input);if(input.credential.key)return{type:"api_key",source:"stored credential"};let resolved2=await inherited?.resolve(input);return resolved2?{type:"api_key",source:resolved2.source}:void 0}if(rawKey!==void 0){if(isCommandConfigValue(rawKey))return{type:"api_key",source:"configured API key"};let envNames=getConfigValueEnvVarNames(rawKey);for(let name of envNames)if(await input.ctx.env(name)===void 0)return;return{type:"api_key",source:"configured API key"}}if(inherited?.check)return inherited.check(input);let resolved=await inherited?.resolve(input);return resolved?{type:"api_key",source:resolved.source}:void 0},resolve:async input=>{let result;if(input.credential)result=inherited?await inherited.resolve(input):input.credential.key?{auth:{apiKey:input.credential.key},env:input.credential.env,source:"stored credential"}:void 0;else if(rawKey!==void 0){let env2=await configContextEnv([rawKey],input.ctx),key=resolveConfigValueOrThrow(rawKey,`API key for provider "${providerId}"`,env2);result=inherited?await inherited.resolve({...input,credential:{type:"api_key",key}}):{auth:{apiKey:key},source:"configured API key"}}else result=await inherited?.resolve(input);if(!result)return;let explicitEnv={...input.credential?.env??{},...result.env??{}},headerEnv=await configContextEnv(Object.values(rawHeaders??{}),input.ctx,explicitEnv),headers=resolveHeadersOrThrow(rawHeaders,`provider "${providerId}"`,headerEnv);return{...result,auth:withConfiguredAuth(result.auth,headers,authHeader)}}}}function composeOAuthAuth(providerId,base,config,extension){let oauth=extension?.oauth?adaptOAuth(extension.oauth):base?.auth.oauth;if(!oauth)return;let rawHeaders=configuredHeaders(config,extension),authHeader=extension?.authHeader??config?.authHeader??!1;return{...oauth,toAuth:async credential=>{let auth=await oauth.toAuth(credential),env2=credential.env,headers=resolveHeadersOrThrow(rawHeaders,`provider "${providerId}"`,typeof env2=="object"&&env2!==null?env2:void 0);return withConfiguredAuth(auth,headers,authHeader)}}}function rawModelHeaders(model2,config,extension){let definition=config?.models?.find(entry=>entry.id===model2.id),extensionModel=extension?.models?.find(entry=>entry.id===model2.id),headers={...config?.modelOverrides?.[model2.id]?.headers,...definition?.headers,...extensionModel?.headers};return Object.keys(headers).length>0?headers:void 0}function validateExtensionProvider(providerId,base,modelsConfig,extension){if(extension.streamSimple&&!extension.api)throw new Error(`Provider ${providerId}: "api" is required when registering streamSimple.`);applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],modelsConfig),extension)}function composeModelProvider(providerId,base,modelConfig,extension){let config=modelConfig.getProvider(providerId),extensionOAuthCredential,refreshedExtensionModels,currentExtension=()=>extension&&refreshedExtensionModels?{...extension,models:refreshedExtensionModels}:extension,getModels2=()=>{let models=applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],config),currentExtension());return extensionOAuthCredential&&extension?.oauth?.modifyModels&&(models=extension.oauth.modifyModels(models,extensionOAuthCredential)),models.map(model2=>{let override=config?.modelOverrides?.[model2.id];return override?applyModelOverride(model2,override):model2})};getModels2();let apiKey=composeApiKeyAuth(providerId,base,config,extension),oauth=composeOAuthAuth(providerId,base,config,extension);if(!apiKey&&!oauth)throw new Error(`Provider ${providerId}: no authentication method configured.`);let supportsBaseApi=model2=>base?.getModels().some(entry=>entry.api===model2.api)??!1,streamWith=(model2,context,options,simple)=>lazyStream(model2,async()=>{if(extension?.streamSimple&&model2.api===extension.api)return extension.streamSimple(model2,context,options);if(base&&supportsBaseApi(model2))return simple?base.streamSimple(model2,context,options):base.stream(model2,context,options);let api=getApiProvider(model2.api);if(!api)throw new Error(`No API provider registered for api: ${model2.api}`);return simple?api.streamSimple(model2,context,options):api.stream(model2,context,options)}),provider2={id:providerId,name:extension?.name??config?.name??base?.name??extension?.oauth?.name??providerId,baseUrl:extension?.baseUrl??config?.baseUrl??base?.baseUrl,headers:base?.headers,auth:{...apiKey?{apiKey}:{},...oauth?{oauth}:{}},getModels:getModels2,refreshModels:base?.refreshModels||extension?.refreshModels||extension?.oauth?.modifyModels?async context=>{await base?.refreshModels?.(context);let refreshed;if(extension?.refreshModels&&(refreshed=await extension.refreshModels(context)),context.signal.aborted)return;let oauthCredential=context.credential?.type==="oauth"?context.credential:void 0;await context.publish({update:()=>{refreshed&&(applyExtension(providerId,applyModelsJson(providerId,base?.getModels()??[],config),{...extension,models:refreshed}),refreshedExtensionModels=refreshed),extensionOAuthCredential=oauthCredential}})}:void 0,filterModels:base?.filterModels?(models,credential)=>base.filterModels(models,credential):void 0,stream:(model2,context,options)=>streamWith(model2,context,options,!1),streamSimple:(model2,context,options)=>streamWith(model2,context,options,!0)},fetchDeferred=base?.fetchDeferred;fetchDeferred&&(provider2.fetchDeferred=(model2,handle,options)=>fetchDeferred(model2,handle,options));let cancelDeferred=base?.cancelDeferred;return cancelDeferred&&(provider2.cancelDeferred=(model2,handle,options)=>cancelDeferred(model2,handle,options)),provider2}function resolveConfiguredModelHeaders(model2,config,extension,env2){return resolveHeadersOrThrow(rawModelHeaders(model2,config,extension),`model "${model2.provider}/${model2.id}"`,env2)}function resolveCompatibilityRequestConfig(model2,config,extension){let configured=resolveHeadersOrThrow({...configuredHeaders(config,extension),...rawModelHeaders(model2,config,extension)},`model "${model2.provider}/${model2.id}"`);return{headers:model2.headers||configured?{...model2.headers,...configured}:void 0,authHeader:extension?.authHeader??config?.authHeader??!1}}function configuredRequestAuthStatus(config,extension){let value=configuredApiKey(config,extension);if(value===void 0)return;if(isCommandConfigValue(value))return{configured:!0,source:"models_json_command"};let names2=getConfigValueEnvVarNames(value);return names2.length>0?isConfigValueConfigured(value)?{configured:!0,source:"environment",label:names2.join(", ")}:{configured:!1}:{configured:!0,source:extension?.apiKey!==void 0?"fallback":"models_json_key"}}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider2,modelId){return this.runtime.getModel(provider2,modelId)}hasConfiguredAuth(model2){return this.runtime.hasConfiguredAuth(model2.provider)}async getApiKeyAndHeaders(model2){try{let resolution=await this.runtime.getAuth(model2);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model2);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model2.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 "${model2.provider}"`:message}}}getProviderAuthStatus(provider2){return this.runtime.getProviderAuthStatus(provider2)}getProvider(provider2){return this.runtime.getProvider(provider2)}login(provider2,type,interaction){return this.runtime.login(provider2,type,interaction)}complete(model2,context,options){return this.runtime.complete(model2,context,options)}getProviderDisplayName(provider2){return this.runtime.getProvider(provider2)?.name??provider2}getProviderAuth(provider2){return this.runtime.getAuth(provider2)}async getApiKeyForProvider(provider2){try{return(await this.runtime.getAuth(provider2))?.auth.apiKey}catch{return}}isUsingOAuth(model2){return this.runtime.isUsingOAuth(model2.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()}};import{existsSync as existsSync7,readdirSync as readdirSync5,readFileSync as readFileSync5,statSync as statSync6}from"fs";import{basename as basename4,dirname as dirname7,join as join17,resolve as resolve4,sep as sep3}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 value=defaultTarget==="@"||defaultTarget==="ARGUMENTS"?allArgs:args[parseInt(defaultTarget,10)-1];return value||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){try{let rawContent=readFileSync5(filePath,"utf-8"),{frontmatter,body}=parseFrontmatter(rawContent),name=basename4(filePath).replace(/\.md$/,""),description=frontmatter.description||"";if(!description){let firstLine=body.split(`
1082
1082
  `).find(line=>line.trim());firstLine&&(description=firstLine.slice(0,60),firstLine.length>60&&(description+="..."))}return{name,description,...frontmatter["argument-hint"]&&{argumentHint:frontmatter["argument-hint"]},content:body,sourceInfo,filePath}}catch{return null}}function loadTemplatesFromDir2(dir,getSourceInfo){let templates=[];if(!existsSync7(dir))return templates;try{let entries=readdirSync5(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=join17(dir,entry.name),isFile2=entry.isFile();if(entry.isSymbolicLink())try{isFile2=statSync6(fullPath).isFile()}catch{continue}if(isFile2&&entry.name.endsWith(".md")){let template=loadTemplateFromFile2(fullPath,getSourceInfo(fullPath));template&&templates.push(template)}}}catch{return templates}return templates}function loadPromptTemplates2(options){let resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(options.agentDir),promptPaths=options.promptPaths,includeDefaults=options.includeDefaults,templates=[],globalPromptsDir=join17(resolvedAgentDir,"prompts"),projectPromptsDir=resolve4(resolvedCwd,CONFIG_DIR_NAME,"prompts"),isUnderPath=(target,root)=>{let normalizedRoot=resolve4(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep3)?normalizedRoot:`${normalizedRoot}${sep3}`;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:statSync6(resolvedPath).isDirectory()?resolvedPath:dirname7(resolvedPath)});includeDefaults&&(templates.push(...loadTemplatesFromDir2(globalPromptsDir,getSourceInfo)),templates.push(...loadTemplatesFromDir2(projectPromptsDir,getSourceInfo)));for(let rawPath of promptPaths){let resolvedPath=resolvePath(rawPath,resolvedCwd,{trim:!0});if(existsSync7(resolvedPath))try{let stats=statSync6(resolvedPath);if(stats.isDirectory())templates.push(...loadTemplatesFromDir2(resolvedPath,getSourceInfo));else if(stats.isFile()&&resolvedPath.endsWith(".md")){let template=loadTemplateFromFile2(resolvedPath,getSourceInfo(resolvedPath));template&&templates.push(template)}}catch{}}return templates}function expandPromptTemplate(text,templates){if(!text.startsWith("/"))return text;let match2=text.match(/^\/([^\s]+)(?:\s+([\s\S]*))?$/);if(!match2)return text;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 text}import{existsSync as existsSync8,mkdirSync as mkdirSync3,writeFileSync as writeFileSync4}from"node:fs";import{dirname as dirname8}from"node:path";function exportSessionToJsonl(sessionManager,outputPath,createTrailingEntries){let filePath=resolvePath(outputPath??`session-${new Date().toISOString().replace(/[:.]/g,"-")}.jsonl`,process.cwd()),dir=dirname8(filePath);existsSync8(dir)||mkdirSync3(dir,{recursive:!0});let timestamp=new Date().toISOString(),header2={type:"session",version:CURRENT_SESSION_VERSION,id:sessionManager.getSessionId(),timestamp,cwd:sessionManager.getCwd()},lines=[JSON.stringify(header2)],parentId=null;for(let entry of sessionManager.getBranch())lines.push(JSON.stringify({...entry,parentId})),parentId=entry.id;for(let entry of createTrailingEntries?.(parentId,timestamp)??[])lines.push(JSON.stringify(entry));return writeFileSync4(filePath,`${lines.join(`
1083
1083
  `)}
1084
1084
  `),filePath}var import_ignore2=__toESM(require_ignore(),1);import{existsSync as existsSync9,readdirSync as readdirSync6,readFileSync as readFileSync6,statSync as statSync7}from"fs";import{basename as basename5,dirname as dirname9,join as join18,relative as relative2,resolve as resolve5,sep as sep4}from"path";var MAX_NAME_LENGTH2=64,MAX_DESCRIPTION_LENGTH2=1024,IGNORE_FILE_NAMES2=[".gitignore",".ignore",".fdignore"];function toPosixPath(p){return p.split(sep4).join("/")}function prefixIgnorePattern2(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 addIgnoreRules2(ig,dir,rootDir){let relativeDir=relative2(rootDir,dir),prefix=relativeDir?`${toPosixPath(relativeDir)}/`:"";for(let filename of IGNORE_FILE_NAMES2){let ignorePath=join18(dir,filename);if(existsSync9(ignorePath))try{let patterns=readFileSync6(ignorePath,"utf-8").split(/\r?\n/).map(line=>prefixIgnorePattern2(line,prefix)).filter(line=>!!line);patterns.length>0&&ig.add(patterns)}catch{}}}function validateName2(name){let errors=[];return name.length>MAX_NAME_LENGTH2&&errors.push(`name exceeds ${MAX_NAME_LENGTH2} characters (${name.length})`),/^[a-z0-9-]+$/.test(name)||errors.push("name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)"),(name.startsWith("-")||name.endsWith("-"))&&errors.push("name must not start or end with a hyphen"),name.includes("--")&&errors.push("name must not contain consecutive hyphens"),errors}function validateDescription2(description){let errors=[];return typeof description!="string"||description.trim()===""?errors.push("description is required"):description.length>MAX_DESCRIPTION_LENGTH2&&errors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH2} characters (${description.length})`),errors}function createSkillSourceInfo(filePath,baseDir,source2){switch(source2){case"user":return createSyntheticSourceInfo(filePath,{source:"local",scope:"user",baseDir});case"project":return createSyntheticSourceInfo(filePath,{source:"local",scope:"project",baseDir});case"path":return createSyntheticSourceInfo(filePath,{source:"local",baseDir});default:return createSyntheticSourceInfo(filePath,{source:source2,baseDir})}}function loadSkillsFromDir(options){let{dir,source:source2}=options;return loadSkillsFromDirInternal2(dir,source2,!0)}function loadSkillsFromDirInternal2(dir,source2,includeRootFiles,ignoreMatcher,rootDir){let skills=[],diagnostics=[];if(!existsSync9(dir))return{skills,diagnostics};let root=rootDir??dir,ig=ignoreMatcher??(0,import_ignore2.default)();addIgnoreRules2(ig,dir,root);try{let entries=readdirSync6(dir,{withFileTypes:!0});for(let entry of entries){if(entry.name!=="SKILL.md")continue;let fullPath=join18(dir,entry.name),isFile2=entry.isFile();if(entry.isSymbolicLink())try{isFile2=statSync7(fullPath).isFile()}catch{continue}let relPath=toPosixPath(relative2(root,fullPath));if(!isFile2||ig.ignores(relPath))continue;let result=loadSkillFromFile2(fullPath,source2);return result.skill&&skills.push(result.skill),diagnostics.push(...result.diagnostics),{skills,diagnostics}}for(let entry of entries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join18(dir,entry.name),isDirectory=entry.isDirectory(),isFile2=entry.isFile();if(entry.isSymbolicLink())try{let stats=statSync7(fullPath);isDirectory=stats.isDirectory(),isFile2=stats.isFile()}catch{continue}let relPath=toPosixPath(relative2(root,fullPath)),ignorePath=isDirectory?`${relPath}/`:relPath;if(ig.ignores(ignorePath))continue;if(isDirectory){let subResult=loadSkillsFromDirInternal2(fullPath,source2,!1,ig,root);skills.push(...subResult.skills),diagnostics.push(...subResult.diagnostics);continue}if(!isFile2||!includeRootFiles||!entry.name.endsWith(".md"))continue;let result=loadSkillFromFile2(fullPath,source2);result.skill&&skills.push(result.skill),diagnostics.push(...result.diagnostics)}}catch{}return{skills,diagnostics}}function loadSkillFromFile2(filePath,source2){let diagnostics=[],isDeclaredSkill=basename5(filePath)==="SKILL.md",rawContent;try{rawContent=readFileSync6(filePath,"utf-8")}catch(error){let message=error instanceof Error?error.message:"failed to read skill file";return diagnostics.push({type:"warning",message,path:filePath}),{skill:null,diagnostics}}let frontmatter;try{({frontmatter}=parseFrontmatter(rawContent))}catch(error){if(isDeclaredSkill){let message=error instanceof Error?error.message:"failed to parse skill file";diagnostics.push({type:"warning",message,path:filePath})}return{skill:null,diagnostics}}let description=frontmatter.description,hasDescription=typeof description=="string"&&description.trim()!=="";if(!isDeclaredSkill&&!hasDescription)return{skill:null,diagnostics};let skillDir=dirname9(filePath),parentDirName=basename5(skillDir),descErrors=validateDescription2(description);for(let error of descErrors)diagnostics.push({type:"warning",message:error,path:filePath});let name=(typeof frontmatter.name=="string"?frontmatter.name:void 0)||parentDirName,nameErrors=validateName2(name);for(let error of nameErrors)diagnostics.push({type:"warning",message:error,path:filePath});return hasDescription?{skill:{name,description,filePath,baseDir:skillDir,sourceInfo:createSkillSourceInfo(filePath,skillDir,source2),disableModelInvocation:frontmatter["disable-model-invocation"]===!0},diagnostics}:{skill:null,diagnostics}}function formatSkillsForPrompt(skills){let visibleSkills=skills.filter(s=>!s.disableModelInvocation);if(visibleSkills.length===0)return"";let lines=[`
@@ -1246,8 +1246,8 @@ ${body}
1246
1246
  </skill>`;return args?`${skillBlock}
1247
1247
 
1248
1248
  ${args}`:skillBlock}catch(err2){return this._extensionRunner.emitError({extensionPath:skill.filePath,event:"skill_expansion",error:err2 instanceof Error?err2.message:String(err2)}),text}}async steer(text,images){text.startsWith("/")&&this._throwIfExtensionCommand(text);let expandedText=this._expandSkillCommand(text);expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates]),await this._queueSteer(expandedText,images)}async followUp(text,images){text.startsWith("/")&&this._throwIfExtensionCommand(text);let expandedText=this._expandSkillCommand(text);expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates]),await this._queueFollowUp(expandedText,images)}async _queueSteer(text,images){this._steeringMessages.push(text),this._emitQueueUpdate();let content=[{type:"text",text}];images&&content.push(...images),this.agent.steer({role:"user",content,timestamp:Date.now()})}async _queueFollowUp(text,images){this._followUpMessages.push(text),this._emitQueueUpdate();let content=[{type:"text",text}];images&&content.push(...images),this.agent.followUp({role:"user",content,timestamp:Date.now()})}_throwIfExtensionCommand(text){let spaceIndex=text.indexOf(" "),commandName=spaceIndex===-1?text.slice(1):text.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()};options?.deliverAs==="nextTurn"?this._pendingNextTurnMessages.push(appMessage):this.isStreaming&&options?.triggerTurn!==!1?options?.deliverAs==="followUp"?this.agent.followUp(appMessage):this.agent.steer(appMessage):options?.triggerTurn?await this._runAgentPrompt(appMessage):this.isStreaming?this._pendingCustomMessages.push(appMessage):this._appendCustomMessage(appMessage)}_appendCustomMessage(appMessage){this.agent.state.messages.push(appMessage),this.sessionManager.appendCustomMessageEntry(appMessage.customType,appMessage.content,appMessage.display,appMessage.details),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 text,images;if(typeof content=="string")text=content;else{let textParts=[];images=[];for(let part of content)part.type==="text"?textParts.push(part.text):images.push(part);text=textParts.join(`
1249
- `),images.length===0&&(images=void 0)}await this.prompt(text,{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._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.abortRetry(),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source2){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source:source2})}async setModel(model2,options={}){if(!await this._modelRuntime.checkAuth(model2.provider))throw new Error(`No API key for ${model2.provider}/${model2.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model2);this.agent.state.model=model2,this.sessionManager.appendModelChange(model2.provider,model2.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model2.provider,model2.id),this._addPersistedDefaultToNonEmptyScope(model2)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model2,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model2){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model2)))return;this._scopedModels=[...this._scopedModels,{model:model2}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model2.provider}/${model2.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(model2=>`${model2.provider}\0${model2.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 compact(preparation,requestModel,apiKey,headers,customInstructions,signal,this.thinkingLevel,this.agent.streamFunction,env2,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}async compact(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1;try{if(!this.model)throw new Error(formatNoModelSelectedMessage());let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(this.model),pathEntries=this.sessionManager.getBranch(),settings2=this.settingsManager.getCompactionSettings(),preparation=prepareCompaction(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 result=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result?.cancel)throw new Error("Compaction cancelled");result?.compaction&&(extensionCompaction=result.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 result=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,this._compactionAbortController.signal,env2,"manual");summary=result.summary,firstKeptEntryId=result.firstKeptEntryId,tokensBefore=result.tokensBefore,usage=result.usage,details=result.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(),sessionContext=this.sessionManager.buildSessionContext();this.agent.state.messages=sessionContext.messages;let estimatedTokensAfter=estimateMessagesTokens(sessionContext.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._compactionAbortController=void 0,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=message==="Compaction cancelled"||error instanceof Error&&error.name==="AbortError",errorMessage2=aborted?void 0:`Compaction failed: ${message}`;throw this._compactionAbortController=void 0,this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage2}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage2,aborted,willRetry:!1,fromExtension}),error}finally{this._compactionAbortController=void 0}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0){let settings2=this.settingsManager.getCompactionSettings();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 contextOverflow=sameModel&&isContextOverflow(assistantMessage,contextWindow),recoverableLength=sameModel&&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 errorMessage2=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:errorMessage2}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage2,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0;let messages=this.agent.state.messages;return messages.length>0&&messages[messages.length-1].role==="assistant"&&(this.agent.state.messages=messages.slice(0,-1)),await this._runAutoCompaction("overflow",willRetry)}let contextTokens,directContextTokens=assistantMessage.usage?calculateContextTokens(assistantMessage.usage):0;if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens(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 shouldCompact(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){let settings2=this.settingsManager.getCompactionSettings(),started=!1,fromExtension=!1;try{if(!this.model)return!1;let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(this.model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)return!1;this._emit({type:"compaction_start",reason}),this._autoCompactionAbortController=new AbortController,started=!0;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:this._autoCompactionAbortController.signal});if(extensionResult?.cancel)return this._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),await this._emitSessionCompactFailed({reason,aborted:!0,willRetry:!1,fromExtension:!1}),!1;extensionResult?.compaction&&(extensionCompaction=extensionResult.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 compactResult=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,void 0,this._autoCompactionAbortController.signal,env2,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}if(this._autoCompactionAbortController.signal.aborted)return this._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),await this._emitSessionCompactFailed({reason,aborted:!0,willRetry:!1,fromExtension}),!1;this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries(),sessionContext=this.sessionManager.buildSessionContext();this.agent.state.messages=sessionContext.messages;let estimatedTokensAfter=estimateMessagesTokens(sessionContext.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 result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};if(this._emit({type:"compaction_end",reason,result,aborted:!1,willRetry}),willRetry){let messages=this.agent.state.messages,lastMsg=messages[messages.length-1];return lastMsg?.role==="assistant"&&(lastMsg.stopReason==="error"||lastMsg.stopReason==="length")&&(this.agent.state.messages=messages.slice(0,-1)),!0}return this.agent.hasQueuedMessages()}catch(error){let errorMessage2=error instanceof Error?error.message:"compaction failed";if(started){let formattedErrorMessage=reason==="overflow"?`Context overflow recovery failed: ${errorMessage2}`:`Auto-compaction failed: ${errorMessage2}`;this._emit({type:"compaction_end",reason,result:void 0,aborted:!1,willRetry:!1,errorMessage:formattedErrorMessage}),await this._emitSessionCompactFailed({reason,errorMessage:formattedErrorMessage,aborted:!1,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController=void 0}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){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.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup"),await bindings.onResourcesExtended?.(),await this._extensionRunner.emit(this._sessionStartEvent)}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._baseSystemPrompt=this._rebuildSystemPrompt(this.getActiveToolNames()),this.agent.state.systemPrompt=this._baseSystemPrompt}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source2=this.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname12(entry.extensionPath);return{path:entry.path,metadata:{source:source2,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(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 model2=>this._modelRuntime.hasConfiguredAuth(model2.provider)?(await this.setModel(model2),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{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(),compact:options=>{(async()=>{try{let result=await this.compact(options?.customInstructions);options?.onComplete?.(result)}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:provider2=>{this._modelRuntime.registerNativeProvider(provider2),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,value]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value);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){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate(),await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._buildRuntime({activeToolNames:this.getActiveToolNames(),flagValues:previousFlagValues,includeAllExtensionTools:!0}),(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(source2){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage2)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage2})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source2})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}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=settings2.baseDelayMs*2**(this._retryAttempt-1);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"});let messages=this.agent.state.messages;messages.length>0&&messages[messages.length-1].role==="assistant"&&(this.agent.state.messages=messages.slice(0,-1)),this._retryAbortController=new AbortController;try{await sleep2(delayMs,this._retryAbortController.signal)}catch{let attempt2=this._retryAttempt;return this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"}),!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}
1250
- ${command}`:command;try{let result=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,result,options),result}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result,options){let bashMessage={role:"bashExecution",command,output:result.output,exitCode:result.exitCode,cancelled:result.cancelled,truncated:result.truncated,fullOutputPath:result.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.agent.state.messages.push(bashMessage),this.sessionManager.appendMessage(bashMessage))}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.agent.state.messages.push(bashMessage),this.sessionManager.appendMessage(bashMessage);this._pendingBashMessages=[]}}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.");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}=collectEntriesForBranchSummary(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};this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result?.cancel)return{cancelled:!0};result?.summary&&options.summarize&&(extensionSummary=result.summary,fromExtension=!0),result?.customInstructions!==void 0&&(customInstructions=result.customInstructions),result?.replaceInstructions!==void 0&&(replaceInstructions=result.replaceInstructions),result?.label!==void 0&&(label=result.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let model2=this.model,{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model2),branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result=await generateBranchSummary(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(result.aborted)return{cancelled:!0,aborted:!0};if(result.error)throw new Error(result.error);summaryText=result.summary,summaryUsage=result.usage,summaryDetails={readFiles:result.readFiles||[],modifiedFiles:result.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;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);label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label);let sessionContext=this.sessionManager.buildSessionContext();return this.agent.state.messages=sessionContext.messages,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}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text=contentText(entry.message.content,"");text&&result.push({entryId:entry.id,text})}return result}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals();for(let entry of this.sessionManager.getEntries()){if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage&&addUsageToTotals(usageTotals,entry.usage),entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++,message.usage&&addUsageToTotals(usageTotals,message.usage);else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c2=>c2.type==="toolCall").length),addUsageToTotals(usageTotals,assistantMsg.usage)}}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 model2=this.model;if(!model2)return;let contextWindow=model2.contextWindow??0;if(contextWindow<=0)return;let branchEntries=this.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branchEntries);if(latestCompaction){let compactionIndex=branchEntries.lastIndexOf(latestCompaction),hasPostCompactionUsage=!1;for(let i=branchEntries.length-1;i>compactionIndex;i--){let entry=branchEntries[i];if(entry.type==="message"&&entry.message.role==="assistant"){let assistant=entry.message;if(assistant.stopReason!=="aborted"&&assistant.stopReason!=="error"&&calculateContextTokens(assistant.usage)>0){hasPostCompactionUsage=!0;break}}}if(!hasPostCompactionUsage)return{tokens:null,contextWindow,percent:null}}let estimate=estimateContextTokens(this.messages),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)}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 text="";for(let content of lastAssistant.content)content.type==="text"&&(text+=content.text);return text.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}};var import_proper_lockfile=__toESM(require_proper_lockfile(),1);import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync8,writeFileSync as writeFileSync5}from"fs";import{dirname as dirname13,join as join21}from"path";import{setTimeout as sleep3}from"timers/promises";function abortReason(signal){if(signal.reason!==void 0)return signal.reason;let error=new Error("The operation was aborted");return error.name="AbortError",error}function operationSignal(signal){return signal??new AbortController().signal}function raceWithAbortSignal(operation,signal){return signal?signal.aborted?(operation.catch(()=>{}),Promise.reject(abortReason(signal))):new Promise((resolve26,reject)=>{let settled=!1,cleanup=()=>signal.removeEventListener("abort",onAbort),onAbort=()=>{settled||(settled=!0,cleanup(),reject(abortReason(signal)))};signal.addEventListener("abort",onAbort,{once:!0}),operation.then(value=>{settled||(settled=!0,cleanup(),resolve26(value))},error=>{settled||(settled=!0,cleanup(),reject(error))}),signal.aborted&&onAbort()}):operation}var AUTH_FILE_WRITE_OPTIONS={encoding:"utf-8",mode:384},sharedAuthFileReadState,FileAuthStorageBackend=class{constructor(authPath=join21(getAgentDir(),"auth.json")){this.authPath=normalizePath(authPath)}ensureParentDir(){let dir=dirname13(this.authPath);existsSync11(dir)||mkdirSync5(dir,{recursive:!0,mode:448})}ensureFileExists(){existsSync11(this.authPath)||writeFileSync5(this.authPath,"{}",AUTH_FILE_WRITE_OPTIONS)}acquireLockSyncWithRetry(path14){let lastError;for(let attempt2=1;attempt2<=10;attempt2++)try{return import_proper_lockfile.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 auth storage lock")}withLock(fn){this.ensureParentDir(),this.ensureFileExists();let release;try{release=this.acquireLockSyncWithRetry(this.authPath);let current=existsSync11(this.authPath)?readFileSync8(this.authPath,"utf-8"):void 0,{result,next}=fn(current);return next!==void 0&&writeFileSync5(this.authPath,next,AUTH_FILE_WRITE_OPTIONS),result}finally{release&&release()}}async acquireLockAsync(signal,onCompromised){let deadline=Date.now()+3e4,retry=0;for(;;){signal?.throwIfAborted();let release;try{release=await import_proper_lockfile.default.lock(this.authPath,{realpath:!1,retries:0,stale:3e4,onCompromised})}catch(error){signal?.throwIfAborted();let code=typeof error=="object"&&error!==null&&"code"in error?String(error.code):void 0,remainingMs=deadline-Date.now();if(code!=="ELOCKED"||remainingMs<=0)throw error;let baseDelayMs=Math.min(10*2**retry,2e3/2);retry++;let delayMs=Math.min(Math.round(baseDelayMs*(1+Math.random())),remainingMs);signal?await sleep3(delayMs,void 0,{signal}):await sleep3(delayMs);continue}return signal?.aborted&&(await release(),signal.throwIfAborted()),release}}async withLockAsync(fn,options){options?.signal?.throwIfAborted(),this.ensureParentDir(),this.ensureFileExists();let release,lockCompromised=!1,lockCompromisedError,throwIfCompromised=()=>{if(lockCompromised)throw lockCompromisedError??new Error("Auth storage lock was compromised")};try{release=await this.acquireLockAsync(options?.signal,error=>{lockCompromised=!0,lockCompromisedError=error}),throwIfCompromised(),options?.signal?.throwIfAborted();let current=existsSync11(this.authPath)?readFileSync8(this.authPath,"utf-8"):void 0,{result,next}=await fn(current);return throwIfCompromised(),options?.signal?.throwIfAborted(),next!==void 0&&writeFileSync5(this.authPath,next,AUTH_FILE_WRITE_OPTIONS),throwIfCompromised(),result}finally{if(release)try{await release()}catch{}}}},ReadOnlyAuthStorage=class{constructor(authPath=join21(getAgentDir(),"auth.json")){this.authPath=normalizePath(authPath)}load(){if(this.data)return this.data;let parsed;try{parsed=JSON.parse(stripBom(readFileSync8(this.authPath,"utf-8")))}catch(error){if(error.code==="ENOENT")return this.data={},this.data;throw new Error(`Failed to read auth.json: ${error instanceof Error?error.message:String(error)}`)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new Error("Invalid auth.json: expected an object");for(let[providerId,credential]of Object.entries(parsed)){if(typeof credential!="object"||credential===null||Array.isArray(credential))throw new Error(`Invalid auth.json credential for provider "${providerId}"`);let value=credential;if(value.type==="api_key"){let validKey=value.key===void 0||typeof value.key=="string",validEnv=value.env===void 0||typeof value.env=="object"&&value.env!==null&&!Array.isArray(value.env)&&Object.values(value.env).every(entry=>typeof entry=="string");if(validKey&&validEnv)continue}else if(value.type==="oauth"&&typeof value.access=="string"&&typeof value.refresh=="string"&&typeof value.expires=="number"&&Number.isFinite(value.expires))continue;throw new Error(`Invalid auth.json credential for provider "${providerId}"`)}return this.data=parsed,this.data}async read(providerId,options){options?.signal?.throwIfAborted();let credential=this.load()[providerId];if(options?.signal?.throwIfAborted(),!!credential)return credential.type!=="api_key"||!credential.key||isCommandConfigValue(credential.key)?structuredClone(credential):{...credential,key:resolveConfigValue(credential.key,credential.env)}}async list(options){options?.signal?.throwIfAborted();let credentials=Object.entries(this.load()).map(([providerId,credential])=>({providerId,type:credential.type}));return options?.signal?.throwIfAborted(),credentials}async modify(_providerId,_fn,_options){throw new Error("Read-only credential storage cannot modify auth.json")}async delete(_providerId,_options){throw new Error("Read-only credential storage cannot modify auth.json")}},InMemoryAuthStorageBackend=class{constructor(){this.asyncChain=Promise.resolve()}withLock(fn){let{result,next}=fn(this.value);return next!==void 0&&(this.value=next),result}withLockAsync(fn,options){let previous=this.asyncChain,operation=(async()=>{await previous.catch(()=>{}),options?.signal?.throwIfAborted();let{result,next}=await fn(this.value);return options?.signal?.throwIfAborted(),next!==void 0&&(this.value=next),result})();return this.asyncChain=operation.catch(()=>{}),raceWithAbortSignal(operation,options?.signal)}},AuthStorage=class _AuthStorage{constructor(storage,authPath){if(this.storage=storage,this.authPath=authPath,this.readState=authPath&&sharedAuthFileReadState?.authPath===authPath?sharedAuthFileReadState.readState:{data:{}},authPath&&!sharedAuthFileReadState&&(sharedAuthFileReadState={authPath,readState:this.readState}),authPath){let revision=getFileRevision(authPath);if(revision!==void 0&&revision===this.readState.revision)return}this.reload()}static create(authPath=join21(getAgentDir(),"auth.json")){let normalizedAuthPath=normalizePath(authPath);return new _AuthStorage(new FileAuthStorageBackend(normalizedAuthPath),normalizedAuthPath)}static fromStorage(storage){return new _AuthStorage(storage)}static inMemory(data={}){let storage=new InMemoryAuthStorageBackend;return storage.withLock(()=>({result:void 0,next:JSON.stringify(data,null,2)})),_AuthStorage.fromStorage(storage)}parseStorageData(content){return content?JSON.parse(stripBom(content)):{}}updateReadState(data,revision){this.readState.data=data,this.readState.revision=revision}reload(){let content,revision;try{this.storage.withLock(current=>(content=current,revision=this.authPath?getFileRevision(this.authPath):void 0,{result:void 0})),this.updateReadState(this.parseStorageData(content),revision)}catch{}}async reloadFromStorageAsync(options){return this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content),revision=this.authPath?getFileRevision(this.authPath):void 0;return this.updateReadState(currentData,revision),{result:currentData}},options)}async readLatestData(options){if(options?.signal?.throwIfAborted(),!this.authPath){let reload2=this.reloadFromStorageAsync(options);return options?.signal?reload2:reload2.catch(()=>this.readState.data)}let revision=getFileRevision(this.authPath);if(revision!==void 0&&revision===this.readState.revision)return this.readState.data;if(!this.readState.reload){let controller=new AbortController,reload2={controller,promise:this.reloadFromStorageAsync({signal:controller.signal}),readers:0};this.readState.reload=reload2,reload2.promise.then(()=>{this.readState.reload===reload2&&(this.readState.reload=void 0)},()=>{this.readState.reload===reload2&&(this.readState.reload=void 0)})}let reload=this.readState.reload;reload.readers++;try{let result=raceWithAbortSignal(reload.promise,options?.signal);return options?.signal?await result:await result.catch(()=>this.readState.data)}finally{reload.readers--,reload.readers===0&&this.readState.reload===reload&&(this.readState.reload=void 0,reload.controller.abort())}}async read(provider2,options){let credential=(await this.readLatestData(options))[provider2];return options?.signal?.throwIfAborted(),credential?.type!=="api_key"||credential.key===void 0?credential:{...credential,key:resolveConfigValue(credential.key,credential.env)}}async modify(provider2,fn,options){let latestData=this.readState.data,revision,result=await this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content),next=await fn(currentData[provider2]);if(next===void 0)return latestData=currentData,revision=this.authPath?getFileRevision(this.authPath):void 0,{result:currentData[provider2]};let merged={...currentData,[provider2]:next};return latestData=merged,{result:next,next:JSON.stringify(merged,null,2)}},options);return this.updateReadState(latestData,revision),result}async delete(provider2,options){let latestData=this.readState.data;await this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content);return delete currentData[provider2],latestData=currentData,{result:void 0,next:JSON.stringify(currentData,null,2)}},options),this.updateReadState(latestData)}async list(options){let entries=Object.entries(await this.readLatestData(options));return options?.signal?.throwIfAborted(),entries.map(([providerId,credential])=>({providerId,type:credential.type}))}};function readStoredCredential(providerId,authPath=join21(getAgentDir(),"auth.json")){try{return JSON.parse(stripBom(readFileSync8(normalizePath(authPath),"utf-8")))[providerId]}catch{return}}var balanced=(a,b2,str2)=>{let ma=a instanceof RegExp?maybeMatch(a,str2):a,mb=b2 instanceof RegExp?maybeMatch(b2,str2):b2,r=ma!==null&&mb!=null&&range(ma,mb,str2);return r&&{start:r[0],end:r[1],pre:str2.slice(0,r[0]),body:str2.slice(r[0]+ma.length,r[1]),post:str2.slice(r[1]+mb.length)}},maybeMatch=(reg,str2)=>{let m2=str2.match(reg);return m2?m2[0]:null},range=(a,b2,str2)=>{let begs,beg,left,right,result,ai=str2.indexOf(a),bi=str2.indexOf(b2,ai+1),i=ai;if(ai>=0&&bi>0){if(a===b2)return[ai,bi];for(begs=[],left=str2.length;i>=0&&!result;){if(i===ai)begs.push(i),ai=str2.indexOf(a,i+1);else if(begs.length===1){let r=begs.pop();r!==void 0&&(result=[r,bi])}else beg=begs.pop(),beg!==void 0&&beg<left&&(left=beg,right=bi),bi=str2.indexOf(b2,i+1);i=ai<bi&&ai>=0?ai:bi}begs.length&&right!==void 0&&(result=[left,right])}return result};var escSlash="\0SLASH"+Math.random()+"\0",escOpen="\0OPEN"+Math.random()+"\0",escClose="\0CLOSE"+Math.random()+"\0",escComma="\0COMMA"+Math.random()+"\0",escPeriod="\0PERIOD"+Math.random()+"\0",escSlashPattern=new RegExp(escSlash,"g"),escOpenPattern=new RegExp(escOpen,"g"),escClosePattern=new RegExp(escClose,"g"),escCommaPattern=new RegExp(escComma,"g"),escPeriodPattern=new RegExp(escPeriod,"g"),slashPattern=/\\\\/g,openPattern=/\\{/g,closePattern=/\\}/g,commaPattern=/\\,/g,periodPattern=/\\\./g,EXPANSION_MAX=1e5,EXPANSION_MAX_LENGTH=4e6;function numeric(str2){return isNaN(str2)?str2.charCodeAt(0):parseInt(str2,10)}function escapeBraces(str2){return str2.replace(slashPattern,escSlash).replace(openPattern,escOpen).replace(closePattern,escClose).replace(commaPattern,escComma).replace(periodPattern,escPeriod)}function unescapeBraces(str2){return str2.replace(escSlashPattern,"\\").replace(escOpenPattern,"{").replace(escClosePattern,"}").replace(escCommaPattern,",").replace(escPeriodPattern,".")}function parseCommaParts(str2){if(!str2)return[""];let parts=[],m2=balanced("{","}",str2);if(!m2)return str2.split(",");let{pre,body,post}=m2,p=pre.split(",");p[p.length-1]+="{"+body+"}";let postParts=parseCommaParts(post);return post.length&&(p[p.length-1]+=postParts.shift(),p.push.apply(p,postParts)),parts.push.apply(parts,p),parts}function expand(str2,options={}){if(!str2)return[];let{max=EXPANSION_MAX,maxLength=EXPANSION_MAX_LENGTH}=options;return str2.slice(0,2)==="{}"&&(str2="\\{\\}"+str2.slice(2)),expand_(escapeBraces(str2),max,maxLength,!0).map(unescapeBraces)}function embrace(str2){return"{"+str2+"}"}function isPadded(el){return/^-?0\d/.test(el)}function lte(i,y2){return i<=y2}function gte(i,y2){return i>=y2}function combine(acc,pre,values,max,maxLength,dropEmpties){let out=[],length=0;for(let a=0;a<acc.length;a++)for(let v2=0;v2<values.length;v2++){if(out.length>=max)return out;let expansion=acc[a]+pre+values[v2];if(!(dropEmpties&&!expansion)){if(length+expansion.length>maxLength)return out;out.push(expansion),length+=expansion.length}}return out}function expandSequence(body,isAlphaSequence,max,maxLength){let n=body.split(/\.\./),N=[];if(n[0]===void 0||n[1]===void 0)return N;let x2=numeric(n[0]),y2=numeric(n[1]),width=Math.max(n[0].length,n[1].length),incr=n.length===3&&n[2]!==void 0?Math.max(Math.abs(numeric(n[2])),1):1,test=lte;y2<x2&&(incr*=-1,test=gte);let pad2=n.some(isPadded),length=0;for(let i=x2;test(i,y2)&&N.length<max;i+=incr){let c2;if(isAlphaSequence)c2=String.fromCharCode(i),c2==="\\"&&(c2="");else if(c2=String(i),pad2){let need=width-c2.length;if(need>0){let z2=new Array(need+1).join("0");i<0?c2="-"+z2+c2.slice(1):c2=z2+c2}}if(length+c2.length>maxLength)break;N.push(c2),length+=c2.length}return N}function expand_(str2,max,maxLength,isTop){let acc=[""],dropEmpties=!1,firstGroup=!0;for(;;){let m2=balanced("{","}",str2);if(!m2)return combine(acc,str2,[""],max,maxLength,dropEmpties);let pre=m2.pre;if(/\$$/.test(pre)){if(acc=combine(acc,pre+"{"+m2.body+"}",[""],max,maxLength,dropEmpties&&!m2.post.length),firstGroup=!1,!m2.post.length)break;str2=m2.post;continue}let isNumericSequence=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m2.body),isAlphaSequence=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m2.body),isSequence=isNumericSequence||isAlphaSequence,isOptions=m2.body.indexOf(",")>=0;if(!isSequence&&!isOptions){if(m2.post.match(/,(?!,).*\}/)){str2=m2.pre+"{"+m2.body+escClose+m2.post,isTop=!0;continue}return combine(acc,pre+"{"+m2.body+"}"+m2.post,[""],max,maxLength,dropEmpties)}firstGroup&&(dropEmpties=isTop&&!isSequence,firstGroup=!1);let values;if(isSequence)values=expandSequence(m2.body,isAlphaSequence,max,maxLength);else{let n=parseCommaParts(m2.body);if(n.length===1&&n[0]!==void 0&&(n=expand_(n[0],max,maxLength,!1).map(embrace),n.length===1)){if(acc=combine(acc,pre+n[0],[""],max,maxLength,dropEmpties&&!m2.post.length),!m2.post.length)break;str2=m2.post;continue}let dropsEmpties=dropEmpties&&!m2.post.length&&!pre;for(let d=0;dropsEmpties&&d<acc.length;d++)acc[d]&&(dropsEmpties=!1);values=[];let valuesLength=0;outer:for(let j2=0;j2<n.length;j2++){let expanded=expand_(n[j2],max,maxLength,!1);for(let k2=0;k2<expanded.length;k2++){let v2=expanded[k2];if(!(dropsEmpties&&!v2)){if(values.length>=max||valuesLength+v2.length>maxLength)break outer;values.push(v2),valuesLength+=v2.length}}}}if(acc=combine(acc,pre,values,max,maxLength,dropEmpties&&!m2.post.length),!m2.post.length)break;str2=m2.post}return acc}var assertValidPattern=pattern=>{if(typeof pattern!="string")throw new TypeError("invalid pattern");if(pattern.length>65536)throw new TypeError("pattern is too long")};var posixClasses={"[:alnum:]":["\\p{L}\\p{Nl}\\p{Nd}",!0],"[:alpha:]":["\\p{L}\\p{Nl}",!0],"[:ascii:]":["\\x00-\\x7f",!1],"[:blank:]":["\\p{Zs}\\t",!0],"[:cntrl:]":["\\p{Cc}",!0],"[:digit:]":["\\p{Nd}",!0],"[:graph:]":["\\p{Z}\\p{C}",!0,!0],"[:lower:]":["\\p{Ll}",!0],"[:print:]":["\\p{C}",!0],"[:punct:]":["\\p{P}",!0],"[:space:]":["\\p{Z}\\t\\r\\n\\v\\f",!0],"[:upper:]":["\\p{Lu}",!0],"[:word:]":["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}",!0],"[:xdigit:]":["A-Fa-f0-9",!1]},braceEscape=s=>s.replace(/[[\]\\-]/g,"\\$&"),regexpEscape=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),rangesToString=ranges=>ranges.join(""),parseClass=(glob,position)=>{let pos=position;if(glob.charAt(pos)!=="[")throw new Error("not in a brace expression");let ranges=[],negs=[],i=pos+1,sawStart=!1,uflag=!1,escaping=!1,negate=!1,endPos=pos,rangeStart="";WHILE:for(;i<glob.length;){let c2=glob.charAt(i);if((c2==="!"||c2==="^")&&i===pos+1){negate=!0,i++;continue}if(c2==="]"&&sawStart&&!escaping){endPos=i+1;break}if(sawStart=!0,c2==="\\"&&!escaping){escaping=!0,i++;continue}if(c2==="["&&!escaping){for(let[cls,[unip,u,neg]]of Object.entries(posixClasses))if(glob.startsWith(cls,i)){if(rangeStart)return["$.",!1,glob.length-pos,!0];i+=cls.length,neg?negs.push(unip):ranges.push(unip),uflag=uflag||u;continue WHILE}}if(escaping=!1,rangeStart){c2>rangeStart?ranges.push(braceEscape(rangeStart)+"-"+braceEscape(c2)):c2===rangeStart&&ranges.push(braceEscape(c2)),rangeStart="",i++;continue}if(glob.startsWith("-]",i+1)){ranges.push(braceEscape(c2+"-")),i+=2;continue}if(glob.startsWith("-",i+1)){rangeStart=c2,i+=2;continue}ranges.push(braceEscape(c2)),i++}if(endPos<i)return["",!1,0,!1];if(!ranges.length&&!negs.length)return["$.",!1,glob.length-pos,!0];if(negs.length===0&&ranges.length===1&&/^\\?.$/.test(ranges[0])&&!negate){let r=ranges[0].length===2?ranges[0].slice(-1):ranges[0];return[regexpEscape(r),!1,endPos-pos,!1]}let sranges="["+(negate?"^":"")+rangesToString(ranges)+"]",snegs="["+(negate?"":"^")+rangesToString(negs)+"]";return[ranges.length&&negs.length?"("+sranges+"|"+snegs+")":ranges.length?sranges:snegs,uflag,endPos-pos,!0]};var unescape=(s,{windowsPathsNoEscape=!1,magicalBraces=!0}={})=>magicalBraces?windowsPathsNoEscape?s.replace(/\[([^/\\])\]/g,"$1"):s.replace(/((?!\\).|^)\[([^/\\])\]/g,"$1$2").replace(/\\([^/])/g,"$1"):windowsPathsNoEscape?s.replace(/\[([^/\\{}])\]/g,"$1"):s.replace(/((?!\\).|^)\[([^/\\{}])\]/g,"$1$2").replace(/\\([^/{}])/g,"$1");var _a2,types=new Set(["!","?","+","*","@"]),isExtglobType=c2=>types.has(c2),isExtglobAST=c2=>isExtglobType(c2.type),adoptionMap=new Map([["!",["@"]],["?",["?","@"]],["@",["@"]],["*",["*","+","?","@"]],["+",["+","@"]]]),adoptionWithSpaceMap=new Map([["!",["?"]],["@",["?"]],["+",["?","*"]]]),adoptionAnyMap=new Map([["!",["?","@"]],["?",["?","@"]],["@",["?","@"]],["*",["*","+","?","@"]],["+",["+","@","?","*"]]]),usurpMap=new Map([["!",new Map([["!","@"]])],["?",new Map([["*","*"],["+","*"]])],["@",new Map([["!","!"],["?","?"],["@","@"],["*","*"],["+","+"]])],["+",new Map([["?","*"],["*","*"]])]]),startNoTraversal="(?!(?:^|/)\\.\\.?(?:$|/))",startNoDot="(?!\\.)",addPatternStart=new Set(["[","."]),justDots=new Set(["..","."]),reSpecials=new Set("().*{}+?[]^$\\!"),regExpEscape=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),qmark="[^/]",star=qmark+"*?",starNoEmpty=qmark+"+?",ID=0,AST=class{type;#root;#hasMagic;#uflag=!1;#parts=[];#parent;#parentIndex;#negs;#filledNegs=!1;#options;#toString;#emptyExt=!1;id=++ID;get depth(){return(this.#parent?.depth??-1)+1}[Symbol.for("nodejs.util.inspect.custom")](){return{"@@type":"AST",id:this.id,type:this.type,root:this.#root.id,parent:this.#parent?.id,depth:this.depth,partsLength:this.#parts.length,parts:this.#parts}}constructor(type,parent,options={}){this.type=type,type&&(this.#hasMagic=!0),this.#parent=parent,this.#root=this.#parent?this.#parent.#root:this,this.#options=this.#root===this?options:this.#root.#options,this.#negs=this.#root===this?[]:this.#root.#negs,type==="!"&&!this.#root.#filledNegs&&this.#negs.push(this),this.#parentIndex=this.#parent?this.#parent.#parts.length:0}get hasMagic(){if(this.#hasMagic!==void 0)return this.#hasMagic;for(let p of this.#parts)if(typeof p!="string"&&(p.type||p.hasMagic))return this.#hasMagic=!0;return this.#hasMagic}toString(){return this.#toString!==void 0?this.#toString:this.type?this.#toString=this.type+"("+this.#parts.map(p=>String(p)).join("|")+")":this.#toString=this.#parts.map(p=>String(p)).join("")}#fillNegs(){if(this!==this.#root)throw new Error("should only call on root");if(this.#filledNegs)return this;this.toString(),this.#filledNegs=!0;let n;for(;n=this.#negs.pop();){if(n.type!=="!")continue;let p=n,pp=p.#parent;for(;pp;){for(let i=p.#parentIndex+1;!pp.type&&i<pp.#parts.length;i++)for(let part of n.#parts){if(typeof part=="string")throw new Error("string part in extglob AST??");part.copyIn(pp.#parts[i])}p=pp,pp=p.#parent}}return this}push(...parts){for(let p of parts)if(p!==""){if(typeof p!="string"&&!(p instanceof _a2&&p.#parent===this))throw new Error("invalid part: "+p);this.#parts.push(p)}}toJSON(){let ret=this.type===null?this.#parts.slice().map(p=>typeof p=="string"?p:p.toJSON()):[this.type,...this.#parts.map(p=>p.toJSON())];return this.isStart()&&!this.type&&ret.unshift([]),this.isEnd()&&(this===this.#root||this.#root.#filledNegs&&this.#parent?.type==="!")&&ret.push({}),ret}isStart(){if(this.#root===this)return!0;if(!this.#parent?.isStart())return!1;if(this.#parentIndex===0)return!0;let p=this.#parent;for(let i=0;i<this.#parentIndex;i++){let pp=p.#parts[i];if(!(pp instanceof _a2&&pp.type==="!"))return!1}return!0}isEnd(){if(this.#root===this||this.#parent?.type==="!")return!0;if(!this.#parent?.isEnd())return!1;if(!this.type)return this.#parent?.isEnd();let pl=this.#parent?this.#parent.#parts.length:0;return this.#parentIndex===pl-1}copyIn(part){typeof part=="string"?this.push(part):this.push(part.clone(this))}clone(parent){let c2=new _a2(this.type,parent);for(let p of this.#parts)c2.copyIn(p);return c2}static#parseAST(str2,ast,pos,opt,extDepth){let maxDepth=opt.maxExtglobRecursion??2,escaping=!1,inBrace=!1,braceStart=-1,braceNeg=!1;if(ast.type===null){let i2=pos,acc2="";for(;i2<str2.length;){let c2=str2.charAt(i2++);if(escaping||c2==="\\"){escaping=!escaping,acc2+=c2;continue}if(inBrace){i2===braceStart+1?(c2==="^"||c2==="!")&&(braceNeg=!0):c2==="]"&&!(i2===braceStart+2&&braceNeg)&&(inBrace=!1),acc2+=c2;continue}else if(c2==="["){inBrace=!0,braceStart=i2,braceNeg=!1,acc2+=c2;continue}if(!opt.noext&&isExtglobType(c2)&&str2.charAt(i2)==="("&&extDepth<=maxDepth){ast.push(acc2),acc2="";let ext2=new _a2(c2,ast);i2=_a2.#parseAST(str2,ext2,i2,opt,extDepth+1),ast.push(ext2);continue}acc2+=c2}return ast.push(acc2),i2}let i=pos+1,part=new _a2(null,ast),parts=[],acc="";for(;i<str2.length;){let c2=str2.charAt(i++);if(escaping||c2==="\\"){escaping=!escaping,acc+=c2;continue}if(inBrace){i===braceStart+1?(c2==="^"||c2==="!")&&(braceNeg=!0):c2==="]"&&!(i===braceStart+2&&braceNeg)&&(inBrace=!1),acc+=c2;continue}else if(c2==="["){inBrace=!0,braceStart=i,braceNeg=!1,acc+=c2;continue}if(!opt.noext&&isExtglobType(c2)&&str2.charAt(i)==="("&&(extDepth<=maxDepth||ast&&ast.#canAdoptType(c2))){let depthAdd=ast&&ast.#canAdoptType(c2)?0:1;part.push(acc),acc="";let ext2=new _a2(c2,part);part.push(ext2),i=_a2.#parseAST(str2,ext2,i,opt,extDepth+depthAdd);continue}if(c2==="|"){part.push(acc),acc="",parts.push(part),part=new _a2(null,ast);continue}if(c2===")")return acc===""&&ast.#parts.length===0&&(ast.#emptyExt=!0),part.push(acc),acc="",ast.push(...parts,part),i;acc+=c2}return ast.type=null,ast.#hasMagic=void 0,ast.#parts=[str2.substring(pos-1)],i}#canAdoptWithSpace(child){return this.#canAdopt(child,adoptionWithSpaceMap)}#canAdopt(child,map=adoptionMap){if(!child||typeof child!="object"||child.type!==null||child.#parts.length!==1||this.type===null)return!1;let gc=child.#parts[0];return!gc||typeof gc!="object"||gc.type===null?!1:this.#canAdoptType(gc.type,map)}#canAdoptType(c2,map=adoptionAnyMap){return!!map.get(this.type)?.includes(c2)}#adoptWithSpace(child,index3){let gc=child.#parts[0],blank=new _a2(null,gc,this.options);blank.#parts.push(""),gc.push(blank),this.#adopt(child,index3)}#adopt(child,index3){let gc=child.#parts[0];this.#parts.splice(index3,1,...gc.#parts);for(let p of gc.#parts)typeof p=="object"&&(p.#parent=this);this.#toString=void 0}#canUsurpType(c2){return!!usurpMap.get(this.type)?.has(c2)}#canUsurp(child){if(!child||typeof child!="object"||child.type!==null||child.#parts.length!==1||this.type===null||this.#parts.length!==1)return!1;let gc=child.#parts[0];return!gc||typeof gc!="object"||gc.type===null?!1:this.#canUsurpType(gc.type)}#usurp(child){let m2=usurpMap.get(this.type),gc=child.#parts[0],nt2=m2?.get(gc.type);if(!nt2)return!1;this.#parts=gc.#parts;for(let p of this.#parts)typeof p=="object"&&(p.#parent=this);this.type=nt2,this.#toString=void 0,this.#emptyExt=!1}static fromGlob(pattern,options={}){let ast=new _a2(null,void 0,options);return _a2.#parseAST(pattern,ast,0,options,0),ast}toMMPattern(){if(this!==this.#root)return this.#root.toMMPattern();let glob=this.toString(),[re,body,hasMagic,uflag]=this.toRegExpSource();if(!(hasMagic||this.#hasMagic||this.#options.nocase&&!this.#options.nocaseMagicOnly&&glob.toUpperCase()!==glob.toLowerCase()))return body;let flags=(this.#options.nocase?"i":"")+(uflag?"u":"");return Object.assign(new RegExp(`^${re}$`,flags),{_src:re,_glob:glob})}get options(){return this.#options}toRegExpSource(allowDot){let dot=allowDot??!!this.#options.dot;if(this.#root===this&&(this.#flatten(),this.#fillNegs()),!isExtglobAST(this)){let noEmpty=this.isStart()&&this.isEnd()&&!this.#parts.some(s=>typeof s!="string"),src=this.#parts.map(p=>{let[re,_2,hasMagic,uflag]=typeof p=="string"?_a2.#parseGlob(p,this.#hasMagic,noEmpty):p.toRegExpSource(allowDot);return this.#hasMagic=this.#hasMagic||hasMagic,this.#uflag=this.#uflag||uflag,re}).join(""),start2="";if(this.isStart()&&typeof this.#parts[0]=="string"&&!(this.#parts.length===1&&justDots.has(this.#parts[0]))){let aps=addPatternStart,needNoTrav=dot&&aps.has(src.charAt(0))||src.startsWith("\\.")&&aps.has(src.charAt(2))||src.startsWith("\\.\\.")&&aps.has(src.charAt(4)),needNoDot=!dot&&!allowDot&&aps.has(src.charAt(0));start2=needNoTrav?startNoTraversal:needNoDot?startNoDot:""}let end="";return this.isEnd()&&this.#root.#filledNegs&&this.#parent?.type==="!"&&(end="(?:$|\\/)"),[start2+src+end,unescape(src),this.#hasMagic=!!this.#hasMagic,this.#uflag]}let repeated=this.type==="*"||this.type==="+",start=this.type==="!"?"(?:(?!(?:":"(?:",body=this.#partsToRegExp(dot);if(this.isStart()&&this.isEnd()&&!body&&this.type!=="!"){let s=this.toString(),me2=this;return me2.#parts=[s],me2.type=null,me2.#hasMagic=void 0,[s,unescape(this.toString()),!1,!1]}let bodyDotAllowed=!repeated||allowDot||dot||!startNoDot?"":this.#partsToRegExp(!0);bodyDotAllowed===body&&(bodyDotAllowed=""),bodyDotAllowed&&(body=`(?:${body})(?:${bodyDotAllowed})*?`);let final="";if(this.type==="!"&&this.#emptyExt)final=(this.isStart()&&!dot?startNoDot:"")+starNoEmpty;else{let close=this.type==="!"?"))"+(this.isStart()&&!dot&&!allowDot?startNoDot:"")+star+")":this.type==="@"?")":this.type==="?"?")?":this.type==="+"&&bodyDotAllowed?")":this.type==="*"&&bodyDotAllowed?")?":`)${this.type}`;final=start+body+close}return[final,unescape(body),this.#hasMagic=!!this.#hasMagic,this.#uflag]}#flatten(){if(isExtglobAST(this)){let iterations=0,done=!1;do{done=!0;for(let i=0;i<this.#parts.length;i++){let c2=this.#parts[i];typeof c2=="object"&&(c2.#flatten(),this.#canAdopt(c2)?(done=!1,this.#adopt(c2,i)):this.#canAdoptWithSpace(c2)?(done=!1,this.#adoptWithSpace(c2,i)):this.#canUsurp(c2)&&(done=!1,this.#usurp(c2)))}}while(!done&&++iterations<10)}else for(let p of this.#parts)typeof p=="object"&&p.#flatten();this.#toString=void 0}#partsToRegExp(dot){return this.#parts.map(p=>{if(typeof p=="string")throw new Error("string type in extglob ast??");let[re,_2,_hasMagic,uflag]=p.toRegExpSource(dot);return this.#uflag=this.#uflag||uflag,re}).filter(p=>!(this.isStart()&&this.isEnd())||!!p).join("|")}static#parseGlob(glob,hasMagic,noEmpty=!1){let escaping=!1,re="",uflag=!1,inStar=!1;for(let i=0;i<glob.length;i++){let c2=glob.charAt(i);if(escaping){escaping=!1,re+=(reSpecials.has(c2)?"\\":"")+c2;continue}if(c2==="*"){if(inStar)continue;inStar=!0,re+=noEmpty&&/^[*]+$/.test(glob)?starNoEmpty:star,hasMagic=!0;continue}else inStar=!1;if(c2==="\\"){i===glob.length-1?re+="\\\\":escaping=!0;continue}if(c2==="["){let[src,needUflag,consumed,magic]=parseClass(glob,i);if(consumed){re+=src,uflag=uflag||needUflag,i+=consumed-1,hasMagic=hasMagic||magic;continue}}if(c2==="?"){re+=qmark,hasMagic=!0;continue}re+=regExpEscape(c2)}return[re,unescape(glob),!!hasMagic,uflag]}};_a2=AST;var escape=(s,{windowsPathsNoEscape=!1,magicalBraces=!1}={})=>magicalBraces?windowsPathsNoEscape?s.replace(/[?*()[\]{}]/g,"[$&]"):s.replace(/[?*()[\]\\{}]/g,"\\$&"):windowsPathsNoEscape?s.replace(/[?*()[\]]/g,"[$&]"):s.replace(/[?*()[\]\\]/g,"\\$&");var minimatch=(p,pattern,options={})=>(assertValidPattern(pattern),!options.nocomment&&pattern.charAt(0)==="#"?!1:new Minimatch(pattern,options).match(p)),starDotExtRE=/^\*+([^+@!?*[(]*)$/,starDotExtTest=ext2=>f2=>!f2.startsWith(".")&&f2.endsWith(ext2),starDotExtTestDot=ext2=>f2=>f2.endsWith(ext2),starDotExtTestNocase=ext2=>(ext2=ext2.toLowerCase(),f2=>!f2.startsWith(".")&&f2.toLowerCase().endsWith(ext2)),starDotExtTestNocaseDot=ext2=>(ext2=ext2.toLowerCase(),f2=>f2.toLowerCase().endsWith(ext2)),starDotStarRE=/^\*+\.\*+$/,starDotStarTest=f2=>!f2.startsWith(".")&&f2.includes("."),starDotStarTestDot=f2=>f2!=="."&&f2!==".."&&f2.includes("."),dotStarRE=/^\.\*+$/,dotStarTest=f2=>f2!=="."&&f2!==".."&&f2.startsWith("."),starRE=/^\*+$/,starTest=f2=>f2.length!==0&&!f2.startsWith("."),starTestDot=f2=>f2.length!==0&&f2!=="."&&f2!=="..",qmarksRE=/^\?+([^+@!?*[(]*)?$/,qmarksTestNocase=([$0,ext2=""])=>{let noext=qmarksTestNoExt([$0]);return ext2?(ext2=ext2.toLowerCase(),f2=>noext(f2)&&f2.toLowerCase().endsWith(ext2)):noext},qmarksTestNocaseDot=([$0,ext2=""])=>{let noext=qmarksTestNoExtDot([$0]);return ext2?(ext2=ext2.toLowerCase(),f2=>noext(f2)&&f2.toLowerCase().endsWith(ext2)):noext},qmarksTestDot=([$0,ext2=""])=>{let noext=qmarksTestNoExtDot([$0]);return ext2?f2=>noext(f2)&&f2.endsWith(ext2):noext},qmarksTest=([$0,ext2=""])=>{let noext=qmarksTestNoExt([$0]);return ext2?f2=>noext(f2)&&f2.endsWith(ext2):noext},qmarksTestNoExt=([$0])=>{let len=$0.length;return f2=>f2.length===len&&!f2.startsWith(".")},qmarksTestNoExtDot=([$0])=>{let len=$0.length;return f2=>f2.length===len&&f2!=="."&&f2!==".."},defaultPlatform=typeof process=="object"&&process?typeof process.env=="object"&&process.env&&process.env.__MINIMATCH_TESTING_PLATFORM__||process.platform:"posix",path10={win32:{sep:"\\"},posix:{sep:"/"}},sep6=defaultPlatform==="win32"?path10.win32.sep:path10.posix.sep;minimatch.sep=sep6;var GLOBSTAR=Symbol("globstar **");minimatch.GLOBSTAR=GLOBSTAR;var qmark2="[^/]",star2=qmark2+"*?",twoStarDot="(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?",twoStarNoDot="(?:(?!(?:\\/|^)\\.).)*?",filter=(pattern,options={})=>p=>minimatch(p,pattern,options);minimatch.filter=filter;var ext=(a,b2={})=>Object.assign({},a,b2),defaults=def=>{if(!def||typeof def!="object"||!Object.keys(def).length)return minimatch;let orig=minimatch;return Object.assign((p,pattern,options={})=>orig(p,pattern,ext(def,options)),{Minimatch:class extends orig.Minimatch{constructor(pattern,options={}){super(pattern,ext(def,options))}static defaults(options){return orig.defaults(ext(def,options)).Minimatch}},AST:class extends orig.AST{constructor(type,parent,options={}){super(type,parent,ext(def,options))}static fromGlob(pattern,options={}){return orig.AST.fromGlob(pattern,ext(def,options))}},unescape:(s,options={})=>orig.unescape(s,ext(def,options)),escape:(s,options={})=>orig.escape(s,ext(def,options)),filter:(pattern,options={})=>orig.filter(pattern,ext(def,options)),defaults:options=>orig.defaults(ext(def,options)),makeRe:(pattern,options={})=>orig.makeRe(pattern,ext(def,options)),braceExpand:(pattern,options={})=>orig.braceExpand(pattern,ext(def,options)),match:(list,pattern,options={})=>orig.match(list,pattern,ext(def,options)),sep:orig.sep,GLOBSTAR})};minimatch.defaults=defaults;var braceExpand=(pattern,options={})=>(assertValidPattern(pattern),options.nobrace||!/\{(?:(?!\{).)*\}/.test(pattern)?[pattern]:expand(pattern,{max:options.braceExpandMax}));minimatch.braceExpand=braceExpand;var makeRe=(pattern,options={})=>new Minimatch(pattern,options).makeRe();minimatch.makeRe=makeRe;var match=(list,pattern,options={})=>{let mm=new Minimatch(pattern,options);return list=list.filter(f2=>mm.match(f2)),mm.options.nonull&&!list.length&&list.push(pattern),list};minimatch.match=match;var globMagic=/[?*]|[+@!]\(.*?\)|\[|\]/,regExpEscape2=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),Minimatch=class{options;set;pattern;windowsPathsNoEscape;nonegate;negate;comment;empty;preserveMultipleSlashes;partial;globSet;globParts;nocase;isWindows;platform;windowsNoMagicRoot;maxGlobstarRecursion;regexp;constructor(pattern,options={}){assertValidPattern(pattern),options=options||{},this.options=options,this.maxGlobstarRecursion=options.maxGlobstarRecursion??200,this.pattern=pattern,this.platform=options.platform||defaultPlatform,this.isWindows=this.platform==="win32";let awe="allowWindowsEscape";this.windowsPathsNoEscape=!!options.windowsPathsNoEscape||options[awe]===!1,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\/g,"/")),this.preserveMultipleSlashes=!!options.preserveMultipleSlashes,this.regexp=null,this.negate=!1,this.nonegate=!!options.nonegate,this.comment=!1,this.empty=!1,this.partial=!!options.partial,this.nocase=!!this.options.nocase,this.windowsNoMagicRoot=options.windowsNoMagicRoot!==void 0?options.windowsNoMagicRoot:!!(this.isWindows&&this.nocase),this.globSet=[],this.globParts=[],this.set=[],this.make()}hasMagic(){if(this.options.magicalBraces&&this.set.length>1)return!0;for(let pattern of this.set)for(let part of pattern)if(typeof part!="string")return!0;return!1}debug(..._2){}make(){let pattern=this.pattern,options=this.options;if(!options.nocomment&&pattern.charAt(0)==="#"){this.comment=!0;return}if(!pattern){this.empty=!0;return}this.parseNegate(),this.globSet=[...new Set(this.braceExpand())],options.debug&&(this.debug=(...args)=>console.error(...args)),this.debug(this.pattern,this.globSet);let rawGlobParts=this.globSet.map(s=>this.slashSplit(s));this.globParts=this.preprocess(rawGlobParts),this.debug(this.pattern,this.globParts);let set=this.globParts.map((s,_2,__)=>{if(this.isWindows&&this.windowsNoMagicRoot){let isUNC=s[0]===""&&s[1]===""&&(s[2]==="?"||!globMagic.test(s[2]))&&!globMagic.test(s[3]),isDrive=/^[a-z]:/i.test(s[0]);if(isUNC)return[...s.slice(0,4),...s.slice(4).map(ss=>this.parse(ss))];if(isDrive)return[s[0],...s.slice(1).map(ss=>this.parse(ss))]}return s.map(ss=>this.parse(ss))});if(this.debug(this.pattern,set),this.set=set.filter(s=>s.indexOf(!1)===-1),this.isWindows)for(let i=0;i<this.set.length;i++){let p=this.set[i];p[0]===""&&p[1]===""&&this.globParts[i][2]==="?"&&typeof p[3]=="string"&&/^[a-z]:$/i.test(p[3])&&(p[2]="?")}this.debug(this.pattern,this.set)}preprocess(globParts){if(this.options.noglobstar)for(let partset of globParts)for(let j2=0;j2<partset.length;j2++)partset[j2]==="**"&&(partset[j2]="*");let{optimizationLevel=1}=this.options;return optimizationLevel>=2?(globParts=this.firstPhasePreProcess(globParts),globParts=this.secondPhasePreProcess(globParts)):optimizationLevel>=1?globParts=this.levelOneOptimize(globParts):globParts=this.adjascentGlobstarOptimize(globParts),globParts}adjascentGlobstarOptimize(globParts){return globParts.map(parts=>{let gs=-1;for(;(gs=parts.indexOf("**",gs+1))!==-1;){let i=gs;for(;parts[i+1]==="**";)i++;i!==gs&&parts.splice(gs,i-gs)}return parts})}levelOneOptimize(globParts){return globParts.map(parts=>(parts=parts.reduce((set,part)=>{let prev=set[set.length-1];return part==="**"&&prev==="**"?set:part===".."&&prev&&prev!==".."&&prev!=="."&&prev!=="**"?(set.pop(),set):(set.push(part),set)},[]),parts.length===0?[""]:parts))}levelTwoFileOptimize(parts){Array.isArray(parts)||(parts=this.slashSplit(parts));let didSomething=!1;do{if(didSomething=!1,!this.preserveMultipleSlashes){for(let i=1;i<parts.length-1;i++){let p=parts[i];i===1&&p===""&&parts[0]===""||(p==="."||p==="")&&(didSomething=!0,parts.splice(i,1),i--)}parts[0]==="."&&parts.length===2&&(parts[1]==="."||parts[1]==="")&&(didSomething=!0,parts.pop())}let dd=0;for(;(dd=parts.indexOf("..",dd+1))!==-1;){let p=parts[dd-1];p&&p!=="."&&p!==".."&&p!=="**"&&!(this.isWindows&&/^[a-z]:$/i.test(p))&&(didSomething=!0,parts.splice(dd-1,2),dd-=2)}}while(didSomething);return parts.length===0?[""]:parts}firstPhasePreProcess(globParts){let didSomething=!1;do{didSomething=!1;for(let parts of globParts){let gs=-1;for(;(gs=parts.indexOf("**",gs+1))!==-1;){let gss=gs;for(;parts[gss+1]==="**";)gss++;gss>gs&&parts.splice(gs+1,gss-gs);let next=parts[gs+1],p=parts[gs+2],p2=parts[gs+3];if(next!==".."||!p||p==="."||p===".."||!p2||p2==="."||p2==="..")continue;didSomething=!0,parts.splice(gs,1);let other=parts.slice(0);other[gs]="**",globParts.push(other),gs--}if(!this.preserveMultipleSlashes){for(let i=1;i<parts.length-1;i++){let p=parts[i];i===1&&p===""&&parts[0]===""||(p==="."||p==="")&&(didSomething=!0,parts.splice(i,1),i--)}parts[0]==="."&&parts.length===2&&(parts[1]==="."||parts[1]==="")&&(didSomething=!0,parts.pop())}let dd=0;for(;(dd=parts.indexOf("..",dd+1))!==-1;){let p=parts[dd-1];if(p&&p!=="."&&p!==".."&&p!=="**"){didSomething=!0;let splin=dd===1&&parts[dd+1]==="**"?["."]:[];parts.splice(dd-1,2,...splin),parts.length===0&&parts.push(""),dd-=2}}}}while(didSomething);return globParts}secondPhasePreProcess(globParts){for(let i=0;i<globParts.length-1;i++)for(let j2=i+1;j2<globParts.length;j2++){let matched=this.partsMatch(globParts[i],globParts[j2],!this.preserveMultipleSlashes);if(matched){globParts[i]=[],globParts[j2]=matched;break}}return globParts.filter(gs=>gs.length)}partsMatch(a,b2,emptyGSMatch=!1){let ai=0,bi=0,result=[],which="";for(;ai<a.length&&bi<b2.length;)if(a[ai]===b2[bi])result.push(which==="b"?b2[bi]:a[ai]),ai++,bi++;else if(emptyGSMatch&&a[ai]==="**"&&b2[bi]===a[ai+1])result.push(a[ai]),ai++;else if(emptyGSMatch&&b2[bi]==="**"&&a[ai]===b2[bi+1])result.push(b2[bi]),bi++;else if(a[ai]==="*"&&b2[bi]&&(this.options.dot||!b2[bi].startsWith("."))&&b2[bi]!=="**"){if(which==="b")return!1;which="a",result.push(a[ai]),ai++,bi++}else if(b2[bi]==="*"&&a[ai]&&(this.options.dot||!a[ai].startsWith("."))&&a[ai]!=="**"){if(which==="a")return!1;which="b",result.push(b2[bi]),ai++,bi++}else return!1;return a.length===b2.length&&result}parseNegate(){if(this.nonegate)return;let pattern=this.pattern,negate=!1,negateOffset=0;for(let i=0;i<pattern.length&&pattern.charAt(i)==="!";i++)negate=!negate,negateOffset++;negateOffset&&(this.pattern=pattern.slice(negateOffset)),this.negate=negate}matchOne(file,pattern,partial=!1){let fileStartIndex=0,patternStartIndex=0;if(this.isWindows){let fileDrive=typeof file[0]=="string"&&/^[a-z]:$/i.test(file[0]),fileUNC=!fileDrive&&file[0]===""&&file[1]===""&&file[2]==="?"&&/^[a-z]:$/i.test(file[3]),patternDrive=typeof pattern[0]=="string"&&/^[a-z]:$/i.test(pattern[0]),patternUNC=!patternDrive&&pattern[0]===""&&pattern[1]===""&&pattern[2]==="?"&&typeof pattern[3]=="string"&&/^[a-z]:$/i.test(pattern[3]),fdi=fileUNC?3:fileDrive?0:void 0,pdi=patternUNC?3:patternDrive?0:void 0;if(typeof fdi=="number"&&typeof pdi=="number"){let[fd,pd]=[file[fdi],pattern[pdi]];fd.toLowerCase()===pd.toLowerCase()&&(pattern[pdi]=fd,patternStartIndex=pdi,fileStartIndex=fdi)}}let{optimizationLevel=1}=this.options;return optimizationLevel>=2&&(file=this.levelTwoFileOptimize(file)),pattern.includes(GLOBSTAR)?this.#matchGlobstar(file,pattern,partial,fileStartIndex,patternStartIndex):this.#matchOne(file,pattern,partial,fileStartIndex,patternStartIndex)}#matchGlobstar(file,pattern,partial,fileIndex,patternIndex){let firstgs=pattern.indexOf(GLOBSTAR,patternIndex),lastgs=pattern.lastIndexOf(GLOBSTAR),[head,body,tail]=partial?[pattern.slice(patternIndex,firstgs),pattern.slice(firstgs+1),[]]:[pattern.slice(patternIndex,firstgs),pattern.slice(firstgs+1,lastgs),pattern.slice(lastgs+1)];if(head.length){let fileHead=file.slice(fileIndex,fileIndex+head.length);if(!this.#matchOne(fileHead,head,partial,0,0))return!1;fileIndex+=head.length,patternIndex+=head.length}let fileTailMatch=0;if(tail.length){if(tail.length+fileIndex>file.length)return!1;let tailStart=file.length-tail.length;if(this.#matchOne(file,tail,partial,tailStart,0))fileTailMatch=tail.length;else{if(file[file.length-1]!==""||fileIndex+tail.length===file.length||(tailStart--,!this.#matchOne(file,tail,partial,tailStart,0)))return!1;fileTailMatch=tail.length+1}}if(!body.length){let sawSome=!!fileTailMatch;for(let i2=fileIndex;i2<file.length-fileTailMatch;i2++){let f2=String(file[i2]);if(sawSome=!0,f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1}return partial||sawSome}let bodySegments=[[[],0]],currentBody=bodySegments[0],nonGsParts=0,nonGsPartsSums=[0];for(let b2 of body)b2===GLOBSTAR?(nonGsPartsSums.push(nonGsParts),currentBody=[[],0],bodySegments.push(currentBody)):(currentBody[0].push(b2),nonGsParts++);let i=bodySegments.length-1,fileLength=file.length-fileTailMatch;for(let b2 of bodySegments)b2[1]=fileLength-(nonGsPartsSums[i--]+b2[0].length);return!!this.#matchGlobStarBodySections(file,bodySegments,fileIndex,0,partial,0,!!fileTailMatch)}#matchGlobStarBodySections(file,bodySegments,fileIndex,bodyIndex,partial,globStarDepth,sawTail){let bs=bodySegments[bodyIndex];if(!bs){for(let i=fileIndex;i<file.length;i++){sawTail=!0;let f2=file[i];if(f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1}return sawTail}let[body,after]=bs;for(;fileIndex<=after;){if(this.#matchOne(file.slice(0,fileIndex+body.length),body,partial,fileIndex,0)&&globStarDepth<this.maxGlobstarRecursion){let sub=this.#matchGlobStarBodySections(file,bodySegments,fileIndex+body.length,bodyIndex+1,partial,globStarDepth+1,sawTail);if(sub!==!1)return sub}let f2=file[fileIndex];if(f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1;fileIndex++}return partial||null}#matchOne(file,pattern,partial,fileIndex,patternIndex){let fi,pi,pl,fl;for(fi=fileIndex,pi=patternIndex,fl=file.length,pl=pattern.length;fi<fl&&pi<pl;fi++,pi++){this.debug("matchOne loop");let p=pattern[pi],f2=file[fi];if(this.debug(pattern,p,f2),p===!1||p===GLOBSTAR)return!1;let hit;if(typeof p=="string"?(hit=f2===p,this.debug("string match",p,f2,hit)):(hit=p.test(f2),this.debug("pattern match",p,f2,hit)),!hit)return!1}if(fi===fl&&pi===pl)return!0;if(fi===fl)return partial;if(pi===pl)return fi===fl-1&&file[fi]==="";throw new Error("wtf?")}braceExpand(){return braceExpand(this.pattern,this.options)}parse(pattern){assertValidPattern(pattern);let options=this.options;if(pattern==="**")return GLOBSTAR;if(pattern==="")return"";let m2,fastTest=null;(m2=pattern.match(starRE))?fastTest=options.dot?starTestDot:starTest:(m2=pattern.match(starDotExtRE))?fastTest=(options.nocase?options.dot?starDotExtTestNocaseDot:starDotExtTestNocase:options.dot?starDotExtTestDot:starDotExtTest)(m2[1]):(m2=pattern.match(qmarksRE))?fastTest=(options.nocase?options.dot?qmarksTestNocaseDot:qmarksTestNocase:options.dot?qmarksTestDot:qmarksTest)(m2):(m2=pattern.match(starDotStarRE))?fastTest=options.dot?starDotStarTestDot:starDotStarTest:(m2=pattern.match(dotStarRE))&&(fastTest=dotStarTest);let re=AST.fromGlob(pattern,this.options).toMMPattern();return fastTest&&typeof re=="object"&&Reflect.defineProperty(re,"test",{value:fastTest}),re}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let set=this.set;if(!set.length)return this.regexp=!1,this.regexp;let options=this.options,twoStar=options.noglobstar?star2:options.dot?twoStarDot:twoStarNoDot,flags=new Set(options.nocase?["i"]:[]),re=set.map(pattern=>{let pp=pattern.map(p=>{if(p instanceof RegExp)for(let f2 of p.flags.split(""))flags.add(f2);return typeof p=="string"?regExpEscape2(p):p===GLOBSTAR?GLOBSTAR:p._src});pp.forEach((p,i)=>{let next=pp[i+1],prev=pp[i-1];p!==GLOBSTAR||prev===GLOBSTAR||(prev===void 0?next!==void 0&&next!==GLOBSTAR?pp[i+1]="(?:\\/|"+twoStar+"\\/)?"+next:pp[i]=twoStar:next===void 0?pp[i-1]=prev+"(?:\\/|\\/"+twoStar+")?":next!==GLOBSTAR&&(pp[i-1]=prev+"(?:\\/|\\/"+twoStar+"\\/)"+next,pp[i+1]=GLOBSTAR))});let filtered=pp.filter(p=>p!==GLOBSTAR);if(this.partial&&filtered.length>=1){let prefixes=[];for(let i=1;i<=filtered.length;i++)prefixes.push(filtered.slice(0,i).join("/"));return"(?:"+prefixes.join("|")+")"}return filtered.join("/")}).join("|"),[open10,close]=set.length>1?["(?:",")"]:["",""];re="^"+open10+re+close+"$",this.partial&&(re="^(?:\\/|"+open10+re.slice(1,-1)+close+")$"),this.negate&&(re="^(?!"+re+").+$");try{this.regexp=new RegExp(re,[...flags].join(""))}catch{this.regexp=!1}return this.regexp}slashSplit(p){return this.preserveMultipleSlashes?p.split("/"):this.isWindows&&/^\/\/[^/]+/.test(p)?["",...p.split(/\/+/)]:p.split(/\/+/)}match(f2,partial=this.partial){if(this.debug("match",f2,this.pattern),this.comment)return!1;if(this.empty)return f2==="";if(f2==="/"&&partial)return!0;let options=this.options;this.isWindows&&(f2=f2.split("\\").join("/"));let ff=this.slashSplit(f2);this.debug(this.pattern,"split",ff);let set=this.set;this.debug(this.pattern,"set",set);let filename=ff[ff.length-1];if(!filename)for(let i=ff.length-2;!filename&&i>=0;i--)filename=ff[i];for(let pattern of set){let file=ff;if(options.matchBase&&pattern.length===1&&(file=[filename]),this.matchOne(file,pattern,partial))return options.flipNegate?!0:!this.negate}return options.flipNegate?!1:this.negate}static defaults(def){return minimatch.defaults(def).Minimatch}};minimatch.AST=AST;minimatch.Minimatch=Minimatch;minimatch.escape=escape;minimatch.unescape=unescape;var defaultModelPerProvider={"amazon-bedrock":"us.anthropic.claude-opus-4-6-v1","ant-ling":"Ring-2.6-1T",anthropic:"claude-opus-4-8",openai:"gpt-5.5","azure-openai-responses":"gpt-5.4","openai-codex":"gpt-5.5",radius:"auto",nvidia:"nvidia/nemotron-3-super-120b-a12b",deepseek:"deepseek-v4-pro",google:"gemini-3.1-pro-preview","google-vertex":"gemini-3.1-pro-preview","github-copilot":"gpt-5.4",openrouter:"moonshotai/kimi-k2.6","vercel-ai-gateway":"zai/glm-5.1",xai:"grok-4.6",groq:"openai/gpt-oss-120b",cerebras:"gpt-oss-120b",zai:"glm-5.3","zai-coding-cn":"glm-5.3",mistral:"devstral-medium-latest",minimax:"MiniMax-M2.7","minimax-cn":"MiniMax-M2.7",moonshotai:"kimi-k2.6","moonshotai-cn":"kimi-k2.6",huggingface:"moonshotai/Kimi-K2.6",fireworks:"accounts/fireworks/models/kimi-k2p6",together:"moonshotai/Kimi-K2.6",baseten:"zai-org/GLM-5.2",opencode:"kimi-k2.6","opencode-go":"kimi-k2.6","kimi-coding":"kimi-for-coding","cloudflare-workers-ai":"@cf/moonshotai/kimi-k2.6","cloudflare-ai-gateway":"workers-ai/@cf/moonshotai/kimi-k2.6","qwen-token-plan":"qwen3.7-max","qwen-token-plan-cn":"qwen3.7-max","qwen-token-plan-individual":"qwen3.8-max",xiaomi:"mimo-v2.5-pro","xiaomi-token-plan-cn":"mimo-v2.5-pro","xiaomi-token-plan-ams":"mimo-v2.5-pro","xiaomi-token-plan-sgp":"mimo-v2.5-pro"};function isAlias(id){return id.endsWith("-latest")?!0:!/-\d{8}$/.test(id)}function findExactModelReferenceMatch(modelReference,availableModels){let trimmedReference=modelReference.trim();if(!trimmedReference)return;let normalizedReference=trimmedReference.toLowerCase(),canonicalMatches=availableModels.filter(model2=>`${model2.provider}/${model2.id}`.toLowerCase()===normalizedReference);if(canonicalMatches.length===1)return canonicalMatches[0];if(canonicalMatches.length>1)return;let slashIndex=trimmedReference.indexOf("/");if(slashIndex!==-1){let provider2=trimmedReference.substring(0,slashIndex).trim(),modelId=trimmedReference.substring(slashIndex+1).trim();if(provider2&&modelId){let providerMatches=availableModels.filter(model2=>model2.provider.toLowerCase()===provider2.toLowerCase()&&model2.id.toLowerCase()===modelId.toLowerCase());if(providerMatches.length===1)return providerMatches[0];if(providerMatches.length>1)return}}let idMatches=availableModels.filter(model2=>model2.id.toLowerCase()===normalizedReference);return idMatches.length===1?idMatches[0]:void 0}function tryMatchModel(modelPattern,availableModels){let exactMatch=findExactModelReferenceMatch(modelPattern,availableModels);if(exactMatch)return exactMatch;let matches=availableModels.filter(m2=>m2.id.toLowerCase().includes(modelPattern.toLowerCase())||m2.name?.toLowerCase().includes(modelPattern.toLowerCase()));if(matches.length===0)return;let aliases=matches.filter(m2=>isAlias(m2.id)),datedVersions=matches.filter(m2=>!isAlias(m2.id));return aliases.length>0?(aliases.sort((a,b2)=>b2.id.localeCompare(a.id)),aliases[0]):(datedVersions.sort((a,b2)=>b2.id.localeCompare(a.id)),datedVersions[0])}function buildFallbackModel(provider2,modelId,availableModels){let providerModels=availableModels.filter(m2=>m2.provider===provider2);if(providerModels.length===0)return;let defaultId=defaultModelPerProvider[provider2];return{...defaultId?providerModels.find(m2=>m2.id===defaultId)??providerModels[0]:providerModels[0],id:modelId,name:modelId}}function parseModelPattern(pattern,availableModels,options){let exactMatch=tryMatchModel(pattern,availableModels);if(exactMatch)return{model:exactMatch,thinkingLevel:void 0,warning:void 0};let lastColonIndex=pattern.lastIndexOf(":");if(lastColonIndex===-1)return{model:void 0,thinkingLevel:void 0,warning:void 0};let prefix=pattern.substring(0,lastColonIndex),suffix=pattern.substring(lastColonIndex+1);if(isValidThinkingLevel(suffix)){let result=parseModelPattern(prefix,availableModels,options);return result.model?{model:result.model,thinkingLevel:result.warning?void 0:suffix,warning:result.warning}:result}else{if(!(options?.allowInvalidThinkingLevelFallback??!0))return{model:void 0,thinkingLevel:void 0,warning:void 0};let result=parseModelPattern(prefix,availableModels,options);return result.model?{model:result.model,thinkingLevel:void 0,warning:`Invalid thinking level "${suffix}" in pattern "${pattern}". Using default instead.`}:result}}function resolveModelScopeFromModels(patterns,models){let availableModels=[...models],scopedModels=[],diagnostics=[];for(let pattern of patterns){if(pattern.includes("*")||pattern.includes("?")||pattern.includes("[")){let colonIdx=pattern.lastIndexOf(":"),globPattern2=pattern,thinkingLevel2;if(colonIdx!==-1){let suffix=pattern.substring(colonIdx+1);isValidThinkingLevel(suffix)&&(thinkingLevel2=suffix,globPattern2=pattern.substring(0,colonIdx))}let exactMatch=findExactModelReferenceMatch(globPattern2,availableModels);if(exactMatch){scopedModels.find(sm=>modelsAreEqual(sm.model,exactMatch))||scopedModels.push({model:exactMatch,thinkingLevel:thinkingLevel2});continue}let matchingModels=availableModels.filter(m2=>{let fullId=`${m2.provider}/${m2.id}`;return minimatch(fullId,globPattern2,{nocase:!0})||minimatch(m2.id,globPattern2,{nocase:!0})});if(matchingModels.length===0){diagnostics.push({type:"warning",code:"no-match",message:`No models match pattern "${pattern}"`,pattern});continue}for(let model3 of matchingModels)scopedModels.find(sm=>modelsAreEqual(sm.model,model3))||scopedModels.push({model:model3,thinkingLevel:thinkingLevel2});continue}let{model:model2,thinkingLevel,warning}=parseModelPattern(pattern,availableModels);if(warning&&diagnostics.push({type:"warning",code:"invalid-thinking-level",message:warning,pattern}),!model2){diagnostics.push({type:"warning",code:"no-match",message:`No models match pattern "${pattern}"`,pattern});continue}scopedModels.find(sm=>modelsAreEqual(sm.model,model2))||scopedModels.push({model:model2,thinkingLevel})}return{scopedModels,diagnostics}}async function resolveModelScopeWithDiagnostics(patterns,modelRuntime,options){return resolveModelScopeFromModels(patterns,await modelRuntime.getAvailable(void 0,options))}async function resolveModelScope(patterns,modelRuntime,options){let{scopedModels,diagnostics}=await resolveModelScopeWithDiagnostics(patterns,modelRuntime,options);for(let diagnostic of diagnostics)console.warn(source_default.yellow(`Warning: ${diagnostic.message}`));return scopedModels}function resolveCliModel(options){let{cliProvider,cliModel,cliThinking,modelRuntime}=options;if(!cliModel)return{model:void 0,warning:void 0,error:void 0};let availableModels=[...modelRuntime.getModels()];if(availableModels.length===0)return{model:void 0,warning:void 0,error:"No models available. Check your installation or add models to models.json."};let providerMap=new Map;for(let m2 of availableModels)providerMap.set(m2.provider.toLowerCase(),m2.provider);let provider2=cliProvider?providerMap.get(cliProvider.toLowerCase()):void 0;if(cliProvider&&!provider2)return{model:void 0,warning:void 0,error:`Unknown provider "${cliProvider}". Use --list-models to see available providers/models.`};let pattern=cliModel,inferredProvider=!1;if(!provider2){let slashIndex=cliModel.indexOf("/");if(slashIndex!==-1){let maybeProvider=cliModel.substring(0,slashIndex),canonical=providerMap.get(maybeProvider.toLowerCase());canonical&&(provider2=canonical,pattern=cliModel.substring(slashIndex+1),inferredProvider=!0)}}if(!provider2){let lower=cliModel.toLowerCase(),exactMatches=availableModels.filter(m2=>m2.id.toLowerCase()===lower||`${m2.provider}/${m2.id}`.toLowerCase()===lower);if(exactMatches.length===1)return{model:exactMatches[0],warning:void 0,thinkingLevel:void 0,error:void 0};if(exactMatches.length>1){let authenticatedExactMatches=exactMatches.filter(m2=>modelRuntime.hasConfiguredAuth(m2.provider));if(authenticatedExactMatches.length===1)return{model:authenticatedExactMatches[0],warning:void 0,thinkingLevel:void 0,error:void 0};let matches=exactMatches.map(m2=>`${m2.provider}/${m2.id}`).sort((a,b2)=>a.localeCompare(b2)).join(", "),authHint=authenticatedExactMatches.length===0?"No matching provider is authenticated.":"More than one matching provider is authenticated.";return{model:void 0,warning:void 0,thinkingLevel:void 0,error:`Model "${cliModel}" is ambiguous across providers: ${matches}. ${authHint} Use --provider or provider/model.`}}}if(cliProvider&&provider2){let prefix=`${provider2}/`;cliModel.toLowerCase().startsWith(prefix.toLowerCase())&&(pattern=cliModel.substring(prefix.length))}let candidates=provider2?availableModels.filter(m2=>m2.provider===provider2):availableModels,{model:model2,thinkingLevel,warning}=parseModelPattern(pattern,candidates,{allowInvalidThinkingLevelFallback:!1});if(model2){if(inferredProvider){let rawExactMatches=availableModels.filter(m2=>m2.id.toLowerCase()===cliModel.toLowerCase()&&!modelsAreEqual(m2,model2));if(rawExactMatches.length>0&&!modelRuntime.hasConfiguredAuth(model2.provider)){let authenticatedRawMatches=rawExactMatches.filter(m2=>modelRuntime.hasConfiguredAuth(m2.provider));if(authenticatedRawMatches.length===1)return{model:authenticatedRawMatches[0],thinkingLevel:void 0,warning:void 0,error:void 0}}}return{model:model2,thinkingLevel,warning,error:void 0}}if(inferredProvider){let lower=cliModel.toLowerCase(),exact=availableModels.find(m2=>m2.id.toLowerCase()===lower||`${m2.provider}/${m2.id}`.toLowerCase()===lower);if(exact)return{model:exact,warning:void 0,thinkingLevel:void 0,error:void 0};let fallback=parseModelPattern(cliModel,availableModels,{allowInvalidThinkingLevelFallback:!1});if(fallback.model)return{model:fallback.model,thinkingLevel:fallback.thinkingLevel,warning:fallback.warning,error:void 0}}if(provider2){let fallbackPattern=pattern,fallbackThinking;if(!cliThinking){let lastColon=pattern.lastIndexOf(":");if(lastColon!==-1){let suffix=pattern.substring(lastColon+1);isValidThinkingLevel(suffix)&&(fallbackPattern=pattern.substring(0,lastColon),fallbackThinking=suffix)}}let fallbackModel=buildFallbackModel(provider2,fallbackPattern,availableModels);if(fallbackModel){let requestedThinking=cliThinking??fallbackThinking,model3=requestedThinking&&requestedThinking!=="off"?{...fallbackModel,reasoning:!0}:fallbackModel,fallbackWarning=warning?`${warning} Model "${fallbackPattern}" not found for provider "${provider2}". Using custom model id.`:`Model "${fallbackPattern}" not found for provider "${provider2}". Using custom model id.`;return{model:model3,thinkingLevel:fallbackThinking,warning:fallbackWarning,error:void 0}}}let display=provider2?`${provider2}/${pattern}`:cliModel;return{model:void 0,thinkingLevel:void 0,warning,error:`Model "${display}" not found. Use --list-models to see available models.`}}async function findInitialModel(options){let{cliProvider,cliModel,scopedModels,isContinuing,defaultProvider,defaultModelId,defaultThinkingLevel,modelThinkingLevels,modelRuntime}=options,model2,thinkingLevel=DEFAULT_THINKING_LEVEL;if(cliProvider&&cliModel){let resolved=resolveCliModel({cliProvider,cliModel,modelRuntime});if(resolved.error&&(console.error(source_default.red(resolved.error)),process.exit(1)),resolved.model)return{model:resolved.model,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}if(scopedModels.length>0&&!isContinuing){let scopedModel=scopedModels[0],perModel=modelThinkingLevels?.[`${scopedModel.model.provider}/${scopedModel.model.id}`];return{model:scopedModel.model,thinkingLevel:scopedModel.thinkingLevel??perModel??defaultThinkingLevel??DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}if(defaultProvider&&defaultModelId){let found=modelRuntime.getModel(defaultProvider,defaultModelId);if(found&&modelRuntime.hasConfiguredAuth(found.provider)){model2=found;let perModel=modelThinkingLevels?.[`${defaultProvider}/${defaultModelId}`];return perModel?thinkingLevel=perModel:defaultThinkingLevel&&(thinkingLevel=defaultThinkingLevel),{model:model2,thinkingLevel,fallbackMessage:void 0}}}let availableModels=[...modelRuntime.getAvailableSnapshot()];if(availableModels.length>0){for(let provider2 of Object.keys(defaultModelPerProvider)){let defaultId=defaultModelPerProvider[provider2],match2=availableModels.find(m2=>m2.provider===provider2&&m2.id===defaultId);if(match2)return{model:match2,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}return{model:availableModels[0],thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}return{model:void 0,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}import{dirname as dirname14,join as join23}from"node:path";import{readFile as readFile2}from"node:fs/promises";function stripJsonComments(input){return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g,m2=>m2[0]==='"'?m2:"").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g,(m2,tail)=>tail??(m2[0]==='"'?m2:""))}var PercentileCutoffsSchema=typebox_exports.Object({p50:typebox_exports.Optional(typebox_exports.Number()),p75:typebox_exports.Optional(typebox_exports.Number()),p90:typebox_exports.Optional(typebox_exports.Number()),p99:typebox_exports.Optional(typebox_exports.Number())}),OpenRouterRoutingSchema=typebox_exports.Object({allow_fallbacks:typebox_exports.Optional(typebox_exports.Boolean()),require_parameters:typebox_exports.Optional(typebox_exports.Boolean()),data_collection:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("deny"),typebox_exports.Literal("allow")])),zdr:typebox_exports.Optional(typebox_exports.Boolean()),enforce_distillable_text:typebox_exports.Optional(typebox_exports.Boolean()),order:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),only:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),ignore:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),quantizations:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),sort:typebox_exports.Optional(typebox_exports.Union([typebox_exports.String(),typebox_exports.Object({by:typebox_exports.Optional(typebox_exports.String()),partition:typebox_exports.Optional(typebox_exports.Union([typebox_exports.String(),typebox_exports.Null()]))})])),max_price:typebox_exports.Optional(typebox_exports.Object({prompt:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),completion:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),image:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),audio:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),request:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()]))})),preferred_min_throughput:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),PercentileCutoffsSchema])),preferred_max_latency:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),PercentileCutoffsSchema]))}),VercelGatewayRoutingSchema=typebox_exports.Object({only:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),order:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String()))}),ThinkingLevelMapValueSchema=typebox_exports.Union([typebox_exports.String(),typebox_exports.Null()]),ThinkingLevelMapSchema=typebox_exports.Object({off:typebox_exports.Optional(ThinkingLevelMapValueSchema),minimal:typebox_exports.Optional(ThinkingLevelMapValueSchema),low:typebox_exports.Optional(ThinkingLevelMapValueSchema),medium:typebox_exports.Optional(ThinkingLevelMapValueSchema),high:typebox_exports.Optional(ThinkingLevelMapValueSchema),xhigh:typebox_exports.Optional(ThinkingLevelMapValueSchema),max:typebox_exports.Optional(ThinkingLevelMapValueSchema)}),ChatTemplateKwargScalarSchema=typebox_exports.Union([typebox_exports.String(),typebox_exports.Number(),typebox_exports.Boolean(),typebox_exports.Null()]),ChatTemplateKwargVariableSchema=typebox_exports.Object({$var:typebox_exports.Union([typebox_exports.Literal("thinking.enabled"),typebox_exports.Literal("thinking.effort")]),omitWhenOff:typebox_exports.Optional(typebox_exports.Boolean())}),ChatTemplateKwargSchema=typebox_exports.Union([ChatTemplateKwargScalarSchema,ChatTemplateKwargVariableSchema]),OpenAICompletionsCompatSchema=typebox_exports.Object({supportsStore:typebox_exports.Optional(typebox_exports.Boolean()),supportsDeveloperRole:typebox_exports.Optional(typebox_exports.Boolean()),supportsReasoningEffort:typebox_exports.Optional(typebox_exports.Boolean()),supportsUsageInStreaming:typebox_exports.Optional(typebox_exports.Boolean()),supportsFinishReason:typebox_exports.Optional(typebox_exports.Boolean()),maxTokensField:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("max_completion_tokens"),typebox_exports.Literal("max_tokens")])),requiresToolResultName:typebox_exports.Optional(typebox_exports.Boolean()),requiresAssistantAfterToolResult:typebox_exports.Optional(typebox_exports.Boolean()),requiresThinkingAsText:typebox_exports.Optional(typebox_exports.Boolean()),requiresReasoningContentOnAssistantMessages:typebox_exports.Optional(typebox_exports.Boolean()),thinkingFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openrouter"),typebox_exports.Literal("together"),typebox_exports.Literal("baseten"),typebox_exports.Literal("deepseek"),typebox_exports.Literal("zai"),typebox_exports.Literal("qwen"),typebox_exports.Literal("chat-template"),typebox_exports.Literal("qwen-chat-template"),typebox_exports.Literal("string-thinking"),typebox_exports.Literal("ant-ling")])),chatTemplateKwargs:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ChatTemplateKwargSchema)),chatTemplateArgs:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ChatTemplateKwargSchema)),cacheControlFormat:typebox_exports.Optional(typebox_exports.Literal("anthropic")),openRouterRouting:typebox_exports.Optional(OpenRouterRoutingSchema),vercelGatewayRouting:typebox_exports.Optional(VercelGatewayRoutingSchema),supportsOpenAIGrammarTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictMode:typebox_exports.Optional(typebox_exports.Boolean()),sendSessionAffinityHeaders:typebox_exports.Optional(typebox_exports.Boolean()),deferredToolsMode:typebox_exports.Optional(typebox_exports.Literal("kimi")),sessionAffinityFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openai-nosession"),typebox_exports.Literal("openrouter")])),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean())}),OpenAIResponsesCompatSchema=typebox_exports.Object({supportsDeveloperRole:typebox_exports.Optional(typebox_exports.Boolean()),sessionAffinityFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openai-nosession"),typebox_exports.Literal("openrouter")])),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictMode:typebox_exports.Optional(typebox_exports.Boolean()),supportsOpenAIGrammarTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsAdditionalTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsToolSearch:typebox_exports.Optional(typebox_exports.Boolean())}),AnthropicMessagesCompatSchema=typebox_exports.Object({supportsEagerToolInputStreaming:typebox_exports.Optional(typebox_exports.Boolean()),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean()),sendSessionAffinityHeaders:typebox_exports.Optional(typebox_exports.Boolean()),supportsCacheControlOnTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsTemperature:typebox_exports.Optional(typebox_exports.Boolean()),forceAdaptiveThinking:typebox_exports.Optional(typebox_exports.Boolean()),allowEmptySignature:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsToolReferences:typebox_exports.Optional(typebox_exports.Boolean())}),ProviderCompatSchema=typebox_exports.Union([OpenAICompletionsCompatSchema,OpenAIResponsesCompatSchema,AnthropicMessagesCompatSchema]),ModelCostRatesSchema={input:typebox_exports.Number(),output:typebox_exports.Number(),cacheRead:typebox_exports.Number(),cacheWrite:typebox_exports.Number()},ModelCostTierSchema=typebox_exports.Object({inputTokensAbove:typebox_exports.Number(),...ModelCostRatesSchema}),ModelCostSchema=typebox_exports.Object({...ModelCostRatesSchema,tiers:typebox_exports.Optional(typebox_exports.Array(ModelCostTierSchema))}),ModelDefinitionSchema=typebox_exports.Object({id:typebox_exports.String({minLength:1}),name:typebox_exports.Optional(typebox_exports.String({minLength:1})),api:typebox_exports.Optional(typebox_exports.String({minLength:1})),baseUrl:typebox_exports.Optional(typebox_exports.String({minLength:1})),reasoning:typebox_exports.Optional(typebox_exports.Boolean()),thinkingLevelMap:typebox_exports.Optional(ThinkingLevelMapSchema),input:typebox_exports.Optional(typebox_exports.Array(typebox_exports.Union([typebox_exports.Literal("text"),typebox_exports.Literal("image")]))),cost:typebox_exports.Optional(ModelCostSchema),contextWindow:typebox_exports.Optional(typebox_exports.Number()),maxTokens:typebox_exports.Optional(typebox_exports.Number()),samplingParams:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.Unknown())),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema)}),ModelOverrideSchema=typebox_exports.Object({name:typebox_exports.Optional(typebox_exports.String({minLength:1})),reasoning:typebox_exports.Optional(typebox_exports.Boolean()),thinkingLevelMap:typebox_exports.Optional(ThinkingLevelMapSchema),input:typebox_exports.Optional(typebox_exports.Array(typebox_exports.Union([typebox_exports.Literal("text"),typebox_exports.Literal("image")]))),cost:typebox_exports.Optional(typebox_exports.Object({input:typebox_exports.Optional(typebox_exports.Number()),output:typebox_exports.Optional(typebox_exports.Number()),cacheRead:typebox_exports.Optional(typebox_exports.Number()),cacheWrite:typebox_exports.Optional(typebox_exports.Number()),tiers:typebox_exports.Optional(typebox_exports.Array(ModelCostTierSchema))})),contextWindow:typebox_exports.Optional(typebox_exports.Number()),maxTokens:typebox_exports.Optional(typebox_exports.Number()),samplingParams:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.Unknown())),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema)}),ProviderConfigSchema=typebox_exports.Object({name:typebox_exports.Optional(typebox_exports.String({minLength:1})),baseUrl:typebox_exports.Optional(typebox_exports.String({minLength:1})),apiKey:typebox_exports.Optional(typebox_exports.String({minLength:1})),api:typebox_exports.Optional(typebox_exports.String({minLength:1})),oauth:typebox_exports.Optional(typebox_exports.Literal("radius")),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema),authHeader:typebox_exports.Optional(typebox_exports.Boolean()),models:typebox_exports.Optional(typebox_exports.Array(ModelDefinitionSchema)),modelOverrides:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ModelOverrideSchema))}),ModelsConfigSchema=typebox_exports.Object({providers:typebox_exports.Record(typebox_exports.String(),ProviderConfigSchema)}),validateModelsConfig=Compile(ModelsConfigSchema);function formatValidationPath2(error){if(error.keyword==="required"){let requiredProperty=error.params.requiredProperties?.[0];if(requiredProperty){let basePath=error.instancePath.replace(/^\//,"").replace(/\//g,".");return basePath?`${basePath}.${requiredProperty}`:requiredProperty}}return error.instancePath.replace(/^\//,"").replace(/\//g,".")||"root"}function deepFreeze(value){if(typeof value!="object"||value===null||Object.isFrozen(value))return value;for(let child of Object.values(value))deepFreeze(child);return Object.freeze(value)}var ModelConfig=class _ModelConfig{constructor(providers,error){this.providers=providers,this.error=error}static async load(modelsJsonPath){if(!modelsJsonPath)return new _ModelConfig(new Map);let path14=normalizePath(modelsJsonPath),content;try{content=await readFile2(path14,"utf-8")}catch(error){return error.code==="ENOENT"?new _ModelConfig(new Map):new _ModelConfig(new Map,`Failed to load models.json: ${error instanceof Error?error.message:error}
1249
+ `),images.length===0&&(images=void 0)}await this.prompt(text,{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._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.abortRetry(),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source2){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source:source2})}async setModel(model2,options={}){if(!await this._modelRuntime.checkAuth(model2.provider))throw new Error(`No API key for ${model2.provider}/${model2.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model2);this.agent.state.model=model2,this.sessionManager.appendModelChange(model2.provider,model2.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model2.provider,model2.id),this._addPersistedDefaultToNonEmptyScope(model2)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model2,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model2){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model2)))return;this._scopedModels=[...this._scopedModels,{model:model2}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model2.provider}/${model2.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(model2=>`${model2.provider}\0${model2.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 compact(preparation,requestModel,apiKey,headers,customInstructions,signal,this.thinkingLevel,this.agent.streamFunction,env2,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}async compact(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1;try{if(!this.model)throw new Error(formatNoModelSelectedMessage());let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(this.model),pathEntries=this.sessionManager.getBranch(),settings2=this.settingsManager.getCompactionSettings(),preparation=prepareCompaction(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 result=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result?.cancel)throw new Error("Compaction cancelled");result?.compaction&&(extensionCompaction=result.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 result=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,customInstructions,this._compactionAbortController.signal,env2,"manual");summary=result.summary,firstKeptEntryId=result.firstKeptEntryId,tokensBefore=result.tokensBefore,usage=result.usage,details=result.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(),sessionContext=this.sessionManager.buildSessionContext();this.agent.state.messages=sessionContext.messages;let estimatedTokensAfter=estimateMessagesTokens(sessionContext.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._compactionAbortController=void 0,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=message==="Compaction cancelled"||error instanceof Error&&error.name==="AbortError",errorMessage2=aborted?void 0:`Compaction failed: ${message}`;throw this._compactionAbortController=void 0,this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage2}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage2,aborted,willRetry:!1,fromExtension}),error}finally{this._compactionAbortController=void 0}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0){let settings2=this.settingsManager.getCompactionSettings();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 contextOverflow=sameModel&&isContextOverflow(assistantMessage,contextWindow),recoverableLength=sameModel&&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 errorMessage2=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:errorMessage2}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage2,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0;let messages=this.agent.state.messages;return messages.length>0&&messages[messages.length-1].role==="assistant"&&(this.agent.state.messages=messages.slice(0,-1)),await this._runAutoCompaction("overflow",willRetry)}let contextTokens,directContextTokens=assistantMessage.usage?calculateContextTokens(assistantMessage.usage):0;if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens(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 shouldCompact(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){let settings2=this.settingsManager.getCompactionSettings(),started=!1,fromExtension=!1;try{if(!this.model)return!1;let{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(this.model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)return!1;this._emit({type:"compaction_start",reason}),this._autoCompactionAbortController=new AbortController,started=!0;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:this._autoCompactionAbortController.signal});if(extensionResult?.cancel)return this._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),await this._emitSessionCompactFailed({reason,aborted:!0,willRetry:!1,fromExtension:!1}),!1;extensionResult?.compaction&&(extensionCompaction=extensionResult.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 compactResult=await this._runDefaultCompaction(preparation,requestModel,apiKey,headers,void 0,this._autoCompactionAbortController.signal,env2,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}if(this._autoCompactionAbortController.signal.aborted)return this._emit({type:"compaction_end",reason,result:void 0,aborted:!0,willRetry:!1}),await this._emitSessionCompactFailed({reason,aborted:!0,willRetry:!1,fromExtension}),!1;this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries(),sessionContext=this.sessionManager.buildSessionContext();this.agent.state.messages=sessionContext.messages;let estimatedTokensAfter=estimateMessagesTokens(sessionContext.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 result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};if(this._emit({type:"compaction_end",reason,result,aborted:!1,willRetry}),willRetry){let messages=this.agent.state.messages,lastMsg=messages[messages.length-1];return lastMsg?.role==="assistant"&&(lastMsg.stopReason==="error"||lastMsg.stopReason==="length")&&(this.agent.state.messages=messages.slice(0,-1)),!0}return this.agent.hasQueuedMessages()}catch(error){let errorMessage2=error instanceof Error?error.message:"compaction failed";if(started){let formattedErrorMessage=reason==="overflow"?`Context overflow recovery failed: ${errorMessage2}`:`Auto-compaction failed: ${errorMessage2}`;this._emit({type:"compaction_end",reason,result:void 0,aborted:!1,willRetry:!1,errorMessage:formattedErrorMessage}),await this._emitSessionCompactFailed({reason,errorMessage:formattedErrorMessage,aborted:!1,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController=void 0}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){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.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup"),await bindings.onResourcesExtended?.(),await this._extensionRunner.emit(this._sessionStartEvent)}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._baseSystemPrompt=this._rebuildSystemPrompt(this.getActiveToolNames()),this.agent.state.systemPrompt=this._baseSystemPrompt}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source2=this.getExtensionSourceLabel(entry.extensionPath),baseDir=entry.extensionPath.startsWith("<")?void 0:dirname12(entry.extensionPath);return{path:entry.path,metadata:{source:source2,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return extensionPath.startsWith("<")?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(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 model2=>this._modelRuntime.hasConfiguredAuth(model2.provider)?(await this.setModel(model2),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{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(),compact:options=>{(async()=>{try{let result=await this.compact(options?.customInstructions);options?.onComplete?.(result)}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:provider2=>{this._modelRuntime.registerNativeProvider(provider2),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,value]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value);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){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate(),await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._buildRuntime({activeToolNames:this.getActiveToolNames(),flagValues:previousFlagValues,includeAllExtensionTools:!0}),(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:message.diagnostics?.some(diagnostic=>diagnostic.type==="kpi_account_failover")?!0:isRetryableAssistantError(message)}_summarizationRetryCallbacks(source2){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage2)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage2})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source2})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}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=settings2.baseDelayMs*2**(this._retryAttempt-1);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"});let messages=this.agent.state.messages;messages.length>0&&messages[messages.length-1].role==="assistant"&&(this.agent.state.messages=messages.slice(0,-1)),this._retryAbortController=new AbortController;try{await sleep2(delayMs,this._retryAbortController.signal)}catch{let attempt2=this._retryAttempt;return this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"}),!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}
1250
+ ${command}`:command;try{let result=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,result,options),result}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result,options){let bashMessage={role:"bashExecution",command,output:result.output,exitCode:result.exitCode,cancelled:result.cancelled,truncated:result.truncated,fullOutputPath:result.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.agent.state.messages.push(bashMessage),this.sessionManager.appendMessage(bashMessage))}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.agent.state.messages.push(bashMessage),this.sessionManager.appendMessage(bashMessage);this._pendingBashMessages=[]}}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.");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}=collectEntriesForBranchSummary(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};this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result?.cancel)return{cancelled:!0};result?.summary&&options.summarize&&(extensionSummary=result.summary,fromExtension=!0),result?.customInstructions!==void 0&&(customInstructions=result.customInstructions),result?.replaceInstructions!==void 0&&(replaceInstructions=result.replaceInstructions),result?.label!==void 0&&(label=result.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let model2=this.model,{model:requestModel,apiKey,headers,env:env2}=await this._getSummarizationRequestAuth(model2),branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result=await generateBranchSummary(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(result.aborted)return{cancelled:!0,aborted:!0};if(result.error)throw new Error(result.error);summaryText=result.summary,summaryUsage=result.usage,summaryDetails={readFiles:result.readFiles||[],modifiedFiles:result.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;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);label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label);let sessionContext=this.sessionManager.buildSessionContext();return this.agent.state.messages=sessionContext.messages,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}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text=contentText(entry.message.content,"");text&&result.push({entryId:entry.id,text})}return result}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals();for(let entry of this.sessionManager.getEntries()){if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage&&addUsageToTotals(usageTotals,entry.usage),entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++,message.usage&&addUsageToTotals(usageTotals,message.usage);else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c2=>c2.type==="toolCall").length),addUsageToTotals(usageTotals,assistantMsg.usage)}}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 model2=this.model;if(!model2)return;let contextWindow=model2.contextWindow??0;if(contextWindow<=0)return;let branchEntries=this.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branchEntries);if(latestCompaction){let compactionIndex=branchEntries.lastIndexOf(latestCompaction),hasPostCompactionUsage=!1;for(let i=branchEntries.length-1;i>compactionIndex;i--){let entry=branchEntries[i];if(entry.type==="message"&&entry.message.role==="assistant"){let assistant=entry.message;if(assistant.stopReason!=="aborted"&&assistant.stopReason!=="error"&&calculateContextTokens(assistant.usage)>0){hasPostCompactionUsage=!0;break}}}if(!hasPostCompactionUsage)return{tokens:null,contextWindow,percent:null}}let estimate=estimateContextTokens(this.messages),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)}getLastAssistantError(){let lastAssistant=this.messages.slice().reverse().find(message=>message.role==="assistant");if(lastAssistant?.stopReason==="error")return lastAssistant.errorMessage?.trim()||"Provider request failed without an error message"}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 text="";for(let content of lastAssistant.content)content.type==="text"&&(text+=content.text);return text.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}};var import_proper_lockfile=__toESM(require_proper_lockfile(),1);import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync8,writeFileSync as writeFileSync5}from"fs";import{dirname as dirname13,join as join21}from"path";import{setTimeout as sleep3}from"timers/promises";function abortReason(signal){if(signal.reason!==void 0)return signal.reason;let error=new Error("The operation was aborted");return error.name="AbortError",error}function operationSignal(signal){return signal??new AbortController().signal}function raceWithAbortSignal(operation,signal){return signal?signal.aborted?(operation.catch(()=>{}),Promise.reject(abortReason(signal))):new Promise((resolve26,reject)=>{let settled=!1,cleanup=()=>signal.removeEventListener("abort",onAbort),onAbort=()=>{settled||(settled=!0,cleanup(),reject(abortReason(signal)))};signal.addEventListener("abort",onAbort,{once:!0}),operation.then(value=>{settled||(settled=!0,cleanup(),resolve26(value))},error=>{settled||(settled=!0,cleanup(),reject(error))}),signal.aborted&&onAbort()}):operation}var AUTH_FILE_WRITE_OPTIONS={encoding:"utf-8",mode:384},sharedAuthFileReadState,FileAuthStorageBackend=class{constructor(authPath=join21(getAgentDir(),"auth.json")){this.authPath=normalizePath(authPath)}ensureParentDir(){let dir=dirname13(this.authPath);existsSync11(dir)||mkdirSync5(dir,{recursive:!0,mode:448})}ensureFileExists(){existsSync11(this.authPath)||writeFileSync5(this.authPath,"{}",AUTH_FILE_WRITE_OPTIONS)}acquireLockSyncWithRetry(path14){let lastError;for(let attempt2=1;attempt2<=10;attempt2++)try{return import_proper_lockfile.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 auth storage lock")}withLock(fn){this.ensureParentDir(),this.ensureFileExists();let release;try{release=this.acquireLockSyncWithRetry(this.authPath);let current=existsSync11(this.authPath)?readFileSync8(this.authPath,"utf-8"):void 0,{result,next}=fn(current);return next!==void 0&&writeFileSync5(this.authPath,next,AUTH_FILE_WRITE_OPTIONS),result}finally{release&&release()}}async acquireLockAsync(signal,onCompromised){let deadline=Date.now()+3e4,retry=0;for(;;){signal?.throwIfAborted();let release;try{release=await import_proper_lockfile.default.lock(this.authPath,{realpath:!1,retries:0,stale:3e4,onCompromised})}catch(error){signal?.throwIfAborted();let code=typeof error=="object"&&error!==null&&"code"in error?String(error.code):void 0,remainingMs=deadline-Date.now();if(code!=="ELOCKED"||remainingMs<=0)throw error;let baseDelayMs=Math.min(10*2**retry,2e3/2);retry++;let delayMs=Math.min(Math.round(baseDelayMs*(1+Math.random())),remainingMs);signal?await sleep3(delayMs,void 0,{signal}):await sleep3(delayMs);continue}return signal?.aborted&&(await release(),signal.throwIfAborted()),release}}async withLockAsync(fn,options){options?.signal?.throwIfAborted(),this.ensureParentDir(),this.ensureFileExists();let release,lockCompromised=!1,lockCompromisedError,throwIfCompromised=()=>{if(lockCompromised)throw lockCompromisedError??new Error("Auth storage lock was compromised")};try{release=await this.acquireLockAsync(options?.signal,error=>{lockCompromised=!0,lockCompromisedError=error}),throwIfCompromised(),options?.signal?.throwIfAborted();let current=existsSync11(this.authPath)?readFileSync8(this.authPath,"utf-8"):void 0,{result,next}=await fn(current);return throwIfCompromised(),options?.signal?.throwIfAborted(),next!==void 0&&writeFileSync5(this.authPath,next,AUTH_FILE_WRITE_OPTIONS),throwIfCompromised(),result}finally{if(release)try{await release()}catch{}}}},ReadOnlyAuthStorage=class{constructor(authPath=join21(getAgentDir(),"auth.json")){this.authPath=normalizePath(authPath)}load(){if(this.data)return this.data;let parsed;try{parsed=JSON.parse(stripBom(readFileSync8(this.authPath,"utf-8")))}catch(error){if(error.code==="ENOENT")return this.data={},this.data;throw new Error(`Failed to read auth.json: ${error instanceof Error?error.message:String(error)}`)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new Error("Invalid auth.json: expected an object");for(let[providerId,credential]of Object.entries(parsed)){if(typeof credential!="object"||credential===null||Array.isArray(credential))throw new Error(`Invalid auth.json credential for provider "${providerId}"`);let value=credential;if(value.type==="api_key"){let validKey=value.key===void 0||typeof value.key=="string",validEnv=value.env===void 0||typeof value.env=="object"&&value.env!==null&&!Array.isArray(value.env)&&Object.values(value.env).every(entry=>typeof entry=="string");if(validKey&&validEnv)continue}else if(value.type==="oauth"&&typeof value.access=="string"&&typeof value.refresh=="string"&&typeof value.expires=="number"&&Number.isFinite(value.expires))continue;throw new Error(`Invalid auth.json credential for provider "${providerId}"`)}return this.data=parsed,this.data}async read(providerId,options){options?.signal?.throwIfAborted();let credential=this.load()[providerId];if(options?.signal?.throwIfAborted(),!!credential)return credential.type!=="api_key"||!credential.key||isCommandConfigValue(credential.key)?structuredClone(credential):{...credential,key:resolveConfigValue(credential.key,credential.env)}}async list(options){options?.signal?.throwIfAborted();let credentials=Object.entries(this.load()).map(([providerId,credential])=>({providerId,type:credential.type}));return options?.signal?.throwIfAborted(),credentials}async modify(_providerId,_fn,_options){throw new Error("Read-only credential storage cannot modify auth.json")}async delete(_providerId,_options){throw new Error("Read-only credential storage cannot modify auth.json")}},InMemoryAuthStorageBackend=class{constructor(){this.asyncChain=Promise.resolve()}withLock(fn){let{result,next}=fn(this.value);return next!==void 0&&(this.value=next),result}withLockAsync(fn,options){let previous=this.asyncChain,operation=(async()=>{await previous.catch(()=>{}),options?.signal?.throwIfAborted();let{result,next}=await fn(this.value);return options?.signal?.throwIfAborted(),next!==void 0&&(this.value=next),result})();return this.asyncChain=operation.catch(()=>{}),raceWithAbortSignal(operation,options?.signal)}},AuthStorage=class _AuthStorage{constructor(storage,authPath){if(this.storage=storage,this.authPath=authPath,this.readState=authPath&&sharedAuthFileReadState?.authPath===authPath?sharedAuthFileReadState.readState:{data:{}},authPath&&!sharedAuthFileReadState&&(sharedAuthFileReadState={authPath,readState:this.readState}),authPath){let revision=getFileRevision(authPath);if(revision!==void 0&&revision===this.readState.revision)return}this.reload()}static create(authPath=join21(getAgentDir(),"auth.json")){let normalizedAuthPath=normalizePath(authPath);return new _AuthStorage(new FileAuthStorageBackend(normalizedAuthPath),normalizedAuthPath)}static fromStorage(storage){return new _AuthStorage(storage)}static inMemory(data={}){let storage=new InMemoryAuthStorageBackend;return storage.withLock(()=>({result:void 0,next:JSON.stringify(data,null,2)})),_AuthStorage.fromStorage(storage)}parseStorageData(content){return content?JSON.parse(stripBom(content)):{}}updateReadState(data,revision){this.readState.data=data,this.readState.revision=revision}reload(){let content,revision;try{this.storage.withLock(current=>(content=current,revision=this.authPath?getFileRevision(this.authPath):void 0,{result:void 0})),this.updateReadState(this.parseStorageData(content),revision)}catch{}}async reloadFromStorageAsync(options){return this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content),revision=this.authPath?getFileRevision(this.authPath):void 0;return this.updateReadState(currentData,revision),{result:currentData}},options)}async readLatestData(options){if(options?.signal?.throwIfAborted(),!this.authPath){let reload2=this.reloadFromStorageAsync(options);return options?.signal?reload2:reload2.catch(()=>this.readState.data)}let revision=getFileRevision(this.authPath);if(revision!==void 0&&revision===this.readState.revision)return this.readState.data;if(!this.readState.reload){let controller=new AbortController,reload2={controller,promise:this.reloadFromStorageAsync({signal:controller.signal}),readers:0};this.readState.reload=reload2,reload2.promise.then(()=>{this.readState.reload===reload2&&(this.readState.reload=void 0)},()=>{this.readState.reload===reload2&&(this.readState.reload=void 0)})}let reload=this.readState.reload;reload.readers++;try{let result=raceWithAbortSignal(reload.promise,options?.signal);return options?.signal?await result:await result.catch(()=>this.readState.data)}finally{reload.readers--,reload.readers===0&&this.readState.reload===reload&&(this.readState.reload=void 0,reload.controller.abort())}}async read(provider2,options){let credential=(await this.readLatestData(options))[provider2];return options?.signal?.throwIfAborted(),credential?.type!=="api_key"||credential.key===void 0?credential:{...credential,key:resolveConfigValue(credential.key,credential.env)}}async modify(provider2,fn,options){let latestData=this.readState.data,revision,result=await this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content),next=await fn(currentData[provider2]);if(next===void 0)return latestData=currentData,revision=this.authPath?getFileRevision(this.authPath):void 0,{result:currentData[provider2]};let merged={...currentData,[provider2]:next};return latestData=merged,{result:next,next:JSON.stringify(merged,null,2)}},options);return this.updateReadState(latestData,revision),result}async delete(provider2,options){let latestData=this.readState.data;await this.storage.withLockAsync(async content=>{let currentData=this.parseStorageData(content);return delete currentData[provider2],latestData=currentData,{result:void 0,next:JSON.stringify(currentData,null,2)}},options),this.updateReadState(latestData)}async list(options){let entries=Object.entries(await this.readLatestData(options));return options?.signal?.throwIfAborted(),entries.map(([providerId,credential])=>({providerId,type:credential.type}))}};function readStoredCredential(providerId,authPath=join21(getAgentDir(),"auth.json")){try{return JSON.parse(stripBom(readFileSync8(normalizePath(authPath),"utf-8")))[providerId]}catch{return}}var balanced=(a,b2,str2)=>{let ma=a instanceof RegExp?maybeMatch(a,str2):a,mb=b2 instanceof RegExp?maybeMatch(b2,str2):b2,r=ma!==null&&mb!=null&&range(ma,mb,str2);return r&&{start:r[0],end:r[1],pre:str2.slice(0,r[0]),body:str2.slice(r[0]+ma.length,r[1]),post:str2.slice(r[1]+mb.length)}},maybeMatch=(reg,str2)=>{let m2=str2.match(reg);return m2?m2[0]:null},range=(a,b2,str2)=>{let begs,beg,left,right,result,ai=str2.indexOf(a),bi=str2.indexOf(b2,ai+1),i=ai;if(ai>=0&&bi>0){if(a===b2)return[ai,bi];for(begs=[],left=str2.length;i>=0&&!result;){if(i===ai)begs.push(i),ai=str2.indexOf(a,i+1);else if(begs.length===1){let r=begs.pop();r!==void 0&&(result=[r,bi])}else beg=begs.pop(),beg!==void 0&&beg<left&&(left=beg,right=bi),bi=str2.indexOf(b2,i+1);i=ai<bi&&ai>=0?ai:bi}begs.length&&right!==void 0&&(result=[left,right])}return result};var escSlash="\0SLASH"+Math.random()+"\0",escOpen="\0OPEN"+Math.random()+"\0",escClose="\0CLOSE"+Math.random()+"\0",escComma="\0COMMA"+Math.random()+"\0",escPeriod="\0PERIOD"+Math.random()+"\0",escSlashPattern=new RegExp(escSlash,"g"),escOpenPattern=new RegExp(escOpen,"g"),escClosePattern=new RegExp(escClose,"g"),escCommaPattern=new RegExp(escComma,"g"),escPeriodPattern=new RegExp(escPeriod,"g"),slashPattern=/\\\\/g,openPattern=/\\{/g,closePattern=/\\}/g,commaPattern=/\\,/g,periodPattern=/\\\./g,EXPANSION_MAX=1e5,EXPANSION_MAX_LENGTH=4e6;function numeric(str2){return isNaN(str2)?str2.charCodeAt(0):parseInt(str2,10)}function escapeBraces(str2){return str2.replace(slashPattern,escSlash).replace(openPattern,escOpen).replace(closePattern,escClose).replace(commaPattern,escComma).replace(periodPattern,escPeriod)}function unescapeBraces(str2){return str2.replace(escSlashPattern,"\\").replace(escOpenPattern,"{").replace(escClosePattern,"}").replace(escCommaPattern,",").replace(escPeriodPattern,".")}function parseCommaParts(str2){if(!str2)return[""];let parts=[],m2=balanced("{","}",str2);if(!m2)return str2.split(",");let{pre,body,post}=m2,p=pre.split(",");p[p.length-1]+="{"+body+"}";let postParts=parseCommaParts(post);return post.length&&(p[p.length-1]+=postParts.shift(),p.push.apply(p,postParts)),parts.push.apply(parts,p),parts}function expand(str2,options={}){if(!str2)return[];let{max=EXPANSION_MAX,maxLength=EXPANSION_MAX_LENGTH}=options;return str2.slice(0,2)==="{}"&&(str2="\\{\\}"+str2.slice(2)),expand_(escapeBraces(str2),max,maxLength,!0).map(unescapeBraces)}function embrace(str2){return"{"+str2+"}"}function isPadded(el){return/^-?0\d/.test(el)}function lte(i,y2){return i<=y2}function gte(i,y2){return i>=y2}function combine(acc,pre,values,max,maxLength,dropEmpties){let out=[],length=0;for(let a=0;a<acc.length;a++)for(let v2=0;v2<values.length;v2++){if(out.length>=max)return out;let expansion=acc[a]+pre+values[v2];if(!(dropEmpties&&!expansion)){if(length+expansion.length>maxLength)return out;out.push(expansion),length+=expansion.length}}return out}function expandSequence(body,isAlphaSequence,max,maxLength){let n=body.split(/\.\./),N=[];if(n[0]===void 0||n[1]===void 0)return N;let x2=numeric(n[0]),y2=numeric(n[1]),width=Math.max(n[0].length,n[1].length),incr=n.length===3&&n[2]!==void 0?Math.max(Math.abs(numeric(n[2])),1):1,test=lte;y2<x2&&(incr*=-1,test=gte);let pad2=n.some(isPadded),length=0;for(let i=x2;test(i,y2)&&N.length<max;i+=incr){let c2;if(isAlphaSequence)c2=String.fromCharCode(i),c2==="\\"&&(c2="");else if(c2=String(i),pad2){let need=width-c2.length;if(need>0){let z2=new Array(need+1).join("0");i<0?c2="-"+z2+c2.slice(1):c2=z2+c2}}if(length+c2.length>maxLength)break;N.push(c2),length+=c2.length}return N}function expand_(str2,max,maxLength,isTop){let acc=[""],dropEmpties=!1,firstGroup=!0;for(;;){let m2=balanced("{","}",str2);if(!m2)return combine(acc,str2,[""],max,maxLength,dropEmpties);let pre=m2.pre;if(/\$$/.test(pre)){if(acc=combine(acc,pre+"{"+m2.body+"}",[""],max,maxLength,dropEmpties&&!m2.post.length),firstGroup=!1,!m2.post.length)break;str2=m2.post;continue}let isNumericSequence=/^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m2.body),isAlphaSequence=/^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m2.body),isSequence=isNumericSequence||isAlphaSequence,isOptions=m2.body.indexOf(",")>=0;if(!isSequence&&!isOptions){if(m2.post.match(/,(?!,).*\}/)){str2=m2.pre+"{"+m2.body+escClose+m2.post,isTop=!0;continue}return combine(acc,pre+"{"+m2.body+"}"+m2.post,[""],max,maxLength,dropEmpties)}firstGroup&&(dropEmpties=isTop&&!isSequence,firstGroup=!1);let values;if(isSequence)values=expandSequence(m2.body,isAlphaSequence,max,maxLength);else{let n=parseCommaParts(m2.body);if(n.length===1&&n[0]!==void 0&&(n=expand_(n[0],max,maxLength,!1).map(embrace),n.length===1)){if(acc=combine(acc,pre+n[0],[""],max,maxLength,dropEmpties&&!m2.post.length),!m2.post.length)break;str2=m2.post;continue}let dropsEmpties=dropEmpties&&!m2.post.length&&!pre;for(let d=0;dropsEmpties&&d<acc.length;d++)acc[d]&&(dropsEmpties=!1);values=[];let valuesLength=0;outer:for(let j2=0;j2<n.length;j2++){let expanded=expand_(n[j2],max,maxLength,!1);for(let k2=0;k2<expanded.length;k2++){let v2=expanded[k2];if(!(dropsEmpties&&!v2)){if(values.length>=max||valuesLength+v2.length>maxLength)break outer;values.push(v2),valuesLength+=v2.length}}}}if(acc=combine(acc,pre,values,max,maxLength,dropEmpties&&!m2.post.length),!m2.post.length)break;str2=m2.post}return acc}var assertValidPattern=pattern=>{if(typeof pattern!="string")throw new TypeError("invalid pattern");if(pattern.length>65536)throw new TypeError("pattern is too long")};var posixClasses={"[:alnum:]":["\\p{L}\\p{Nl}\\p{Nd}",!0],"[:alpha:]":["\\p{L}\\p{Nl}",!0],"[:ascii:]":["\\x00-\\x7f",!1],"[:blank:]":["\\p{Zs}\\t",!0],"[:cntrl:]":["\\p{Cc}",!0],"[:digit:]":["\\p{Nd}",!0],"[:graph:]":["\\p{Z}\\p{C}",!0,!0],"[:lower:]":["\\p{Ll}",!0],"[:print:]":["\\p{C}",!0],"[:punct:]":["\\p{P}",!0],"[:space:]":["\\p{Z}\\t\\r\\n\\v\\f",!0],"[:upper:]":["\\p{Lu}",!0],"[:word:]":["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}",!0],"[:xdigit:]":["A-Fa-f0-9",!1]},braceEscape=s=>s.replace(/[[\]\\-]/g,"\\$&"),regexpEscape=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),rangesToString=ranges=>ranges.join(""),parseClass=(glob,position)=>{let pos=position;if(glob.charAt(pos)!=="[")throw new Error("not in a brace expression");let ranges=[],negs=[],i=pos+1,sawStart=!1,uflag=!1,escaping=!1,negate=!1,endPos=pos,rangeStart="";WHILE:for(;i<glob.length;){let c2=glob.charAt(i);if((c2==="!"||c2==="^")&&i===pos+1){negate=!0,i++;continue}if(c2==="]"&&sawStart&&!escaping){endPos=i+1;break}if(sawStart=!0,c2==="\\"&&!escaping){escaping=!0,i++;continue}if(c2==="["&&!escaping){for(let[cls,[unip,u,neg]]of Object.entries(posixClasses))if(glob.startsWith(cls,i)){if(rangeStart)return["$.",!1,glob.length-pos,!0];i+=cls.length,neg?negs.push(unip):ranges.push(unip),uflag=uflag||u;continue WHILE}}if(escaping=!1,rangeStart){c2>rangeStart?ranges.push(braceEscape(rangeStart)+"-"+braceEscape(c2)):c2===rangeStart&&ranges.push(braceEscape(c2)),rangeStart="",i++;continue}if(glob.startsWith("-]",i+1)){ranges.push(braceEscape(c2+"-")),i+=2;continue}if(glob.startsWith("-",i+1)){rangeStart=c2,i+=2;continue}ranges.push(braceEscape(c2)),i++}if(endPos<i)return["",!1,0,!1];if(!ranges.length&&!negs.length)return["$.",!1,glob.length-pos,!0];if(negs.length===0&&ranges.length===1&&/^\\?.$/.test(ranges[0])&&!negate){let r=ranges[0].length===2?ranges[0].slice(-1):ranges[0];return[regexpEscape(r),!1,endPos-pos,!1]}let sranges="["+(negate?"^":"")+rangesToString(ranges)+"]",snegs="["+(negate?"":"^")+rangesToString(negs)+"]";return[ranges.length&&negs.length?"("+sranges+"|"+snegs+")":ranges.length?sranges:snegs,uflag,endPos-pos,!0]};var unescape=(s,{windowsPathsNoEscape=!1,magicalBraces=!0}={})=>magicalBraces?windowsPathsNoEscape?s.replace(/\[([^/\\])\]/g,"$1"):s.replace(/((?!\\).|^)\[([^/\\])\]/g,"$1$2").replace(/\\([^/])/g,"$1"):windowsPathsNoEscape?s.replace(/\[([^/\\{}])\]/g,"$1"):s.replace(/((?!\\).|^)\[([^/\\{}])\]/g,"$1$2").replace(/\\([^/{}])/g,"$1");var _a2,types=new Set(["!","?","+","*","@"]),isExtglobType=c2=>types.has(c2),isExtglobAST=c2=>isExtglobType(c2.type),adoptionMap=new Map([["!",["@"]],["?",["?","@"]],["@",["@"]],["*",["*","+","?","@"]],["+",["+","@"]]]),adoptionWithSpaceMap=new Map([["!",["?"]],["@",["?"]],["+",["?","*"]]]),adoptionAnyMap=new Map([["!",["?","@"]],["?",["?","@"]],["@",["?","@"]],["*",["*","+","?","@"]],["+",["+","@","?","*"]]]),usurpMap=new Map([["!",new Map([["!","@"]])],["?",new Map([["*","*"],["+","*"]])],["@",new Map([["!","!"],["?","?"],["@","@"],["*","*"],["+","+"]])],["+",new Map([["?","*"],["*","*"]])]]),startNoTraversal="(?!(?:^|/)\\.\\.?(?:$|/))",startNoDot="(?!\\.)",addPatternStart=new Set(["[","."]),justDots=new Set(["..","."]),reSpecials=new Set("().*{}+?[]^$\\!"),regExpEscape=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),qmark="[^/]",star=qmark+"*?",starNoEmpty=qmark+"+?",ID=0,AST=class{type;#root;#hasMagic;#uflag=!1;#parts=[];#parent;#parentIndex;#negs;#filledNegs=!1;#options;#toString;#emptyExt=!1;id=++ID;get depth(){return(this.#parent?.depth??-1)+1}[Symbol.for("nodejs.util.inspect.custom")](){return{"@@type":"AST",id:this.id,type:this.type,root:this.#root.id,parent:this.#parent?.id,depth:this.depth,partsLength:this.#parts.length,parts:this.#parts}}constructor(type,parent,options={}){this.type=type,type&&(this.#hasMagic=!0),this.#parent=parent,this.#root=this.#parent?this.#parent.#root:this,this.#options=this.#root===this?options:this.#root.#options,this.#negs=this.#root===this?[]:this.#root.#negs,type==="!"&&!this.#root.#filledNegs&&this.#negs.push(this),this.#parentIndex=this.#parent?this.#parent.#parts.length:0}get hasMagic(){if(this.#hasMagic!==void 0)return this.#hasMagic;for(let p of this.#parts)if(typeof p!="string"&&(p.type||p.hasMagic))return this.#hasMagic=!0;return this.#hasMagic}toString(){return this.#toString!==void 0?this.#toString:this.type?this.#toString=this.type+"("+this.#parts.map(p=>String(p)).join("|")+")":this.#toString=this.#parts.map(p=>String(p)).join("")}#fillNegs(){if(this!==this.#root)throw new Error("should only call on root");if(this.#filledNegs)return this;this.toString(),this.#filledNegs=!0;let n;for(;n=this.#negs.pop();){if(n.type!=="!")continue;let p=n,pp=p.#parent;for(;pp;){for(let i=p.#parentIndex+1;!pp.type&&i<pp.#parts.length;i++)for(let part of n.#parts){if(typeof part=="string")throw new Error("string part in extglob AST??");part.copyIn(pp.#parts[i])}p=pp,pp=p.#parent}}return this}push(...parts){for(let p of parts)if(p!==""){if(typeof p!="string"&&!(p instanceof _a2&&p.#parent===this))throw new Error("invalid part: "+p);this.#parts.push(p)}}toJSON(){let ret=this.type===null?this.#parts.slice().map(p=>typeof p=="string"?p:p.toJSON()):[this.type,...this.#parts.map(p=>p.toJSON())];return this.isStart()&&!this.type&&ret.unshift([]),this.isEnd()&&(this===this.#root||this.#root.#filledNegs&&this.#parent?.type==="!")&&ret.push({}),ret}isStart(){if(this.#root===this)return!0;if(!this.#parent?.isStart())return!1;if(this.#parentIndex===0)return!0;let p=this.#parent;for(let i=0;i<this.#parentIndex;i++){let pp=p.#parts[i];if(!(pp instanceof _a2&&pp.type==="!"))return!1}return!0}isEnd(){if(this.#root===this||this.#parent?.type==="!")return!0;if(!this.#parent?.isEnd())return!1;if(!this.type)return this.#parent?.isEnd();let pl=this.#parent?this.#parent.#parts.length:0;return this.#parentIndex===pl-1}copyIn(part){typeof part=="string"?this.push(part):this.push(part.clone(this))}clone(parent){let c2=new _a2(this.type,parent);for(let p of this.#parts)c2.copyIn(p);return c2}static#parseAST(str2,ast,pos,opt,extDepth){let maxDepth=opt.maxExtglobRecursion??2,escaping=!1,inBrace=!1,braceStart=-1,braceNeg=!1;if(ast.type===null){let i2=pos,acc2="";for(;i2<str2.length;){let c2=str2.charAt(i2++);if(escaping||c2==="\\"){escaping=!escaping,acc2+=c2;continue}if(inBrace){i2===braceStart+1?(c2==="^"||c2==="!")&&(braceNeg=!0):c2==="]"&&!(i2===braceStart+2&&braceNeg)&&(inBrace=!1),acc2+=c2;continue}else if(c2==="["){inBrace=!0,braceStart=i2,braceNeg=!1,acc2+=c2;continue}if(!opt.noext&&isExtglobType(c2)&&str2.charAt(i2)==="("&&extDepth<=maxDepth){ast.push(acc2),acc2="";let ext2=new _a2(c2,ast);i2=_a2.#parseAST(str2,ext2,i2,opt,extDepth+1),ast.push(ext2);continue}acc2+=c2}return ast.push(acc2),i2}let i=pos+1,part=new _a2(null,ast),parts=[],acc="";for(;i<str2.length;){let c2=str2.charAt(i++);if(escaping||c2==="\\"){escaping=!escaping,acc+=c2;continue}if(inBrace){i===braceStart+1?(c2==="^"||c2==="!")&&(braceNeg=!0):c2==="]"&&!(i===braceStart+2&&braceNeg)&&(inBrace=!1),acc+=c2;continue}else if(c2==="["){inBrace=!0,braceStart=i,braceNeg=!1,acc+=c2;continue}if(!opt.noext&&isExtglobType(c2)&&str2.charAt(i)==="("&&(extDepth<=maxDepth||ast&&ast.#canAdoptType(c2))){let depthAdd=ast&&ast.#canAdoptType(c2)?0:1;part.push(acc),acc="";let ext2=new _a2(c2,part);part.push(ext2),i=_a2.#parseAST(str2,ext2,i,opt,extDepth+depthAdd);continue}if(c2==="|"){part.push(acc),acc="",parts.push(part),part=new _a2(null,ast);continue}if(c2===")")return acc===""&&ast.#parts.length===0&&(ast.#emptyExt=!0),part.push(acc),acc="",ast.push(...parts,part),i;acc+=c2}return ast.type=null,ast.#hasMagic=void 0,ast.#parts=[str2.substring(pos-1)],i}#canAdoptWithSpace(child){return this.#canAdopt(child,adoptionWithSpaceMap)}#canAdopt(child,map=adoptionMap){if(!child||typeof child!="object"||child.type!==null||child.#parts.length!==1||this.type===null)return!1;let gc=child.#parts[0];return!gc||typeof gc!="object"||gc.type===null?!1:this.#canAdoptType(gc.type,map)}#canAdoptType(c2,map=adoptionAnyMap){return!!map.get(this.type)?.includes(c2)}#adoptWithSpace(child,index3){let gc=child.#parts[0],blank=new _a2(null,gc,this.options);blank.#parts.push(""),gc.push(blank),this.#adopt(child,index3)}#adopt(child,index3){let gc=child.#parts[0];this.#parts.splice(index3,1,...gc.#parts);for(let p of gc.#parts)typeof p=="object"&&(p.#parent=this);this.#toString=void 0}#canUsurpType(c2){return!!usurpMap.get(this.type)?.has(c2)}#canUsurp(child){if(!child||typeof child!="object"||child.type!==null||child.#parts.length!==1||this.type===null||this.#parts.length!==1)return!1;let gc=child.#parts[0];return!gc||typeof gc!="object"||gc.type===null?!1:this.#canUsurpType(gc.type)}#usurp(child){let m2=usurpMap.get(this.type),gc=child.#parts[0],nt2=m2?.get(gc.type);if(!nt2)return!1;this.#parts=gc.#parts;for(let p of this.#parts)typeof p=="object"&&(p.#parent=this);this.type=nt2,this.#toString=void 0,this.#emptyExt=!1}static fromGlob(pattern,options={}){let ast=new _a2(null,void 0,options);return _a2.#parseAST(pattern,ast,0,options,0),ast}toMMPattern(){if(this!==this.#root)return this.#root.toMMPattern();let glob=this.toString(),[re,body,hasMagic,uflag]=this.toRegExpSource();if(!(hasMagic||this.#hasMagic||this.#options.nocase&&!this.#options.nocaseMagicOnly&&glob.toUpperCase()!==glob.toLowerCase()))return body;let flags=(this.#options.nocase?"i":"")+(uflag?"u":"");return Object.assign(new RegExp(`^${re}$`,flags),{_src:re,_glob:glob})}get options(){return this.#options}toRegExpSource(allowDot){let dot=allowDot??!!this.#options.dot;if(this.#root===this&&(this.#flatten(),this.#fillNegs()),!isExtglobAST(this)){let noEmpty=this.isStart()&&this.isEnd()&&!this.#parts.some(s=>typeof s!="string"),src=this.#parts.map(p=>{let[re,_2,hasMagic,uflag]=typeof p=="string"?_a2.#parseGlob(p,this.#hasMagic,noEmpty):p.toRegExpSource(allowDot);return this.#hasMagic=this.#hasMagic||hasMagic,this.#uflag=this.#uflag||uflag,re}).join(""),start2="";if(this.isStart()&&typeof this.#parts[0]=="string"&&!(this.#parts.length===1&&justDots.has(this.#parts[0]))){let aps=addPatternStart,needNoTrav=dot&&aps.has(src.charAt(0))||src.startsWith("\\.")&&aps.has(src.charAt(2))||src.startsWith("\\.\\.")&&aps.has(src.charAt(4)),needNoDot=!dot&&!allowDot&&aps.has(src.charAt(0));start2=needNoTrav?startNoTraversal:needNoDot?startNoDot:""}let end="";return this.isEnd()&&this.#root.#filledNegs&&this.#parent?.type==="!"&&(end="(?:$|\\/)"),[start2+src+end,unescape(src),this.#hasMagic=!!this.#hasMagic,this.#uflag]}let repeated=this.type==="*"||this.type==="+",start=this.type==="!"?"(?:(?!(?:":"(?:",body=this.#partsToRegExp(dot);if(this.isStart()&&this.isEnd()&&!body&&this.type!=="!"){let s=this.toString(),me2=this;return me2.#parts=[s],me2.type=null,me2.#hasMagic=void 0,[s,unescape(this.toString()),!1,!1]}let bodyDotAllowed=!repeated||allowDot||dot||!startNoDot?"":this.#partsToRegExp(!0);bodyDotAllowed===body&&(bodyDotAllowed=""),bodyDotAllowed&&(body=`(?:${body})(?:${bodyDotAllowed})*?`);let final="";if(this.type==="!"&&this.#emptyExt)final=(this.isStart()&&!dot?startNoDot:"")+starNoEmpty;else{let close=this.type==="!"?"))"+(this.isStart()&&!dot&&!allowDot?startNoDot:"")+star+")":this.type==="@"?")":this.type==="?"?")?":this.type==="+"&&bodyDotAllowed?")":this.type==="*"&&bodyDotAllowed?")?":`)${this.type}`;final=start+body+close}return[final,unescape(body),this.#hasMagic=!!this.#hasMagic,this.#uflag]}#flatten(){if(isExtglobAST(this)){let iterations=0,done=!1;do{done=!0;for(let i=0;i<this.#parts.length;i++){let c2=this.#parts[i];typeof c2=="object"&&(c2.#flatten(),this.#canAdopt(c2)?(done=!1,this.#adopt(c2,i)):this.#canAdoptWithSpace(c2)?(done=!1,this.#adoptWithSpace(c2,i)):this.#canUsurp(c2)&&(done=!1,this.#usurp(c2)))}}while(!done&&++iterations<10)}else for(let p of this.#parts)typeof p=="object"&&p.#flatten();this.#toString=void 0}#partsToRegExp(dot){return this.#parts.map(p=>{if(typeof p=="string")throw new Error("string type in extglob ast??");let[re,_2,_hasMagic,uflag]=p.toRegExpSource(dot);return this.#uflag=this.#uflag||uflag,re}).filter(p=>!(this.isStart()&&this.isEnd())||!!p).join("|")}static#parseGlob(glob,hasMagic,noEmpty=!1){let escaping=!1,re="",uflag=!1,inStar=!1;for(let i=0;i<glob.length;i++){let c2=glob.charAt(i);if(escaping){escaping=!1,re+=(reSpecials.has(c2)?"\\":"")+c2;continue}if(c2==="*"){if(inStar)continue;inStar=!0,re+=noEmpty&&/^[*]+$/.test(glob)?starNoEmpty:star,hasMagic=!0;continue}else inStar=!1;if(c2==="\\"){i===glob.length-1?re+="\\\\":escaping=!0;continue}if(c2==="["){let[src,needUflag,consumed,magic]=parseClass(glob,i);if(consumed){re+=src,uflag=uflag||needUflag,i+=consumed-1,hasMagic=hasMagic||magic;continue}}if(c2==="?"){re+=qmark,hasMagic=!0;continue}re+=regExpEscape(c2)}return[re,unescape(glob),!!hasMagic,uflag]}};_a2=AST;var escape=(s,{windowsPathsNoEscape=!1,magicalBraces=!1}={})=>magicalBraces?windowsPathsNoEscape?s.replace(/[?*()[\]{}]/g,"[$&]"):s.replace(/[?*()[\]\\{}]/g,"\\$&"):windowsPathsNoEscape?s.replace(/[?*()[\]]/g,"[$&]"):s.replace(/[?*()[\]\\]/g,"\\$&");var minimatch=(p,pattern,options={})=>(assertValidPattern(pattern),!options.nocomment&&pattern.charAt(0)==="#"?!1:new Minimatch(pattern,options).match(p)),starDotExtRE=/^\*+([^+@!?*[(]*)$/,starDotExtTest=ext2=>f2=>!f2.startsWith(".")&&f2.endsWith(ext2),starDotExtTestDot=ext2=>f2=>f2.endsWith(ext2),starDotExtTestNocase=ext2=>(ext2=ext2.toLowerCase(),f2=>!f2.startsWith(".")&&f2.toLowerCase().endsWith(ext2)),starDotExtTestNocaseDot=ext2=>(ext2=ext2.toLowerCase(),f2=>f2.toLowerCase().endsWith(ext2)),starDotStarRE=/^\*+\.\*+$/,starDotStarTest=f2=>!f2.startsWith(".")&&f2.includes("."),starDotStarTestDot=f2=>f2!=="."&&f2!==".."&&f2.includes("."),dotStarRE=/^\.\*+$/,dotStarTest=f2=>f2!=="."&&f2!==".."&&f2.startsWith("."),starRE=/^\*+$/,starTest=f2=>f2.length!==0&&!f2.startsWith("."),starTestDot=f2=>f2.length!==0&&f2!=="."&&f2!=="..",qmarksRE=/^\?+([^+@!?*[(]*)?$/,qmarksTestNocase=([$0,ext2=""])=>{let noext=qmarksTestNoExt([$0]);return ext2?(ext2=ext2.toLowerCase(),f2=>noext(f2)&&f2.toLowerCase().endsWith(ext2)):noext},qmarksTestNocaseDot=([$0,ext2=""])=>{let noext=qmarksTestNoExtDot([$0]);return ext2?(ext2=ext2.toLowerCase(),f2=>noext(f2)&&f2.toLowerCase().endsWith(ext2)):noext},qmarksTestDot=([$0,ext2=""])=>{let noext=qmarksTestNoExtDot([$0]);return ext2?f2=>noext(f2)&&f2.endsWith(ext2):noext},qmarksTest=([$0,ext2=""])=>{let noext=qmarksTestNoExt([$0]);return ext2?f2=>noext(f2)&&f2.endsWith(ext2):noext},qmarksTestNoExt=([$0])=>{let len=$0.length;return f2=>f2.length===len&&!f2.startsWith(".")},qmarksTestNoExtDot=([$0])=>{let len=$0.length;return f2=>f2.length===len&&f2!=="."&&f2!==".."},defaultPlatform=typeof process=="object"&&process?typeof process.env=="object"&&process.env&&process.env.__MINIMATCH_TESTING_PLATFORM__||process.platform:"posix",path10={win32:{sep:"\\"},posix:{sep:"/"}},sep6=defaultPlatform==="win32"?path10.win32.sep:path10.posix.sep;minimatch.sep=sep6;var GLOBSTAR=Symbol("globstar **");minimatch.GLOBSTAR=GLOBSTAR;var qmark2="[^/]",star2=qmark2+"*?",twoStarDot="(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?",twoStarNoDot="(?:(?!(?:\\/|^)\\.).)*?",filter=(pattern,options={})=>p=>minimatch(p,pattern,options);minimatch.filter=filter;var ext=(a,b2={})=>Object.assign({},a,b2),defaults=def=>{if(!def||typeof def!="object"||!Object.keys(def).length)return minimatch;let orig=minimatch;return Object.assign((p,pattern,options={})=>orig(p,pattern,ext(def,options)),{Minimatch:class extends orig.Minimatch{constructor(pattern,options={}){super(pattern,ext(def,options))}static defaults(options){return orig.defaults(ext(def,options)).Minimatch}},AST:class extends orig.AST{constructor(type,parent,options={}){super(type,parent,ext(def,options))}static fromGlob(pattern,options={}){return orig.AST.fromGlob(pattern,ext(def,options))}},unescape:(s,options={})=>orig.unescape(s,ext(def,options)),escape:(s,options={})=>orig.escape(s,ext(def,options)),filter:(pattern,options={})=>orig.filter(pattern,ext(def,options)),defaults:options=>orig.defaults(ext(def,options)),makeRe:(pattern,options={})=>orig.makeRe(pattern,ext(def,options)),braceExpand:(pattern,options={})=>orig.braceExpand(pattern,ext(def,options)),match:(list,pattern,options={})=>orig.match(list,pattern,ext(def,options)),sep:orig.sep,GLOBSTAR})};minimatch.defaults=defaults;var braceExpand=(pattern,options={})=>(assertValidPattern(pattern),options.nobrace||!/\{(?:(?!\{).)*\}/.test(pattern)?[pattern]:expand(pattern,{max:options.braceExpandMax}));minimatch.braceExpand=braceExpand;var makeRe=(pattern,options={})=>new Minimatch(pattern,options).makeRe();minimatch.makeRe=makeRe;var match=(list,pattern,options={})=>{let mm=new Minimatch(pattern,options);return list=list.filter(f2=>mm.match(f2)),mm.options.nonull&&!list.length&&list.push(pattern),list};minimatch.match=match;var globMagic=/[?*]|[+@!]\(.*?\)|\[|\]/,regExpEscape2=s=>s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),Minimatch=class{options;set;pattern;windowsPathsNoEscape;nonegate;negate;comment;empty;preserveMultipleSlashes;partial;globSet;globParts;nocase;isWindows;platform;windowsNoMagicRoot;maxGlobstarRecursion;regexp;constructor(pattern,options={}){assertValidPattern(pattern),options=options||{},this.options=options,this.maxGlobstarRecursion=options.maxGlobstarRecursion??200,this.pattern=pattern,this.platform=options.platform||defaultPlatform,this.isWindows=this.platform==="win32";let awe="allowWindowsEscape";this.windowsPathsNoEscape=!!options.windowsPathsNoEscape||options[awe]===!1,this.windowsPathsNoEscape&&(this.pattern=this.pattern.replace(/\\/g,"/")),this.preserveMultipleSlashes=!!options.preserveMultipleSlashes,this.regexp=null,this.negate=!1,this.nonegate=!!options.nonegate,this.comment=!1,this.empty=!1,this.partial=!!options.partial,this.nocase=!!this.options.nocase,this.windowsNoMagicRoot=options.windowsNoMagicRoot!==void 0?options.windowsNoMagicRoot:!!(this.isWindows&&this.nocase),this.globSet=[],this.globParts=[],this.set=[],this.make()}hasMagic(){if(this.options.magicalBraces&&this.set.length>1)return!0;for(let pattern of this.set)for(let part of pattern)if(typeof part!="string")return!0;return!1}debug(..._2){}make(){let pattern=this.pattern,options=this.options;if(!options.nocomment&&pattern.charAt(0)==="#"){this.comment=!0;return}if(!pattern){this.empty=!0;return}this.parseNegate(),this.globSet=[...new Set(this.braceExpand())],options.debug&&(this.debug=(...args)=>console.error(...args)),this.debug(this.pattern,this.globSet);let rawGlobParts=this.globSet.map(s=>this.slashSplit(s));this.globParts=this.preprocess(rawGlobParts),this.debug(this.pattern,this.globParts);let set=this.globParts.map((s,_2,__)=>{if(this.isWindows&&this.windowsNoMagicRoot){let isUNC=s[0]===""&&s[1]===""&&(s[2]==="?"||!globMagic.test(s[2]))&&!globMagic.test(s[3]),isDrive=/^[a-z]:/i.test(s[0]);if(isUNC)return[...s.slice(0,4),...s.slice(4).map(ss=>this.parse(ss))];if(isDrive)return[s[0],...s.slice(1).map(ss=>this.parse(ss))]}return s.map(ss=>this.parse(ss))});if(this.debug(this.pattern,set),this.set=set.filter(s=>s.indexOf(!1)===-1),this.isWindows)for(let i=0;i<this.set.length;i++){let p=this.set[i];p[0]===""&&p[1]===""&&this.globParts[i][2]==="?"&&typeof p[3]=="string"&&/^[a-z]:$/i.test(p[3])&&(p[2]="?")}this.debug(this.pattern,this.set)}preprocess(globParts){if(this.options.noglobstar)for(let partset of globParts)for(let j2=0;j2<partset.length;j2++)partset[j2]==="**"&&(partset[j2]="*");let{optimizationLevel=1}=this.options;return optimizationLevel>=2?(globParts=this.firstPhasePreProcess(globParts),globParts=this.secondPhasePreProcess(globParts)):optimizationLevel>=1?globParts=this.levelOneOptimize(globParts):globParts=this.adjascentGlobstarOptimize(globParts),globParts}adjascentGlobstarOptimize(globParts){return globParts.map(parts=>{let gs=-1;for(;(gs=parts.indexOf("**",gs+1))!==-1;){let i=gs;for(;parts[i+1]==="**";)i++;i!==gs&&parts.splice(gs,i-gs)}return parts})}levelOneOptimize(globParts){return globParts.map(parts=>(parts=parts.reduce((set,part)=>{let prev=set[set.length-1];return part==="**"&&prev==="**"?set:part===".."&&prev&&prev!==".."&&prev!=="."&&prev!=="**"?(set.pop(),set):(set.push(part),set)},[]),parts.length===0?[""]:parts))}levelTwoFileOptimize(parts){Array.isArray(parts)||(parts=this.slashSplit(parts));let didSomething=!1;do{if(didSomething=!1,!this.preserveMultipleSlashes){for(let i=1;i<parts.length-1;i++){let p=parts[i];i===1&&p===""&&parts[0]===""||(p==="."||p==="")&&(didSomething=!0,parts.splice(i,1),i--)}parts[0]==="."&&parts.length===2&&(parts[1]==="."||parts[1]==="")&&(didSomething=!0,parts.pop())}let dd=0;for(;(dd=parts.indexOf("..",dd+1))!==-1;){let p=parts[dd-1];p&&p!=="."&&p!==".."&&p!=="**"&&!(this.isWindows&&/^[a-z]:$/i.test(p))&&(didSomething=!0,parts.splice(dd-1,2),dd-=2)}}while(didSomething);return parts.length===0?[""]:parts}firstPhasePreProcess(globParts){let didSomething=!1;do{didSomething=!1;for(let parts of globParts){let gs=-1;for(;(gs=parts.indexOf("**",gs+1))!==-1;){let gss=gs;for(;parts[gss+1]==="**";)gss++;gss>gs&&parts.splice(gs+1,gss-gs);let next=parts[gs+1],p=parts[gs+2],p2=parts[gs+3];if(next!==".."||!p||p==="."||p===".."||!p2||p2==="."||p2==="..")continue;didSomething=!0,parts.splice(gs,1);let other=parts.slice(0);other[gs]="**",globParts.push(other),gs--}if(!this.preserveMultipleSlashes){for(let i=1;i<parts.length-1;i++){let p=parts[i];i===1&&p===""&&parts[0]===""||(p==="."||p==="")&&(didSomething=!0,parts.splice(i,1),i--)}parts[0]==="."&&parts.length===2&&(parts[1]==="."||parts[1]==="")&&(didSomething=!0,parts.pop())}let dd=0;for(;(dd=parts.indexOf("..",dd+1))!==-1;){let p=parts[dd-1];if(p&&p!=="."&&p!==".."&&p!=="**"){didSomething=!0;let splin=dd===1&&parts[dd+1]==="**"?["."]:[];parts.splice(dd-1,2,...splin),parts.length===0&&parts.push(""),dd-=2}}}}while(didSomething);return globParts}secondPhasePreProcess(globParts){for(let i=0;i<globParts.length-1;i++)for(let j2=i+1;j2<globParts.length;j2++){let matched=this.partsMatch(globParts[i],globParts[j2],!this.preserveMultipleSlashes);if(matched){globParts[i]=[],globParts[j2]=matched;break}}return globParts.filter(gs=>gs.length)}partsMatch(a,b2,emptyGSMatch=!1){let ai=0,bi=0,result=[],which="";for(;ai<a.length&&bi<b2.length;)if(a[ai]===b2[bi])result.push(which==="b"?b2[bi]:a[ai]),ai++,bi++;else if(emptyGSMatch&&a[ai]==="**"&&b2[bi]===a[ai+1])result.push(a[ai]),ai++;else if(emptyGSMatch&&b2[bi]==="**"&&a[ai]===b2[bi+1])result.push(b2[bi]),bi++;else if(a[ai]==="*"&&b2[bi]&&(this.options.dot||!b2[bi].startsWith("."))&&b2[bi]!=="**"){if(which==="b")return!1;which="a",result.push(a[ai]),ai++,bi++}else if(b2[bi]==="*"&&a[ai]&&(this.options.dot||!a[ai].startsWith("."))&&a[ai]!=="**"){if(which==="a")return!1;which="b",result.push(b2[bi]),ai++,bi++}else return!1;return a.length===b2.length&&result}parseNegate(){if(this.nonegate)return;let pattern=this.pattern,negate=!1,negateOffset=0;for(let i=0;i<pattern.length&&pattern.charAt(i)==="!";i++)negate=!negate,negateOffset++;negateOffset&&(this.pattern=pattern.slice(negateOffset)),this.negate=negate}matchOne(file,pattern,partial=!1){let fileStartIndex=0,patternStartIndex=0;if(this.isWindows){let fileDrive=typeof file[0]=="string"&&/^[a-z]:$/i.test(file[0]),fileUNC=!fileDrive&&file[0]===""&&file[1]===""&&file[2]==="?"&&/^[a-z]:$/i.test(file[3]),patternDrive=typeof pattern[0]=="string"&&/^[a-z]:$/i.test(pattern[0]),patternUNC=!patternDrive&&pattern[0]===""&&pattern[1]===""&&pattern[2]==="?"&&typeof pattern[3]=="string"&&/^[a-z]:$/i.test(pattern[3]),fdi=fileUNC?3:fileDrive?0:void 0,pdi=patternUNC?3:patternDrive?0:void 0;if(typeof fdi=="number"&&typeof pdi=="number"){let[fd,pd]=[file[fdi],pattern[pdi]];fd.toLowerCase()===pd.toLowerCase()&&(pattern[pdi]=fd,patternStartIndex=pdi,fileStartIndex=fdi)}}let{optimizationLevel=1}=this.options;return optimizationLevel>=2&&(file=this.levelTwoFileOptimize(file)),pattern.includes(GLOBSTAR)?this.#matchGlobstar(file,pattern,partial,fileStartIndex,patternStartIndex):this.#matchOne(file,pattern,partial,fileStartIndex,patternStartIndex)}#matchGlobstar(file,pattern,partial,fileIndex,patternIndex){let firstgs=pattern.indexOf(GLOBSTAR,patternIndex),lastgs=pattern.lastIndexOf(GLOBSTAR),[head,body,tail]=partial?[pattern.slice(patternIndex,firstgs),pattern.slice(firstgs+1),[]]:[pattern.slice(patternIndex,firstgs),pattern.slice(firstgs+1,lastgs),pattern.slice(lastgs+1)];if(head.length){let fileHead=file.slice(fileIndex,fileIndex+head.length);if(!this.#matchOne(fileHead,head,partial,0,0))return!1;fileIndex+=head.length,patternIndex+=head.length}let fileTailMatch=0;if(tail.length){if(tail.length+fileIndex>file.length)return!1;let tailStart=file.length-tail.length;if(this.#matchOne(file,tail,partial,tailStart,0))fileTailMatch=tail.length;else{if(file[file.length-1]!==""||fileIndex+tail.length===file.length||(tailStart--,!this.#matchOne(file,tail,partial,tailStart,0)))return!1;fileTailMatch=tail.length+1}}if(!body.length){let sawSome=!!fileTailMatch;for(let i2=fileIndex;i2<file.length-fileTailMatch;i2++){let f2=String(file[i2]);if(sawSome=!0,f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1}return partial||sawSome}let bodySegments=[[[],0]],currentBody=bodySegments[0],nonGsParts=0,nonGsPartsSums=[0];for(let b2 of body)b2===GLOBSTAR?(nonGsPartsSums.push(nonGsParts),currentBody=[[],0],bodySegments.push(currentBody)):(currentBody[0].push(b2),nonGsParts++);let i=bodySegments.length-1,fileLength=file.length-fileTailMatch;for(let b2 of bodySegments)b2[1]=fileLength-(nonGsPartsSums[i--]+b2[0].length);return!!this.#matchGlobStarBodySections(file,bodySegments,fileIndex,0,partial,0,!!fileTailMatch)}#matchGlobStarBodySections(file,bodySegments,fileIndex,bodyIndex,partial,globStarDepth,sawTail){let bs=bodySegments[bodyIndex];if(!bs){for(let i=fileIndex;i<file.length;i++){sawTail=!0;let f2=file[i];if(f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1}return sawTail}let[body,after]=bs;for(;fileIndex<=after;){if(this.#matchOne(file.slice(0,fileIndex+body.length),body,partial,fileIndex,0)&&globStarDepth<this.maxGlobstarRecursion){let sub=this.#matchGlobStarBodySections(file,bodySegments,fileIndex+body.length,bodyIndex+1,partial,globStarDepth+1,sawTail);if(sub!==!1)return sub}let f2=file[fileIndex];if(f2==="."||f2===".."||!this.options.dot&&f2.startsWith("."))return!1;fileIndex++}return partial||null}#matchOne(file,pattern,partial,fileIndex,patternIndex){let fi,pi,pl,fl;for(fi=fileIndex,pi=patternIndex,fl=file.length,pl=pattern.length;fi<fl&&pi<pl;fi++,pi++){this.debug("matchOne loop");let p=pattern[pi],f2=file[fi];if(this.debug(pattern,p,f2),p===!1||p===GLOBSTAR)return!1;let hit;if(typeof p=="string"?(hit=f2===p,this.debug("string match",p,f2,hit)):(hit=p.test(f2),this.debug("pattern match",p,f2,hit)),!hit)return!1}if(fi===fl&&pi===pl)return!0;if(fi===fl)return partial;if(pi===pl)return fi===fl-1&&file[fi]==="";throw new Error("wtf?")}braceExpand(){return braceExpand(this.pattern,this.options)}parse(pattern){assertValidPattern(pattern);let options=this.options;if(pattern==="**")return GLOBSTAR;if(pattern==="")return"";let m2,fastTest=null;(m2=pattern.match(starRE))?fastTest=options.dot?starTestDot:starTest:(m2=pattern.match(starDotExtRE))?fastTest=(options.nocase?options.dot?starDotExtTestNocaseDot:starDotExtTestNocase:options.dot?starDotExtTestDot:starDotExtTest)(m2[1]):(m2=pattern.match(qmarksRE))?fastTest=(options.nocase?options.dot?qmarksTestNocaseDot:qmarksTestNocase:options.dot?qmarksTestDot:qmarksTest)(m2):(m2=pattern.match(starDotStarRE))?fastTest=options.dot?starDotStarTestDot:starDotStarTest:(m2=pattern.match(dotStarRE))&&(fastTest=dotStarTest);let re=AST.fromGlob(pattern,this.options).toMMPattern();return fastTest&&typeof re=="object"&&Reflect.defineProperty(re,"test",{value:fastTest}),re}makeRe(){if(this.regexp||this.regexp===!1)return this.regexp;let set=this.set;if(!set.length)return this.regexp=!1,this.regexp;let options=this.options,twoStar=options.noglobstar?star2:options.dot?twoStarDot:twoStarNoDot,flags=new Set(options.nocase?["i"]:[]),re=set.map(pattern=>{let pp=pattern.map(p=>{if(p instanceof RegExp)for(let f2 of p.flags.split(""))flags.add(f2);return typeof p=="string"?regExpEscape2(p):p===GLOBSTAR?GLOBSTAR:p._src});pp.forEach((p,i)=>{let next=pp[i+1],prev=pp[i-1];p!==GLOBSTAR||prev===GLOBSTAR||(prev===void 0?next!==void 0&&next!==GLOBSTAR?pp[i+1]="(?:\\/|"+twoStar+"\\/)?"+next:pp[i]=twoStar:next===void 0?pp[i-1]=prev+"(?:\\/|\\/"+twoStar+")?":next!==GLOBSTAR&&(pp[i-1]=prev+"(?:\\/|\\/"+twoStar+"\\/)"+next,pp[i+1]=GLOBSTAR))});let filtered=pp.filter(p=>p!==GLOBSTAR);if(this.partial&&filtered.length>=1){let prefixes=[];for(let i=1;i<=filtered.length;i++)prefixes.push(filtered.slice(0,i).join("/"));return"(?:"+prefixes.join("|")+")"}return filtered.join("/")}).join("|"),[open10,close]=set.length>1?["(?:",")"]:["",""];re="^"+open10+re+close+"$",this.partial&&(re="^(?:\\/|"+open10+re.slice(1,-1)+close+")$"),this.negate&&(re="^(?!"+re+").+$");try{this.regexp=new RegExp(re,[...flags].join(""))}catch{this.regexp=!1}return this.regexp}slashSplit(p){return this.preserveMultipleSlashes?p.split("/"):this.isWindows&&/^\/\/[^/]+/.test(p)?["",...p.split(/\/+/)]:p.split(/\/+/)}match(f2,partial=this.partial){if(this.debug("match",f2,this.pattern),this.comment)return!1;if(this.empty)return f2==="";if(f2==="/"&&partial)return!0;let options=this.options;this.isWindows&&(f2=f2.split("\\").join("/"));let ff=this.slashSplit(f2);this.debug(this.pattern,"split",ff);let set=this.set;this.debug(this.pattern,"set",set);let filename=ff[ff.length-1];if(!filename)for(let i=ff.length-2;!filename&&i>=0;i--)filename=ff[i];for(let pattern of set){let file=ff;if(options.matchBase&&pattern.length===1&&(file=[filename]),this.matchOne(file,pattern,partial))return options.flipNegate?!0:!this.negate}return options.flipNegate?!1:this.negate}static defaults(def){return minimatch.defaults(def).Minimatch}};minimatch.AST=AST;minimatch.Minimatch=Minimatch;minimatch.escape=escape;minimatch.unescape=unescape;var defaultModelPerProvider={"amazon-bedrock":"us.anthropic.claude-opus-4-6-v1","ant-ling":"Ring-2.6-1T",anthropic:"claude-opus-4-8",openai:"gpt-5.5","azure-openai-responses":"gpt-5.4","openai-codex":"gpt-5.5",radius:"auto",nvidia:"nvidia/nemotron-3-super-120b-a12b",deepseek:"deepseek-v4-pro",google:"gemini-3.1-pro-preview","google-vertex":"gemini-3.1-pro-preview","github-copilot":"gpt-5.4",openrouter:"moonshotai/kimi-k2.6","vercel-ai-gateway":"zai/glm-5.1",xai:"grok-4.6",groq:"openai/gpt-oss-120b",cerebras:"gpt-oss-120b",zai:"glm-5.3","zai-coding-cn":"glm-5.3",mistral:"devstral-medium-latest",minimax:"MiniMax-M2.7","minimax-cn":"MiniMax-M2.7",moonshotai:"kimi-k2.6","moonshotai-cn":"kimi-k2.6",huggingface:"moonshotai/Kimi-K2.6",fireworks:"accounts/fireworks/models/kimi-k2p6",together:"moonshotai/Kimi-K2.6",baseten:"zai-org/GLM-5.2",opencode:"kimi-k2.6","opencode-go":"kimi-k2.6","kimi-coding":"kimi-for-coding","cloudflare-workers-ai":"@cf/moonshotai/kimi-k2.6","cloudflare-ai-gateway":"workers-ai/@cf/moonshotai/kimi-k2.6","qwen-token-plan":"qwen3.7-max","qwen-token-plan-cn":"qwen3.7-max","qwen-token-plan-individual":"qwen3.8-max",xiaomi:"mimo-v2.5-pro","xiaomi-token-plan-cn":"mimo-v2.5-pro","xiaomi-token-plan-ams":"mimo-v2.5-pro","xiaomi-token-plan-sgp":"mimo-v2.5-pro"};function isAlias(id){return id.endsWith("-latest")?!0:!/-\d{8}$/.test(id)}function findExactModelReferenceMatch(modelReference,availableModels){let trimmedReference=modelReference.trim();if(!trimmedReference)return;let normalizedReference=trimmedReference.toLowerCase(),canonicalMatches=availableModels.filter(model2=>`${model2.provider}/${model2.id}`.toLowerCase()===normalizedReference);if(canonicalMatches.length===1)return canonicalMatches[0];if(canonicalMatches.length>1)return;let slashIndex=trimmedReference.indexOf("/");if(slashIndex!==-1){let provider2=trimmedReference.substring(0,slashIndex).trim(),modelId=trimmedReference.substring(slashIndex+1).trim();if(provider2&&modelId){let providerMatches=availableModels.filter(model2=>model2.provider.toLowerCase()===provider2.toLowerCase()&&model2.id.toLowerCase()===modelId.toLowerCase());if(providerMatches.length===1)return providerMatches[0];if(providerMatches.length>1)return}}let idMatches=availableModels.filter(model2=>model2.id.toLowerCase()===normalizedReference);return idMatches.length===1?idMatches[0]:void 0}function tryMatchModel(modelPattern,availableModels){let exactMatch=findExactModelReferenceMatch(modelPattern,availableModels);if(exactMatch)return exactMatch;let matches=availableModels.filter(m2=>m2.id.toLowerCase().includes(modelPattern.toLowerCase())||m2.name?.toLowerCase().includes(modelPattern.toLowerCase()));if(matches.length===0)return;let aliases=matches.filter(m2=>isAlias(m2.id)),datedVersions=matches.filter(m2=>!isAlias(m2.id));return aliases.length>0?(aliases.sort((a,b2)=>b2.id.localeCompare(a.id)),aliases[0]):(datedVersions.sort((a,b2)=>b2.id.localeCompare(a.id)),datedVersions[0])}function buildFallbackModel(provider2,modelId,availableModels){let providerModels=availableModels.filter(m2=>m2.provider===provider2);if(providerModels.length===0)return;let defaultId=defaultModelPerProvider[provider2];return{...defaultId?providerModels.find(m2=>m2.id===defaultId)??providerModels[0]:providerModels[0],id:modelId,name:modelId}}function parseModelPattern(pattern,availableModels,options){let exactMatch=tryMatchModel(pattern,availableModels);if(exactMatch)return{model:exactMatch,thinkingLevel:void 0,warning:void 0};let lastColonIndex=pattern.lastIndexOf(":");if(lastColonIndex===-1)return{model:void 0,thinkingLevel:void 0,warning:void 0};let prefix=pattern.substring(0,lastColonIndex),suffix=pattern.substring(lastColonIndex+1);if(isValidThinkingLevel(suffix)){let result=parseModelPattern(prefix,availableModels,options);return result.model?{model:result.model,thinkingLevel:result.warning?void 0:suffix,warning:result.warning}:result}else{if(!(options?.allowInvalidThinkingLevelFallback??!0))return{model:void 0,thinkingLevel:void 0,warning:void 0};let result=parseModelPattern(prefix,availableModels,options);return result.model?{model:result.model,thinkingLevel:void 0,warning:`Invalid thinking level "${suffix}" in pattern "${pattern}". Using default instead.`}:result}}function resolveModelScopeFromModels(patterns,models){let availableModels=[...models],scopedModels=[],diagnostics=[];for(let pattern of patterns){if(pattern.includes("*")||pattern.includes("?")||pattern.includes("[")){let colonIdx=pattern.lastIndexOf(":"),globPattern2=pattern,thinkingLevel2;if(colonIdx!==-1){let suffix=pattern.substring(colonIdx+1);isValidThinkingLevel(suffix)&&(thinkingLevel2=suffix,globPattern2=pattern.substring(0,colonIdx))}let exactMatch=findExactModelReferenceMatch(globPattern2,availableModels);if(exactMatch){scopedModels.find(sm=>modelsAreEqual(sm.model,exactMatch))||scopedModels.push({model:exactMatch,thinkingLevel:thinkingLevel2});continue}let matchingModels=availableModels.filter(m2=>{let fullId=`${m2.provider}/${m2.id}`;return minimatch(fullId,globPattern2,{nocase:!0})||minimatch(m2.id,globPattern2,{nocase:!0})});if(matchingModels.length===0){diagnostics.push({type:"warning",code:"no-match",message:`No models match pattern "${pattern}"`,pattern});continue}for(let model3 of matchingModels)scopedModels.find(sm=>modelsAreEqual(sm.model,model3))||scopedModels.push({model:model3,thinkingLevel:thinkingLevel2});continue}let{model:model2,thinkingLevel,warning}=parseModelPattern(pattern,availableModels);if(warning&&diagnostics.push({type:"warning",code:"invalid-thinking-level",message:warning,pattern}),!model2){diagnostics.push({type:"warning",code:"no-match",message:`No models match pattern "${pattern}"`,pattern});continue}scopedModels.find(sm=>modelsAreEqual(sm.model,model2))||scopedModels.push({model:model2,thinkingLevel})}return{scopedModels,diagnostics}}async function resolveModelScopeWithDiagnostics(patterns,modelRuntime,options){return resolveModelScopeFromModels(patterns,await modelRuntime.getAvailable(void 0,options))}async function resolveModelScope(patterns,modelRuntime,options){let{scopedModels,diagnostics}=await resolveModelScopeWithDiagnostics(patterns,modelRuntime,options);for(let diagnostic of diagnostics)console.warn(source_default.yellow(`Warning: ${diagnostic.message}`));return scopedModels}function resolveCliModel(options){let{cliProvider,cliModel,cliThinking,modelRuntime}=options;if(!cliModel)return{model:void 0,warning:void 0,error:void 0};let availableModels=[...modelRuntime.getModels()];if(availableModels.length===0)return{model:void 0,warning:void 0,error:"No models available. Check your installation or add models to models.json."};let providerMap=new Map;for(let m2 of availableModels)providerMap.set(m2.provider.toLowerCase(),m2.provider);let provider2=cliProvider?providerMap.get(cliProvider.toLowerCase()):void 0;if(cliProvider&&!provider2)return{model:void 0,warning:void 0,error:`Unknown provider "${cliProvider}". Use --list-models to see available providers/models.`};let pattern=cliModel,inferredProvider=!1;if(!provider2){let slashIndex=cliModel.indexOf("/");if(slashIndex!==-1){let maybeProvider=cliModel.substring(0,slashIndex),canonical=providerMap.get(maybeProvider.toLowerCase());canonical&&(provider2=canonical,pattern=cliModel.substring(slashIndex+1),inferredProvider=!0)}}if(!provider2){let lower=cliModel.toLowerCase(),exactMatches=availableModels.filter(m2=>m2.id.toLowerCase()===lower||`${m2.provider}/${m2.id}`.toLowerCase()===lower);if(exactMatches.length===1)return{model:exactMatches[0],warning:void 0,thinkingLevel:void 0,error:void 0};if(exactMatches.length>1){let authenticatedExactMatches=exactMatches.filter(m2=>modelRuntime.hasConfiguredAuth(m2.provider));if(authenticatedExactMatches.length===1)return{model:authenticatedExactMatches[0],warning:void 0,thinkingLevel:void 0,error:void 0};let matches=exactMatches.map(m2=>`${m2.provider}/${m2.id}`).sort((a,b2)=>a.localeCompare(b2)).join(", "),authHint=authenticatedExactMatches.length===0?"No matching provider is authenticated.":"More than one matching provider is authenticated.";return{model:void 0,warning:void 0,thinkingLevel:void 0,error:`Model "${cliModel}" is ambiguous across providers: ${matches}. ${authHint} Use --provider or provider/model.`}}}if(cliProvider&&provider2){let prefix=`${provider2}/`;cliModel.toLowerCase().startsWith(prefix.toLowerCase())&&(pattern=cliModel.substring(prefix.length))}let candidates=provider2?availableModels.filter(m2=>m2.provider===provider2):availableModels,{model:model2,thinkingLevel,warning}=parseModelPattern(pattern,candidates,{allowInvalidThinkingLevelFallback:!1});if(model2){if(inferredProvider){let rawExactMatches=availableModels.filter(m2=>m2.id.toLowerCase()===cliModel.toLowerCase()&&!modelsAreEqual(m2,model2));if(rawExactMatches.length>0&&!modelRuntime.hasConfiguredAuth(model2.provider)){let authenticatedRawMatches=rawExactMatches.filter(m2=>modelRuntime.hasConfiguredAuth(m2.provider));if(authenticatedRawMatches.length===1)return{model:authenticatedRawMatches[0],thinkingLevel:void 0,warning:void 0,error:void 0}}}return{model:model2,thinkingLevel,warning,error:void 0}}if(inferredProvider){let lower=cliModel.toLowerCase(),exact=availableModels.find(m2=>m2.id.toLowerCase()===lower||`${m2.provider}/${m2.id}`.toLowerCase()===lower);if(exact)return{model:exact,warning:void 0,thinkingLevel:void 0,error:void 0};let fallback=parseModelPattern(cliModel,availableModels,{allowInvalidThinkingLevelFallback:!1});if(fallback.model)return{model:fallback.model,thinkingLevel:fallback.thinkingLevel,warning:fallback.warning,error:void 0}}if(provider2){let fallbackPattern=pattern,fallbackThinking;if(!cliThinking){let lastColon=pattern.lastIndexOf(":");if(lastColon!==-1){let suffix=pattern.substring(lastColon+1);isValidThinkingLevel(suffix)&&(fallbackPattern=pattern.substring(0,lastColon),fallbackThinking=suffix)}}let fallbackModel=buildFallbackModel(provider2,fallbackPattern,availableModels);if(fallbackModel){let requestedThinking=cliThinking??fallbackThinking,model3=requestedThinking&&requestedThinking!=="off"?{...fallbackModel,reasoning:!0}:fallbackModel,fallbackWarning=warning?`${warning} Model "${fallbackPattern}" not found for provider "${provider2}". Using custom model id.`:`Model "${fallbackPattern}" not found for provider "${provider2}". Using custom model id.`;return{model:model3,thinkingLevel:fallbackThinking,warning:fallbackWarning,error:void 0}}}let display=provider2?`${provider2}/${pattern}`:cliModel;return{model:void 0,thinkingLevel:void 0,warning,error:`Model "${display}" not found. Use --list-models to see available models.`}}async function findInitialModel(options){let{cliProvider,cliModel,scopedModels,isContinuing,defaultProvider,defaultModelId,defaultThinkingLevel,modelThinkingLevels,modelRuntime}=options,model2,thinkingLevel=DEFAULT_THINKING_LEVEL;if(cliProvider&&cliModel){let resolved=resolveCliModel({cliProvider,cliModel,modelRuntime});if(resolved.error&&(console.error(source_default.red(resolved.error)),process.exit(1)),resolved.model)return{model:resolved.model,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}if(scopedModels.length>0&&!isContinuing){let scopedModel=scopedModels[0],perModel=modelThinkingLevels?.[`${scopedModel.model.provider}/${scopedModel.model.id}`];return{model:scopedModel.model,thinkingLevel:scopedModel.thinkingLevel??perModel??defaultThinkingLevel??DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}if(defaultProvider&&defaultModelId){let found=modelRuntime.getModel(defaultProvider,defaultModelId);if(found&&modelRuntime.hasConfiguredAuth(found.provider)){model2=found;let perModel=modelThinkingLevels?.[`${defaultProvider}/${defaultModelId}`];return perModel?thinkingLevel=perModel:defaultThinkingLevel&&(thinkingLevel=defaultThinkingLevel),{model:model2,thinkingLevel,fallbackMessage:void 0}}}let availableModels=[...modelRuntime.getAvailableSnapshot()];if(availableModels.length>0){for(let provider2 of Object.keys(defaultModelPerProvider)){let defaultId=defaultModelPerProvider[provider2],match2=availableModels.find(m2=>m2.provider===provider2&&m2.id===defaultId);if(match2)return{model:match2,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}return{model:availableModels[0],thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}return{model:void 0,thinkingLevel:DEFAULT_THINKING_LEVEL,fallbackMessage:void 0}}import{dirname as dirname14,join as join23}from"node:path";import{readFile as readFile2}from"node:fs/promises";function stripJsonComments(input){return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g,m2=>m2[0]==='"'?m2:"").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g,(m2,tail)=>tail??(m2[0]==='"'?m2:""))}var PercentileCutoffsSchema=typebox_exports.Object({p50:typebox_exports.Optional(typebox_exports.Number()),p75:typebox_exports.Optional(typebox_exports.Number()),p90:typebox_exports.Optional(typebox_exports.Number()),p99:typebox_exports.Optional(typebox_exports.Number())}),OpenRouterRoutingSchema=typebox_exports.Object({allow_fallbacks:typebox_exports.Optional(typebox_exports.Boolean()),require_parameters:typebox_exports.Optional(typebox_exports.Boolean()),data_collection:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("deny"),typebox_exports.Literal("allow")])),zdr:typebox_exports.Optional(typebox_exports.Boolean()),enforce_distillable_text:typebox_exports.Optional(typebox_exports.Boolean()),order:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),only:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),ignore:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),quantizations:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),sort:typebox_exports.Optional(typebox_exports.Union([typebox_exports.String(),typebox_exports.Object({by:typebox_exports.Optional(typebox_exports.String()),partition:typebox_exports.Optional(typebox_exports.Union([typebox_exports.String(),typebox_exports.Null()]))})])),max_price:typebox_exports.Optional(typebox_exports.Object({prompt:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),completion:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),image:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),audio:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()])),request:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),typebox_exports.String()]))})),preferred_min_throughput:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),PercentileCutoffsSchema])),preferred_max_latency:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Number(),PercentileCutoffsSchema]))}),VercelGatewayRoutingSchema=typebox_exports.Object({only:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String())),order:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String()))}),ThinkingLevelMapValueSchema=typebox_exports.Union([typebox_exports.String(),typebox_exports.Null()]),ThinkingLevelMapSchema=typebox_exports.Object({off:typebox_exports.Optional(ThinkingLevelMapValueSchema),minimal:typebox_exports.Optional(ThinkingLevelMapValueSchema),low:typebox_exports.Optional(ThinkingLevelMapValueSchema),medium:typebox_exports.Optional(ThinkingLevelMapValueSchema),high:typebox_exports.Optional(ThinkingLevelMapValueSchema),xhigh:typebox_exports.Optional(ThinkingLevelMapValueSchema),max:typebox_exports.Optional(ThinkingLevelMapValueSchema)}),ChatTemplateKwargScalarSchema=typebox_exports.Union([typebox_exports.String(),typebox_exports.Number(),typebox_exports.Boolean(),typebox_exports.Null()]),ChatTemplateKwargVariableSchema=typebox_exports.Object({$var:typebox_exports.Union([typebox_exports.Literal("thinking.enabled"),typebox_exports.Literal("thinking.effort")]),omitWhenOff:typebox_exports.Optional(typebox_exports.Boolean())}),ChatTemplateKwargSchema=typebox_exports.Union([ChatTemplateKwargScalarSchema,ChatTemplateKwargVariableSchema]),OpenAICompletionsCompatSchema=typebox_exports.Object({supportsStore:typebox_exports.Optional(typebox_exports.Boolean()),supportsDeveloperRole:typebox_exports.Optional(typebox_exports.Boolean()),supportsReasoningEffort:typebox_exports.Optional(typebox_exports.Boolean()),supportsUsageInStreaming:typebox_exports.Optional(typebox_exports.Boolean()),supportsFinishReason:typebox_exports.Optional(typebox_exports.Boolean()),maxTokensField:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("max_completion_tokens"),typebox_exports.Literal("max_tokens")])),requiresToolResultName:typebox_exports.Optional(typebox_exports.Boolean()),requiresAssistantAfterToolResult:typebox_exports.Optional(typebox_exports.Boolean()),requiresThinkingAsText:typebox_exports.Optional(typebox_exports.Boolean()),requiresReasoningContentOnAssistantMessages:typebox_exports.Optional(typebox_exports.Boolean()),thinkingFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openrouter"),typebox_exports.Literal("together"),typebox_exports.Literal("baseten"),typebox_exports.Literal("deepseek"),typebox_exports.Literal("zai"),typebox_exports.Literal("qwen"),typebox_exports.Literal("chat-template"),typebox_exports.Literal("qwen-chat-template"),typebox_exports.Literal("string-thinking"),typebox_exports.Literal("ant-ling")])),chatTemplateKwargs:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ChatTemplateKwargSchema)),chatTemplateArgs:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ChatTemplateKwargSchema)),cacheControlFormat:typebox_exports.Optional(typebox_exports.Literal("anthropic")),openRouterRouting:typebox_exports.Optional(OpenRouterRoutingSchema),vercelGatewayRouting:typebox_exports.Optional(VercelGatewayRoutingSchema),supportsOpenAIGrammarTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictMode:typebox_exports.Optional(typebox_exports.Boolean()),sendSessionAffinityHeaders:typebox_exports.Optional(typebox_exports.Boolean()),deferredToolsMode:typebox_exports.Optional(typebox_exports.Literal("kimi")),sessionAffinityFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openai-nosession"),typebox_exports.Literal("openrouter")])),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean())}),OpenAIResponsesCompatSchema=typebox_exports.Object({supportsDeveloperRole:typebox_exports.Optional(typebox_exports.Boolean()),sessionAffinityFormat:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("openai"),typebox_exports.Literal("openai-nosession"),typebox_exports.Literal("openrouter")])),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictMode:typebox_exports.Optional(typebox_exports.Boolean()),supportsOpenAIGrammarTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsAdditionalTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsToolSearch:typebox_exports.Optional(typebox_exports.Boolean())}),AnthropicMessagesCompatSchema=typebox_exports.Object({supportsEagerToolInputStreaming:typebox_exports.Optional(typebox_exports.Boolean()),supportsLongCacheRetention:typebox_exports.Optional(typebox_exports.Boolean()),sendSessionAffinityHeaders:typebox_exports.Optional(typebox_exports.Boolean()),supportsCacheControlOnTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsTemperature:typebox_exports.Optional(typebox_exports.Boolean()),forceAdaptiveThinking:typebox_exports.Optional(typebox_exports.Boolean()),allowEmptySignature:typebox_exports.Optional(typebox_exports.Boolean()),supportsStrictTools:typebox_exports.Optional(typebox_exports.Boolean()),supportsToolReferences:typebox_exports.Optional(typebox_exports.Boolean())}),ProviderCompatSchema=typebox_exports.Union([OpenAICompletionsCompatSchema,OpenAIResponsesCompatSchema,AnthropicMessagesCompatSchema]),ModelCostRatesSchema={input:typebox_exports.Number(),output:typebox_exports.Number(),cacheRead:typebox_exports.Number(),cacheWrite:typebox_exports.Number()},ModelCostTierSchema=typebox_exports.Object({inputTokensAbove:typebox_exports.Number(),...ModelCostRatesSchema}),ModelCostSchema=typebox_exports.Object({...ModelCostRatesSchema,tiers:typebox_exports.Optional(typebox_exports.Array(ModelCostTierSchema))}),ModelDefinitionSchema=typebox_exports.Object({id:typebox_exports.String({minLength:1}),name:typebox_exports.Optional(typebox_exports.String({minLength:1})),api:typebox_exports.Optional(typebox_exports.String({minLength:1})),baseUrl:typebox_exports.Optional(typebox_exports.String({minLength:1})),reasoning:typebox_exports.Optional(typebox_exports.Boolean()),thinkingLevelMap:typebox_exports.Optional(ThinkingLevelMapSchema),input:typebox_exports.Optional(typebox_exports.Array(typebox_exports.Union([typebox_exports.Literal("text"),typebox_exports.Literal("image")]))),cost:typebox_exports.Optional(ModelCostSchema),contextWindow:typebox_exports.Optional(typebox_exports.Number()),maxTokens:typebox_exports.Optional(typebox_exports.Number()),samplingParams:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.Unknown())),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema)}),ModelOverrideSchema=typebox_exports.Object({name:typebox_exports.Optional(typebox_exports.String({minLength:1})),reasoning:typebox_exports.Optional(typebox_exports.Boolean()),thinkingLevelMap:typebox_exports.Optional(ThinkingLevelMapSchema),input:typebox_exports.Optional(typebox_exports.Array(typebox_exports.Union([typebox_exports.Literal("text"),typebox_exports.Literal("image")]))),cost:typebox_exports.Optional(typebox_exports.Object({input:typebox_exports.Optional(typebox_exports.Number()),output:typebox_exports.Optional(typebox_exports.Number()),cacheRead:typebox_exports.Optional(typebox_exports.Number()),cacheWrite:typebox_exports.Optional(typebox_exports.Number()),tiers:typebox_exports.Optional(typebox_exports.Array(ModelCostTierSchema))})),contextWindow:typebox_exports.Optional(typebox_exports.Number()),maxTokens:typebox_exports.Optional(typebox_exports.Number()),samplingParams:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.Unknown())),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema)}),ProviderConfigSchema=typebox_exports.Object({name:typebox_exports.Optional(typebox_exports.String({minLength:1})),baseUrl:typebox_exports.Optional(typebox_exports.String({minLength:1})),apiKey:typebox_exports.Optional(typebox_exports.String({minLength:1})),api:typebox_exports.Optional(typebox_exports.String({minLength:1})),oauth:typebox_exports.Optional(typebox_exports.Literal("radius")),headers:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),typebox_exports.String())),compat:typebox_exports.Optional(ProviderCompatSchema),authHeader:typebox_exports.Optional(typebox_exports.Boolean()),models:typebox_exports.Optional(typebox_exports.Array(ModelDefinitionSchema)),modelOverrides:typebox_exports.Optional(typebox_exports.Record(typebox_exports.String(),ModelOverrideSchema))}),ModelsConfigSchema=typebox_exports.Object({providers:typebox_exports.Record(typebox_exports.String(),ProviderConfigSchema)}),validateModelsConfig=Compile(ModelsConfigSchema);function formatValidationPath2(error){if(error.keyword==="required"){let requiredProperty=error.params.requiredProperties?.[0];if(requiredProperty){let basePath=error.instancePath.replace(/^\//,"").replace(/\//g,".");return basePath?`${basePath}.${requiredProperty}`:requiredProperty}}return error.instancePath.replace(/^\//,"").replace(/\//g,".")||"root"}function deepFreeze(value){if(typeof value!="object"||value===null||Object.isFrozen(value))return value;for(let child of Object.values(value))deepFreeze(child);return Object.freeze(value)}var ModelConfig=class _ModelConfig{constructor(providers,error){this.providers=providers,this.error=error}static async load(modelsJsonPath){if(!modelsJsonPath)return new _ModelConfig(new Map);let path14=normalizePath(modelsJsonPath),content;try{content=await readFile2(path14,"utf-8")}catch(error){return error.code==="ENOENT"?new _ModelConfig(new Map):new _ModelConfig(new Map,`Failed to load models.json: ${error instanceof Error?error.message:error}
1251
1251
 
1252
1252
  File: ${path14}`)}let parsed;try{parsed=JSON.parse(stripJsonComments(stripBom(content)))}catch(error){return new _ModelConfig(new Map,`Failed to parse models.json: ${error instanceof Error?error.message:error}
1253
1253
 
@@ -1307,10 +1307,10 @@ ${kModeState.plan.todos.join(`
1307
1307
  `),await file.sync()}finally{await file.close()}return record})}async function inspectChain(path14){let source2;try{source2=await readFile8(path14,"utf8")}catch(error){if(error.code==="ENOENT")return{ok:!1,path:path14,records:0,reason:"no event log at this path"};throw error}let expectedPreviousHash=FIRST_HASH,records=0,line=0;for(let text of source2.split(`
1308
1308
  `)){if(line+=1,text.length===0)continue;let record;try{record=JSON.parse(text)}catch{return{ok:!1,path:path14,records,line,reason:"record is not valid JSON"}}let{record_hash,...recordWithoutHash}=record;if(typeof record_hash!="string"||!HASH_PATTERN.test(record_hash))return{ok:!1,path:path14,records,line,reason:"record_hash is missing or malformed"};if(recordWithoutHash.prev_hash!==expectedPreviousHash)return{ok:!1,path:path14,records,line,reason:`prev_hash does not chain to the previous record (expected ${String(expectedPreviousHash).slice(0,12)})`};let computed;try{computed=hashRecord(recordWithoutHash)}catch(error){return{ok:!1,path:path14,records,line,reason:error instanceof Error?error.message:String(error)}}if(computed!==record_hash)return{ok:!1,path:path14,records,line,reason:"record_hash does not match the record's own bytes"};records+=1,expectedPreviousHash=record_hash}return{ok:!0,path:path14,records}}var RESEARCH_SERVICES=["exa","perplexity"],MAX_EXTERNAL_CALLS_PER_JOB=20,MAX_RESULTS_PER_REQUEST=10,MAX_CONTENTS_URLS=10,MAX_FIELD_CHARACTERS=1e4,MAX_ATTEMPTS_PER_SERVICE=1;async function resolveResearchKeys(agentDirectory=getAgentDir(),environment=process.env){let saved=await readSavedResearchKeys(agentDirectory),fromEnvironment=value=>{let trimmed=value?.trim();return trimmed===void 0||trimmed.length===0?void 0:trimmed};return{exa:saved.exa??fromEnvironment(environment.EXA_API_KEY),perplexity:saved.perplexity??fromEnvironment(environment.PERPLEXITY_API_KEY)}}function researchSecretName(service){return`${service}/default`}async function readSavedResearchKeys(agentDirectory){let payload;try{payload=JSON.parse(await readFile9(join37(agentDirectory,"accounts.secrets.json"),"utf8"))}catch{return{}}if(!isJsonObject(payload))return{};let keyFor=service=>{let credential=payload[researchSecretName(service)];if(!(!isJsonObject(credential)||credential.type!=="api_key"))return typeof credential.key=="string"&&credential.key.length>0?credential.key:void 0};return{exa:keyFor("exa"),perplexity:keyFor("perplexity")}}var ResearchBudgetError=class extends Error{constructor(limit){super(`Research call budget of ${limit} external calls for this job is spent`),this.name="ResearchBudgetError"}},ResearchShortfallError=class extends Error{constructor(service,origins){super(`${service} answered but supplied ${origins.length} distinct external source${origins.length===1?"":"s"}; two are required`),this.name="ResearchShortfallError",this.service=service,this.origins=[...origins]}},ResearchSession=class{constructor(options){this.attempts=new Map,this.cooling=new Set,this.failures=[],this.sources=[],this.origins=new Set,this.externalCalls=0,this.jobId=options.jobId,this.mode=options.mode,this.keys=options.keys,this.eventsPath=options.eventsPath,this.emitter=options.emit,this.now=options.now??(()=>new Date),this.round=options.round??0,this.node=options.node??"research",this.maxCalls=Math.max(0,options.maxExternalCalls??MAX_EXTERNAL_CALLS_PER_JOB),this.networkState=options.operatorNoNetwork===!0?"no-network":"online",this.networkOrigin=options.operatorNoNetwork===!0?"operator":void 0,this.networkReason=options.operatorNoNetwork===!0?"operator requested no-network":void 0}get network(){return{state:this.networkState,...this.networkOrigin===void 0?{}:{origin:this.networkOrigin},...this.networkReason===void 0?{}:{reason:this.networkReason},failures:this.failures.map(failure=>({...failure}))}}get callsSpent(){return this.externalCalls}get callsRemaining(){return Math.max(0,this.maxCalls-this.externalCalls)}get collected(){return this.sources.map(source2=>({...source2}))}get distinctOrigins(){return[...this.origins]}keyFor(service){return this.keys[service]}isCooling(service){return this.cooling.has(service)}get configuredServices(){if(this.mode==="local"||this.networkState==="no-network")return[];let keyed=RESEARCH_SERVICES.filter(service=>this.keyFor(service)!==void 0);if(this.mode==="exa"||this.mode==="perplexity"){let named=keyed.filter(service=>service===this.mode);return named.length>0?named:keyed}return keyed}get availableServices(){return this.configuredServices.filter(service=>!this.isCooling(service)&&(this.attempts.get(service)??0)<MAX_ATTEMPTS_PER_SERVICE)}timestamp(){return this.now().toISOString()}async emit(type,payload={}){let redacted={...payload,...payload.query===void 0?{}:{query:clampField(payload.query)},...payload.reason===void 0?{}:{reason:clampField(payload.reason)},...payload.source_refs===void 0?{}:{source_refs:payload.source_refs.map(clampField)}};if(this.emitter!==void 0){await this.emitter(type,redacted);return}this.eventsPath!==void 0&&await appendEvent(this.eventsPath,{ts:this.timestamp(),type,job_id:this.jobId,round:this.round,node:this.node,...redacted})}async started(){await this.emit("research.started",{mode:this.mode,network_state:this.networkState,...this.networkReason===void 0?{}:{reason:this.networkReason}})}async completed(mode){await this.emit("research.completed",{mode,network_state:this.networkState,result_count:this.sources.length,source_refs:this.sources.map(source2=>source2.ref),...this.networkReason===void 0?{}:{reason:this.networkReason}})}spend(){if(this.externalCalls>=this.maxCalls)throw new ResearchBudgetError(this.maxCalls);this.externalCalls+=1}async call(service,query,run){let key=this.keyFor(service);if(key===void 0)return await this.recordFailure(service,"unavailable"),{ok:!1,class:"unavailable"};if(this.networkState==="no-network")return await this.recordFailure(service,"unavailable"),{ok:!1,class:"unavailable"};this.spend();let attempt2=(this.attempts.get(service)??0)+1;this.attempts.set(service,attempt2),await this.emit("research.query",{service,query,attempt:attempt2});try{let value=await run(key);return await this.emit("research.call",{service,attempt:attempt2,query}),{ok:!0,value}}catch(error){let failure=classifyResearchFailure(error);return await this.recordFailure(service,failure),{ok:!1,class:failure}}}async recordFailure(service,failureClass){this.cooling.add(service),this.failures.push({service,class:failureClass,at:this.timestamp()}),await this.emit("research.fallback",{service,from:service,reason:failureClass,attempt:this.attempts.get(service)??1})}async addExternalResults(service,results){let observedAt=this.timestamp(),accepted=[];for(let result of results.slice(0,MAX_RESULTS_PER_REQUEST)){let canonical=canonicalizeUrl(result.url);canonical!==void 0&&(this.sources.some(source2=>source2.ref===canonical)||(this.sources.push({kind:"external",ref:canonical,title:clampField(result.title.length>0?result.title:canonical),service,observed_at:observedAt,...result.text===void 0?{}:{excerpt:clampField(result.text)}}),this.origins.add(originOf(canonical)??canonical),accepted.push(canonical)))}return await this.emit("research.result",{service,result_count:accepted.length,source_refs:accepted}),this.origins.size}addLocalSource(ref,title,excerpt){this.sources.some(source2=>source2.ref===ref)||this.sources.push({kind:"local",ref,title:clampField(title),service:null,observed_at:this.timestamp(),...excerpt===void 0?{}:{excerpt:clampField(excerpt)}})}async exhaust(){if(this.networkState==="no-network")return;let exhausted=[...new Set(this.failures.map(failure=>failure.service))];this.networkState="no-network",this.networkOrigin="engine",this.networkReason=`${exhausted.join(" and ")} each failed their bounded attempts`,await this.emit("research.fallback",{service:"local",from:exhausted.join("+"),to:"local",reason:this.networkReason,network_state:this.networkState})}clearExternalSources(){for(let index3=this.sources.length-1;index3>=0;index3-=1)this.sources[index3].kind==="external"&&this.sources.splice(index3,1);this.origins.clear()}};function classifyResearchFailure(error){let status=statusOf(error);if(status===402)return"http_402";if(status===429)return"http_429";if(status!==void 0&&status>=500)return"http_5xx";let name=error instanceof Error?error.name:"",message=error instanceof Error?error.message:String(error);return name==="TimeoutError"||/timed? ?out/iu.test(message)?"timeout":name==="AbortError"||/\babort(?:ed)?\b/iu.test(message)?"abort":"unavailable"}function statusOf(error){if(!(typeof error!="object"||error===null)&&"status"in error&&typeof error.status=="number")return error.status}function clampField(value,limit=MAX_FIELD_CHARACTERS){return value.length<=limit?value:value.slice(0,limit)}function canonicalizeUrl(value){let url;try{url=new URL(value.trim())}catch{return}if(!(url.protocol!=="http:"&&url.protocol!=="https:"))return url.hash="",url.username="",url.password="",url.pathname.length>1&&url.pathname.endsWith("/")&&(url.pathname=url.pathname.replace(/\/+$/u,"")),url.hostname=url.hostname.toLowerCase(),clampField(url.toString())}function originOf(value){try{return new URL(value).origin.toLowerCase()}catch{return}}async function readSecrets(path14){try{let value=JSON.parse(await readFile10(path14,"utf8"));if(typeof value!="object"||value===null||Array.isArray(value))throw new Error("Account secrets must be an object");return{...value}}catch(error){if(error.code==="ENOENT")return{};throw error}}async function writeSecrets(path14,secrets){await mkdir3(dirname22(path14),{recursive:!0});let temporary=`${path14}.${process.pid}.${randomUUID6()}.tmp`,file=await open5(temporary,"wx",384);try{await file.writeFile(`${JSON.stringify(secrets,null,2)}
1309
1309
  `),await file.sync(),await file.close(),await rename3(temporary,path14),await chmod2(path14,384)}catch(error){throw await file.close().catch(()=>{}),await rm3(temporary,{force:!0}),error}}async function saveResearchKeys(values,path14=join38(getAgentDir(),"accounts.secrets.json")){let secrets=await readSecrets(path14);values.exa!==void 0&&(secrets[researchSecretName("exa")]={type:"api_key",key:values.exa}),values.perplexity!==void 0&&(secrets[researchSecretName("perplexity")]={type:"api_key",key:values.perplexity}),await writeSecrets(path14,secrets)}async function removeResearchKey(service,path14=join38(getAgentDir(),"accounts.secrets.json")){let secrets=await readSecrets(path14),name=researchSecretName(service);return secrets[name]===void 0?!1:(delete secrets[name],await writeSecrets(path14,secrets),!0)}async function promptResearchSetup(context){let exa=await context.ui.input("Exa API key for research","Enter to save, s to skip"),perplexity=await context.ui.input("Perplexity API key for research","Enter to save, s to skip"),values={exa:exa===void 0||exa.trim()===""||exa.trim().toLowerCase()==="s"?void 0:exa.trim(),perplexity:perplexity===void 0||perplexity.trim()===""||perplexity.trim().toLowerCase()==="s"?void 0:perplexity.trim()},configured=values.exa!==void 0||values.perplexity!==void 0;configured&&await saveResearchKeys(values),await writeResearchMode(context.cwd,configured?"auto":"local"),context.ui.notify(configured?"External research configured":"Research mode: local","info")}import{readFile as readFile11}from"node:fs/promises";import{join as join39}from"node:path";var LADDER_FILE="model-ladder.md",REQUIRED_ROLES=["implementer","frontend","judgment","precise","fast","review_panel"],LadderError=class extends Error{constructor(message){super(message),this.name="LadderError"}};function splitRow(line){return line.replace(/^\s*\|/u,"").replace(/\|\s*$/u,"").split("|").map(cell=>cell.trim())}function patternsFrom(cell){let found=[],regex2=/`([^`]+)`/gu,match2=regex2.exec(cell);for(;match2!==null;){let value=match2[1].trim();value.length>0&&!value.startsWith("(")&&found.push(value),match2=regex2.exec(cell)}return found}function parseModelLadder(source2){let roles=[],workingOrder=[],inRoleTable=!1;for(let line of source2.split(`
1310
- `)){if(/^\|\s*Role\s*\|/u.test(line)){inRoleTable=!0;continue}if(inRoleTable){if(!line.trimStart().startsWith("|"))inRoleTable=!1;else if(!/^\|\s*-+/u.test(line.trimStart())){let cells=splitRow(line);if(cells.length>=4){let role=cells[0].replace(/`/gu,"").trim();roles.push({role,prefer:patternsFrom(cells[1]),why:cells[2],confidence:cells[3]})}continue}}let ordered2=/^\s*(\d+)\.\s+(.+?)\s+—/u.exec(line);ordered2!==null&&workingOrder.push(ordered2[2].trim())}let missing=REQUIRED_ROLES.filter(role=>!roles.some(entry=>entry.role===role));if(missing.length>0)throw new LadderError(`model ladder has no row for: ${missing.join(", ")}`);for(let entry of roles)if(entry.prefer.length===0&&!/inherit-parent/u.test(entry.why))throw new LadderError(`model ladder role ${entry.role} offers no pattern`);return{roles,workingOrder}}function ladderCandidates(resourceDirectory){return[join39(resourceDirectory,"kstack",LADDER_FILE),join39(resourceDirectory,"..","..","..","docs",LADDER_FILE),join39(resourceDirectory,"..","..","..","..","docs",LADDER_FILE)]}async function readModelLadder(resourceDirectory=getKpiResourceDir()){let attempted=[];for(let candidate of ladderCandidates(resourceDirectory)){attempted.push(candidate);let source2=await readFile11(candidate,"utf8").catch(error=>{if(error.code!=="ENOENT")throw error});if(source2!==void 0)return parseModelLadder(source2)}throw new LadderError(`no ${LADDER_FILE} found; looked in ${attempted.join(", ")}`)}function family(slug){return slug.split("/")[0]}function suggestForRole(entry,candidates,workingOrder){let ranked=[];for(let pattern of entry.prefer){let hits=candidates.filter(slug=>slug.toLowerCase().includes(pattern.toLowerCase())).filter(slug=>!ranked.some(found=>found.slug===slug)).sort((left,right)=>tieBreak(left,right,workingOrder));for(let slug of hits)ranked.push({slug,pattern})}return ranked.length===0?{role:entry.role,confidence:entry.confidence}:{role:entry.role,chosen:ranked[0].slug,matched:ranked[0].pattern,nextBest:ranked[1]?.slug,confidence:entry.confidence}}function tieBreak(left,right,workingOrder){let rank=slug=>{let index3=workingOrder.findIndex(name=>slug.toLowerCase().includes(normalizeName(name)));return index3===-1?Number.MAX_SAFE_INTEGER:index3},difference=rank(left)-rank(right);return difference!==0?difference:left.localeCompare(right)}function normalizeName(name){return name.toLowerCase().replace(/\s+/gu,"-").replace(/[^a-z0-9.-]/gu,"")}var PANEL_CAP=3;function suggestPanel(entry,candidates,workingOrder,cap=PANEL_CAP){let panel=[],seen=new Set;for(let pattern of entry.prefer)for(let slug of candidates.filter(candidate=>candidate.toLowerCase().includes(pattern.toLowerCase())).sort((left,right)=>tieBreak(left,right,workingOrder)))!seen.has(family(slug))&&panel.length<cap&&(seen.add(family(slug)),panel.push(slug));if(panel.length===0)for(let slug of[...candidates].sort((left,right)=>tieBreak(left,right,workingOrder)))!seen.has(family(slug))&&panel.length<cap&&(seen.add(family(slug)),panel.push(slug));return panel}var INHERIT_PARENT="inherit-parent",HEALTHY_POOLS=new Set(POOL_IDS);function liveCandidates(models){let seen=new Set,candidates=[];for(let model2 of models){if(!HEALTHY_POOLS.has(model2.provider))continue;let slug=`${model2.provider}/${model2.id}`;seen.has(slug)||(seen.add(slug),candidates.push(slug))}return candidates}function planModels(ladder,candidates){return REQUIRED_ROLES.map(role=>{let entry=ladder.roles.find(candidate=>candidate.role===role);if(entry===void 0)return{role,confidence:"unknown",value:INHERIT_PARENT};if(role==="review_panel"){let panel=suggestPanel(entry,candidates,ladder.workingOrder,PANEL_CAP);return{role,confidence:entry.confidence,chosen:panel[0],nextBest:panel[1],value:panel.length>0?panel:INHERIT_PARENT}}let suggestion=suggestForRole(entry,candidates,ladder.workingOrder);return{...suggestion,value:suggestion.chosen??INHERIT_PARENT}})}function planToDocument(plan){let roles={};for(let entry of plan)roles[entry.role]=entry.value;return{version:1,roles,inherit_parent:!1}}function renderPlan(plan){return plan.map(entry=>{let value=Array.isArray(entry.value)?entry.value.join(" + "):entry.value,next=entry.nextBest===void 0?"none":entry.nextBest;return`${entry.role} \u2192 ${value} (next best: ${next}; confidence: ${entry.confidence})`})}function assertKnownModels(document,candidates){let allowed=new Set([...candidates,INHERIT_PARENT]);for(let[role,entry]of Object.entries(document.roles)){let values=Array.isArray(entry)?entry:[entry];if(Array.isArray(entry)&&entry.length>PANEL_CAP)throw new Error(`${role} panel exceeds ${PANEL_CAP} entries`);for(let value of values)if(!allowed.has(value))throw new Error(`Unknown model slug: ${value}`)}}function modelsPath(){return join40(getAgentDir(),"kstack","models.json")}async function writeKStackModels(document,candidates,path14=modelsPath()){assertKnownModels(document,candidates),await mkdir4(dirname23(path14),{recursive:!0});let temporary=`${path14}.${process.pid}.${randomUUID7()}.tmp`,file=await open6(temporary,"wx",384);try{await file.writeFile(`${JSON.stringify(document,null,2)}
1311
- `),await file.sync(),await file.close(),await rename4(temporary,path14),await chmod3(path14,384)}catch(error){throw await file.close().catch(()=>{}),await rm4(temporary,{force:!0}),error}}var APPLY="apply this map";async function editPlan(plan,candidates,ui){let current=[...plan];for(;;){let choice=await ui.select("K-stack models",[APPLY,...renderPlan(current),"cancel"]);if(choice===void 0||choice==="cancel")return;if(choice===APPLY)return current;let role=choice.split(" \u2192 ")[0],index3=current.findIndex(entry=>entry.role===role);if(index3===-1)continue;let typed=await ui.input(`${role} model`,`slug, ${INHERIT_PARENT}, or comma-separated for a panel (${candidates.length} live)`);if(typed===void 0||typed.trim().length===0)continue;let values=typed.split(",").map(value2=>value2.trim()).filter(value2=>value2.length>0),allowed=new Set([...candidates,INHERIT_PARENT]),rejected=values.filter(value2=>!allowed.has(value2));if(rejected.length>0){ui.notify(`Not a live model in this session: ${rejected.join(", ")}`,"error");continue}if(role==="review_panel"&&values.length>PANEL_CAP){ui.notify(`A review panel takes at most ${PANEL_CAP} entries`,"error");continue}let value=role==="review_panel"&&values.length>1?values:values[0];current=current.map((entry,position)=>position===index3?{...entry,value}:entry)}}function registerKStackSetup(pi){pi.registerCommand("setup-kstack",{description:"Map K-stack roles onto live K-\u03C0 models using the committed model ladder",handler:async(_args,context)=>{let candidates=liveCandidates(context.modelRegistry.getAvailable());if(candidates.length===0)context.ui.notify("No live model in a K-\u03C0 pool; K-stack roles will inherit the parent session model.","warning");else{let ladder=await readModelLadder(),plan=planModels(ladder,candidates);context.ui.notify(renderPlan(plan).join(`
1312
- `),"info");let edited=await editPlan(plan,candidates,context.ui);edited===void 0?context.ui.notify("K-stack model map unchanged","info"):(await writeKStackModels(planToDocument(edited),candidates),context.ui.notify(`K-stack model map saved to ${modelsPath()}`,"info"))}await promptResearchSetup(context)}})}import{mkdirSync as mkdirSync11,readFileSync as readFileSync15,renameSync as renameSync3,writeFileSync as writeFileSync10}from"node:fs";import{dirname as dirname24,join as join41}from"node:path";var LOCAL_PROVIDER_IDS=["ollama","lmstudio","local-openai"],DEFAULT_LOCAL_BASE_URLS={ollama:"http://127.0.0.1:11434/v1",lmstudio:"http://127.0.0.1:1234/v1","local-openai":void 0},LOCAL_PROVIDER_NAMES={ollama:"Ollama",lmstudio:"LM Studio","local-openai":"Local OpenAI-compatible"},LOCAL_CLIENT_PLACEHOLDER="local",LOCAL_DISCOVERY_TIMEOUT_MS=2e3;function localModel(id,baseUrl,name=id){return{id,name,api:"openai-completions",baseUrl,reasoning:!1,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:32768,maxTokens:4096}}function storedLocalModelsPath(poolId,agentDirectory=getAgentDir()){return join41(agentDirectory,`${poolId}-models.json`)}function readStoredEntries(poolId,agentDirectory){try{let parsed=JSON.parse(readFileSync15(storedLocalModelsPath(poolId,agentDirectory),"utf8"));return Array.isArray(parsed)?parsed.flatMap(entry=>{if(typeof entry!="object"||entry===null)return[];let candidate=entry;return typeof candidate.id!="string"||candidate.id.length===0?[]:typeof candidate.baseUrl!="string"||candidate.baseUrl.length===0?[]:[{id:candidate.id,name:typeof candidate.name=="string"?candidate.name:candidate.id,baseUrl:candidate.baseUrl}]}):[]}catch{return[]}}function readStoredLocalModels(poolId,agentDirectory,slots){let entries=readStoredEntries(poolId,agentDirectory),allowed=slots===void 0?void 0:new Set(slots.map(slot=>slot.baseUrl)),models=entries.filter(entry=>allowed===void 0||allowed.has(entry.baseUrl)).map(entry=>localModel(entry.id,entry.baseUrl,entry.name));return models.length===0?void 0:models}function writeStoredLocalModels(poolId,models,agentDirectory){let path14=storedLocalModelsPath(poolId,agentDirectory),temporaryPath=`${path14}.${process.pid}.tmp`,entries=models.map(entry=>({id:entry.id,name:entry.name,baseUrl:entry.baseUrl??""}));try{mkdirSync11(dirname24(path14),{recursive:!0}),writeFileSync10(temporaryPath,`${JSON.stringify(entries,null,2)}
1313
- `,{encoding:"utf8",mode:384}),renameSync3(temporaryPath,path14)}catch{}}function readModelIds(entries,idField){if(!Array.isArray(entries))return;let ids=[];for(let entry of entries){if(typeof entry!="object"||entry===null)return;let value=entry[idField];if(typeof value!="string"||value.length===0)return;ids.push(value)}return ids}function discoveryHeaders(token){return token===void 0||token.length===0?void 0:{authorization:`Bearer ${token}`}}async function fetchJson(url,options){let fetchImpl=options.fetchImpl??fetch,controller=new AbortController,timer=setTimeout(()=>controller.abort(),options.timeoutMs??LOCAL_DISCOVERY_TIMEOUT_MS),abort=()=>controller.abort();options.signal?.addEventListener("abort",abort,{once:!0});try{let response=await fetchImpl(url,{headers:discoveryHeaders(options.token),signal:controller.signal});return response.ok?{ok:!0,payload:await response.json()}:{ok:!1}}catch{return{ok:!1}}finally{clearTimeout(timer),options.signal?.removeEventListener("abort",abort)}}function apiRoot(baseUrl){return baseUrl.replace(/\/+$/u,"")}async function discoverLocalModels(poolId,options){let root=apiRoot(options.baseUrl),list=await fetchJson(`${root}/models`,options);if(list.ok){let ids2=readModelIds(list.payload?.data,"id");return ids2!==void 0?ids2.map(id=>localModel(id,options.baseUrl)):void 0}if(poolId!=="ollama")return;let tags=await fetchJson(`${apiRoot(root.replace(/\/v1$/u,""))}/api/tags`,options);if(!tags.ok)return;let ids=readModelIds(tags.payload?.models,"name");return ids===void 0?void 0:ids.map(id=>localModel(id,options.baseUrl))}async function refreshLocalModels(poolId,context,dependencies){let slots=await dependencies.resolveSlots(poolId),stored=readStoredLocalModels(poolId,dependencies.agentDirectory,slots)??[];if(!context.allowNetwork||slots.length===0)return stored;let discovered=[],seen=new Set,answered=!1;for(let slot of slots){let models=await discoverLocalModels(poolId,{baseUrl:slot.baseUrl,signal:context.signal,fetchImpl:dependencies.fetchImpl,timeoutMs:dependencies.timeoutMs,token:await dependencies.resolveToken?.(poolId,slot.slotId)});if(models!==void 0){answered=!0;for(let model2 of models)seen.has(model2.id)||(seen.add(model2.id),discovered.push(model2))}}return answered?discovered.length===0?[]:(writeStoredLocalModels(poolId,discovered,dependencies.agentDirectory),discovered):stored}function registerLocalProviders(pi,dependencies){if(typeof pi.registerProvider=="function")for(let poolId of LOCAL_PROVIDER_IDS){let stored=readStoredLocalModels(poolId,dependencies.agentDirectory);pi.registerProvider(poolId,{name:LOCAL_PROVIDER_NAMES[poolId],api:"openai-completions",apiKey:LOCAL_CLIENT_PLACEHOLDER,authHeader:!1,...stored===void 0?{}:{models:stored},async refreshModels(context){return refreshLocalModels(poolId,context,dependencies)}})}}var DEFAULT_SNAPSHOT={slotKind:"api_key"},snapshot={...DEFAULT_SNAPSHOT},changeListener;function setFooterRouteChangeListener(listener){changeListener=listener}function setFooterRouteSnapshot(next){let previous=snapshot;snapshot={slotKind:next.slotKind,...next.route===void 0?{}:{route:next.route},...next.remainingPercent===void 0?{}:{remainingPercent:next.remainingPercent}},(previous.slotKind!==snapshot.slotKind||previous.route!==snapshot.route||previous.remainingPercent!==snapshot.remainingPercent)&&changeListener?.()}function getFooterRouteSnapshot(){return{...snapshot}}var AccountBalancer=class{constructor(now=Date.now){this.cooling=new Map,this.sticky=new Map,this.cursors=new Map,this.advanced=new Map,this.now=now}markCooling(poolId,slotId,until){this.cooling.set(`${poolId}/${slotId}`,until),this.sticky.get(poolId)===slotId&&this.sticky.delete(poolId)}isHealthy(poolId,slotId){return(this.cooling.get(`${poolId}/${slotId}`)??0)<=this.now()}cooldownUntil(poolId,slotId){let until=this.cooling.get(`${poolId}/${slotId}`);return until!==void 0&&until>this.now()?until:void 0}pinned(poolId){return this.sticky.get(poolId)}pin(poolId,slotId){this.sticky.set(poolId,slotId)}pinSlot(poolId,slotId){this.advanced.delete(poolId),this.pin(poolId,slotId)}advance(poolId){let pinned=this.sticky.get(poolId);this.sticky.delete(poolId),pinned!==void 0&&this.advanced.set(poolId,pinned)}releaseSlot(poolId,slotId){this.cooling.delete(`${poolId}/${slotId}`),this.sticky.get(poolId)===slotId&&this.sticky.delete(poolId)}release(poolId){this.sticky.delete(poolId)}selectInFamily(poolId,accounts,usage){let pool=accounts.pools[poolId];if(pool===void 0)return;let healthy=pool.slots.filter(slot=>this.isHealthy(poolId,slot.id));if(healthy.length===0)return;let pinned=this.sticky.get(poolId),sticky=healthy.find(slot=>slot.id===pinned);if(sticky!==void 0)return{poolId,slot:sticky,reason:"sticky",remainingPercent:usage?.remainingPercent(poolId,sticky.id)};let skipped=this.advanced.get(poolId),preferred=skipped===void 0?healthy:healthy.filter(slot=>slot.id!==skipped),candidates=preferred.length>0?preferred:healthy;this.advanced.delete(poolId);let selection=(pool.strategy==="quota-first"?this.chooseByQuota(poolId,candidates,usage):void 0)??{poolId,slot:pool.strategy==="sticky"?candidates[0]:this.rotate(poolId,candidates),reason:"round-robin",remainingPercent:void 0};return this.pin(poolId,selection.slot.id),selection}select(requestedPool,accounts,usage){for(let poolId of this.poolOrder(requestedPool,accounts)){let selection=this.selectInFamily(poolId,accounts,usage);if(selection!==void 0)return selection}}chooseByQuota(poolId,healthy,usage){if(usage===void 0)return;let best;for(let slot of healthy){let remainingPercent=usage.remainingPercent(poolId,slot.id);remainingPercent!==void 0&&(best===void 0||remainingPercent>(best.remainingPercent??-1))&&(best={poolId,slot,reason:"quota-first",remainingPercent})}return best}rotate(poolId,healthy){let cursor=this.cursors.get(poolId)??0;return this.cursors.set(poolId,cursor+1),healthy[cursor%healthy.length]}planFailover(from,accounts,available,source2,usage){let to=this.select(from.poolId,accounts,usage);if(to===void 0||to.poolId===from.poolId&&to.slot.id===from.slot.id)return;if(to.poolId===from.poolId)return{from,to,sameFamily:!0};let model2=source2===void 0?void 0:this.findFallbackModel(source2,to.poolId,available);return{from,to,sameFamily:!1,model:model2}}findFallbackModel(source2,poolId,available){let candidates=available.filter(model2=>model2.provider===poolId);if(candidates.length===0)return;let tier=/opus|pro|max/iu.test(source2.id)?/opus|pro|max/iu:/sonnet|medium|flash/iu.test(source2.id)?/sonnet|medium|flash/iu:void 0;return(tier===void 0?void 0:candidates.find(model2=>tier.test(model2.id)))??candidates[0]}poolOrder(requested,accounts){let configured=accounts.fallback;if(!isLocalPool(requested))return[requested,...configured.filter(poolId=>poolId!==requested)];let placed=configured.indexOf(requested);if(placed>=0)return[requested,...configured.slice(placed+1)];let locals=Object.keys(accounts.pools).filter(poolId=>isLocalPool(poolId)&&poolId!==requested);return[requested,...configured.filter(poolId=>locals.includes(poolId)),...locals.filter(poolId=>!configured.includes(poolId))]}};var QUOTA_TOKENS=/usage[ _-]?limit|rate[ _-]?limit|quota/iu;function header(headers,name){if(headers===void 0)return;let key=Object.keys(headers).find(candidate=>candidate.toLowerCase()===name);return key===void 0?void 0:headers[key]}function parsedReset(failure,now){let retryAfter=header(failure.headers,"retry-after");if(retryAfter!==void 0){let seconds=Number(retryAfter);if(Number.isFinite(seconds)&&seconds>=0)return now+seconds*1e3;let timestamp=Date.parse(retryAfter);if(Number.isFinite(timestamp))return timestamp}for(let name of["x-ratelimit-reset","x-rate-limit-reset","anthropic-ratelimit-unified-reset"]){let value=header(failure.headers,name);if(value===void 0)continue;let numeric2=Number(value);if(Number.isFinite(numeric2))return numeric2>1e10?numeric2:numeric2*1e3;let timestamp=Date.parse(value);if(Number.isFinite(timestamp))return timestamp}}function classify(failure,quotaText,now){let quotaShaped=failure.status===403&&QUOTA_TOKENS.test(quotaText);if(!(failure.status!==429&&failure.status!==402&&!quotaShaped))return{kind:"cooldown",until:parsedReset(failure,now)??now+18e6,reason:`provider response ${failure.status}`}}function classifyProviderFailure(failure,now=Date.now()){return classify(failure,Object.values(failure.headers??{}).filter(Boolean).join(" "),now)}var LIMIT_FAMILIES=[{limit:"anthropic-ratelimit-unified-limit",remaining:"anthropic-ratelimit-unified-remaining",reset:"anthropic-ratelimit-unified-reset"},{limit:"anthropic-ratelimit-requests-limit",remaining:"anthropic-ratelimit-requests-remaining",reset:"anthropic-ratelimit-requests-reset"},{limit:"anthropic-ratelimit-tokens-limit",remaining:"anthropic-ratelimit-tokens-remaining",reset:"anthropic-ratelimit-tokens-reset"},{limit:"anthropic-ratelimit-input-tokens-limit",remaining:"anthropic-ratelimit-input-tokens-remaining",reset:"anthropic-ratelimit-input-tokens-reset"},{limit:"anthropic-ratelimit-output-tokens-limit",remaining:"anthropic-ratelimit-output-tokens-remaining",reset:"anthropic-ratelimit-output-tokens-reset"},{limit:"x-ratelimit-limit-requests",remaining:"x-ratelimit-remaining-requests",reset:"x-ratelimit-reset-requests"},{limit:"x-ratelimit-limit-tokens",remaining:"x-ratelimit-remaining-tokens",reset:"x-ratelimit-reset-tokens"},{limit:"ratelimit-limit",remaining:"ratelimit-remaining",reset:"ratelimit-reset"},{limit:"x-ratelimit-limit",remaining:"x-ratelimit-remaining",reset:"x-ratelimit-reset"}],WINDOW_HEADERS=["anthropic-ratelimit-unified-window","x-ratelimit-window","ratelimit-policy"];function headerValue(headers,name){let key=Object.keys(headers).find(candidate=>candidate.toLowerCase()===name);return key===void 0?void 0:headers[key]}function parseCount(raw){if(raw===void 0)return;let match2=/^\s*([\d.]+)\s*([km])?\s*$/iu.exec(raw);if(match2===null)return;let value=Number(match2[1]);if(!Number.isFinite(value)||value<0)return;let scale=match2[2]?.toLowerCase()==="k"?1e3:match2[2]?.toLowerCase()==="m"?1e6:1;return value*scale}function parseReset(raw,nowMs){if(raw===void 0)return;let duration=/^\s*(?:(\d+)h)?(?:(\d+)m)?(?:([\d.]+)s)?\s*$/iu.exec(raw);if(duration!==null&&(duration[1]??duration[2]??duration[3])!==void 0){let hours=Number(duration[1]??0),minutes=Number(duration[2]??0),seconds=Number(duration[3]??0);return nowMs+((hours*60+minutes)*60+seconds)*1e3}let numeric2=Number(raw);if(Number.isFinite(numeric2))return numeric2>1e10?numeric2:numeric2*1e3;let parsed=Date.parse(raw);return Number.isFinite(parsed)?parsed:void 0}function readUsageHeaders(headers,nowMs){let remainingPercent,resetAt;for(let family2 of LIMIT_FAMILIES){let limit=parseCount(headerValue(headers,family2.limit)),remaining=parseCount(headerValue(headers,family2.remaining));if(limit===void 0||remaining===void 0||limit<=0)continue;let percent=Math.max(0,Math.min(100,Math.round(remaining/limit*100)));(remainingPercent===void 0||percent<remainingPercent)&&(remainingPercent=percent,resetAt=parseReset(headerValue(headers,family2.reset),nowMs))}let retryAfter=parseReset(headerValue(headers,"retry-after"),nowMs);resetAt===void 0&&retryAfter!==void 0&&(resetAt=retryAfter);let window=WINDOW_HEADERS.map(name=>headerValue(headers,name)).find(value=>value!==void 0&&value.length>0);if(!(remainingPercent===void 0&&resetAt===void 0&&window===void 0))return{remainingPercent,resetAt,window}}var UsageCache=class{constructor(options={}){this.snapshots=new Map,this.now=options.now??Date.now,this.readers=options.readers??{}}get(poolId,slotId){return this.snapshots.get(`${poolId}/${slotId}`)}remainingPercent(poolId,slotId){return this.snapshots.get(`${poolId}/${slotId}`)?.remainingPercent}entries(){return[...this.snapshots.values()]}hasReader(poolId){return this.readers[poolId]!==void 0}write(poolId,slotId,source2,reading){let percent=reading.remainingPercent,resetAt=reading.resetAt,window=reading.window,snapshot2={poolId,slotId,remainingPercent:typeof percent=="number"&&Number.isFinite(percent)?Math.max(0,Math.min(100,Math.round(percent))):void 0,resetAt:typeof resetAt=="number"&&Number.isFinite(resetAt)?resetAt:void 0,window:typeof window=="string"&&window.length>0?window:void 0,source:source2,observedAtMs:this.now()};return this.snapshots.set(`${poolId}/${slotId}`,snapshot2),snapshot2}recordHeaders(poolId,slotId,headers){let reading=readUsageHeaders(headers,this.now());return reading===void 0?void 0:this.write(poolId,slotId,"headers",reading)}async refresh(poolId,slotId,signal){let reader=this.readers[poolId];if(reader!==void 0)try{let reading=await reader({poolId,slotId,signal});return reading===void 0?void 0:this.write(poolId,slotId,"reader",reading)}catch{return}}async refreshAll(slots,signal){return(await Promise.all(slots.filter(slot=>this.hasReader(slot.poolId)).map(slot=>this.refresh(slot.poolId,slot.slotId,signal)))).filter(snapshot2=>snapshot2!==void 0)}forget(poolId,slotId){this.snapshots.delete(`${poolId}/${slotId}`)}};function renderAccountsWidget(document,options={}){let now=options.now??Date.now(),lines=["ACCOUNTS"];for(let[poolId,pool]of Object.entries(document.pools)){if(pool===void 0||pool.slots.length===0)continue;let slots=pool.slots.map(slot=>{let snapshot2=options.usage?.get(poolId,slot.id),percent=slot.kind==="local"?"(local) $0":snapshot2?.remainingPercent===void 0?"?%":`${snapshot2.remainingPercent}%`,window=snapshot2?.window===void 0?"":` ${snapshot2.window}`,cooldownUntil=options.health?.cooldownUntil(poolId,slot.id),cooldown=cooldownUntil===void 0||cooldownUntil<=now?"":` cd ${Math.ceil((cooldownUntil-now)/6e4)}m`;return`${slot.label??slot.id} ${percent}${window}${cooldown}`});lines.push(` ${poolId.toUpperCase()} ${slots.join(" ")}`)}return options.route!==void 0&&lines.push(`ROUTE ${options.route.provider}/${options.route.model} via ${options.route.slot}`),lines.join(`
1310
+ `)){if(/^\|\s*Role\s*\|/u.test(line)){inRoleTable=!0;continue}if(inRoleTable){if(!line.trimStart().startsWith("|"))inRoleTable=!1;else if(!/^\|\s*-+/u.test(line.trimStart())){let cells=splitRow(line);if(cells.length>=4){let role=cells[0].replace(/`/gu,"").trim();roles.push({role,prefer:patternsFrom(cells[1]),why:cells[2],confidence:cells[3]})}continue}}let ordered2=/^\s*(\d+)\.\s+(.+?)\s+—/u.exec(line);ordered2!==null&&workingOrder.push(ordered2[2].trim())}let missing=REQUIRED_ROLES.filter(role=>!roles.some(entry=>entry.role===role));if(missing.length>0)throw new LadderError(`model ladder has no row for: ${missing.join(", ")}`);for(let entry of roles)if(entry.prefer.length===0&&!/inherit-parent/u.test(entry.why))throw new LadderError(`model ladder role ${entry.role} offers no pattern`);return{roles,workingOrder}}function ladderCandidates(resourceDirectory){return[join39(resourceDirectory,"kstack",LADDER_FILE),join39(resourceDirectory,"..","..","..","docs",LADDER_FILE),join39(resourceDirectory,"..","..","..","..","docs",LADDER_FILE)]}async function readModelLadder(resourceDirectory=getKpiResourceDir()){let attempted=[];for(let candidate of ladderCandidates(resourceDirectory)){attempted.push(candidate);let source2=await readFile11(candidate,"utf8").catch(error=>{if(error.code!=="ENOENT")throw error});if(source2!==void 0)return parseModelLadder(source2)}throw new LadderError(`no ${LADDER_FILE} found; looked in ${attempted.join(", ")}`)}function family(slug){return slug.split("/")[0]}function suggestForRole(entry,candidates,workingOrder){let ranked=[];for(let pattern of entry.prefer){let hits=candidates.filter(slug=>slug.toLowerCase().includes(pattern.toLowerCase())).filter(slug=>!ranked.some(found=>found.slug===slug)).sort((left,right)=>tieBreak(left,right,workingOrder));for(let slug of hits)ranked.push({slug,pattern})}return ranked.length===0?{role:entry.role,confidence:entry.confidence}:{role:entry.role,chosen:ranked[0].slug,matched:ranked[0].pattern,nextBest:ranked[1]?.slug,confidence:entry.confidence}}function tieBreak(left,right,workingOrder){let rank=slug=>{let index3=workingOrder.findIndex(name=>slug.toLowerCase().includes(normalizeName(name)));return index3===-1?Number.MAX_SAFE_INTEGER:index3},difference=rank(left)-rank(right);return difference!==0?difference:left.localeCompare(right)}function orderCandidates(candidates,workingOrder){return[...candidates].sort((left,right)=>tieBreak(left,right,workingOrder))}function normalizeName(name){return name.toLowerCase().replace(/\s+/gu,"-").replace(/[^a-z0-9.-]/gu,"")}var PANEL_CAP=3;function suggestPanel(entry,candidates,workingOrder,cap=PANEL_CAP){let panel=[],seen=new Set;for(let pattern of entry.prefer)for(let slug of candidates.filter(candidate=>candidate.toLowerCase().includes(pattern.toLowerCase())).sort((left,right)=>tieBreak(left,right,workingOrder)))!seen.has(family(slug))&&panel.length<cap&&(seen.add(family(slug)),panel.push(slug));if(panel.length===0)for(let slug of[...candidates].sort((left,right)=>tieBreak(left,right,workingOrder)))!seen.has(family(slug))&&panel.length<cap&&(seen.add(family(slug)),panel.push(slug));return panel}var INHERIT_PARENT="inherit-parent",HEALTHY_POOLS=new Set(POOL_IDS);function liveCandidates(models,configuredPools){let seen=new Set,candidates=[];for(let model2 of models){if(!HEALTHY_POOLS.has(model2.provider)||!configuredPools.has(model2.provider))continue;let slug=`${model2.provider}/${model2.id}`;seen.has(slug)||(seen.add(slug),candidates.push(slug))}return candidates}function planModels(ladder,candidates){return REQUIRED_ROLES.map(role=>{let entry=ladder.roles.find(candidate=>candidate.role===role);if(entry===void 0)return{role,confidence:"unknown",value:INHERIT_PARENT};if(role==="review_panel"){let panel=suggestPanel(entry,candidates,ladder.workingOrder,PANEL_CAP);return{role,confidence:entry.confidence,chosen:panel[0],nextBest:panel[1],value:panel.length>0?panel:INHERIT_PARENT}}let suggestion=suggestForRole(entry,candidates,ladder.workingOrder);return{...suggestion,value:suggestion.chosen??INHERIT_PARENT}})}function suggestFallbackModels(ladder,candidates){return orderCandidates(candidates,ladder.workingOrder)}function planToDocument(plan,fallbackModels=[]){let roles={};for(let entry of plan)roles[entry.role]=entry.value;return{version:1,roles,fallback_models:[...fallbackModels],inherit_parent:!1}}function renderPlan(plan){return plan.map(entry=>{let value=Array.isArray(entry.value)?entry.value.join(" + "):entry.value,next=entry.nextBest===void 0?"none":entry.nextBest;return`${entry.role} \u2192 ${value} (next best: ${next}; confidence: ${entry.confidence})`})}function assertKnownModels(document,candidates){let allowed=new Set([...candidates,INHERIT_PARENT]);for(let[role,entry]of Object.entries(document.roles)){let values=Array.isArray(entry)?entry:[entry];if(Array.isArray(entry)&&entry.length>PANEL_CAP)throw new Error(`${role} panel exceeds ${PANEL_CAP} entries`);for(let value of values)if(!allowed.has(value))throw new Error(`Unknown model slug: ${value}`)}for(let value of document.fallback_models??[])if(!allowed.has(value)||value===INHERIT_PARENT)throw new Error(`Unknown fallback model slug: ${value}`)}function modelsPath(){return join40(getAgentDir(),"kstack","models.json")}async function writeKStackModels(document,candidates,path14=modelsPath()){assertKnownModels(document,candidates),await mkdir4(dirname23(path14),{recursive:!0});let temporary=`${path14}.${process.pid}.${randomUUID7()}.tmp`,file=await open6(temporary,"wx",384);try{await file.writeFile(`${JSON.stringify(document,null,2)}
1311
+ `),await file.sync(),await file.close(),await rename4(temporary,path14),await chmod3(path14,384)}catch(error){throw await file.close().catch(()=>{}),await rm4(temporary,{force:!0}),error}}async function readKStackModels(path14=modelsPath()){let source2=await readFile12(path14,"utf8").catch(error=>{if(error.code!=="ENOENT")throw error});if(source2===void 0)return;let parsed=JSON.parse(source2),fallbackValid=parsed.fallback_models===void 0||Array.isArray(parsed.fallback_models)&&parsed.fallback_models.every(value=>typeof value=="string");return parsed.version===1&&typeof parsed.roles=="object"&&fallbackValid?parsed:void 0}async function resolveFallbackModels(path14=modelsPath()){let fallbackModels=(await readKStackModels(path14))?.fallback_models;return fallbackModels===void 0?void 0:[...fallbackModels]}var APPLY="apply this map",APPLY_FALLBACKS="apply this fallback order";async function editPlan(plan,candidates,ui){let current=[...plan];for(;;){let choice=await ui.select("K-stack models",[APPLY,...renderPlan(current),"cancel"]);if(choice===void 0||choice==="cancel")return;if(choice===APPLY)return current;let role=choice.split(" \u2192 ")[0],index3=current.findIndex(entry=>entry.role===role);if(index3===-1)continue;let typed=await ui.input(`${role} model`,`slug, ${INHERIT_PARENT}, or comma-separated for a panel (${candidates.length} live)`);if(typed===void 0||typed.trim().length===0)continue;let values=typed.split(",").map(value2=>value2.trim()).filter(value2=>value2.length>0),allowed=new Set([...candidates,INHERIT_PARENT]),rejected=values.filter(value2=>!allowed.has(value2));if(rejected.length>0){ui.notify(`Not a live model in this session: ${rejected.join(", ")}`,"error");continue}if(role==="review_panel"&&values.length>PANEL_CAP){ui.notify(`A review panel takes at most ${PANEL_CAP} entries`,"error");continue}let value=role==="review_panel"&&values.length>1?values:values[0];current=current.map((entry,position)=>position===index3?{...entry,value}:entry)}}async function editFallbackPlan(fallbackModels,candidates,ui){let current=[...fallbackModels];for(;;){let line=`fallback_models \u2192 ${current.length===0?"none":current.join(", ")}`,choice=await ui.select("K-stack fallback models",[APPLY_FALLBACKS,line,"cancel"]);if(choice===void 0||choice==="cancel")return;if(choice===APPLY_FALLBACKS)return current;if(choice!==line)continue;let typed=await ui.input("fallback_models",`comma-separated model slugs (${candidates.length} live)`);if(typed===void 0||typed.trim().length===0)continue;let values=[...new Set(typed.split(",").map(value=>value.trim()).filter(value=>value.length>0))],allowed=new Set(candidates),rejected=values.filter(value=>!allowed.has(value));if(rejected.length>0){ui.notify(`Not a live model in this session: ${rejected.join(", ")}`,"error");continue}current=values}}function registerKStackSetup(pi){pi.registerCommand("setup-kstack",{description:"Map K-stack roles onto live K-\u03C0 models using the committed model ladder",handler:async(_args,context)=>{let accounts=await new AccountsStore().read(),configuredPools=new Set(Object.entries(accounts.pools).filter(([,pool])=>(pool?.slots.length??0)>0).map(([poolId])=>poolId)),candidates=liveCandidates(context.modelRegistry.getAvailable(),configuredPools);if(candidates.length===0)context.ui.notify("No live model in a K-\u03C0 pool; K-stack roles will inherit the parent session model.","warning");else{let ladder=await readModelLadder(),plan=planModels(ladder,candidates),fallbackPlan=suggestFallbackModels(ladder,candidates);context.ui.notify([...renderPlan(plan),`fallback_models \u2192 ${fallbackPlan.length===0?"none":fallbackPlan.join(", ")}`].join(`
1312
+ `),"info");let edited=await editPlan(plan,candidates,context.ui),editedFallbacks=edited===void 0?void 0:await editFallbackPlan(fallbackPlan,candidates,context.ui);edited===void 0||editedFallbacks===void 0?context.ui.notify("K-stack model map unchanged","info"):(await writeKStackModels(planToDocument(edited,editedFallbacks),candidates),context.ui.notify(`K-stack model map saved to ${modelsPath()}`,"info"))}await promptResearchSetup(context)}})}import{mkdirSync as mkdirSync11,readFileSync as readFileSync15,renameSync as renameSync3,writeFileSync as writeFileSync10}from"node:fs";import{dirname as dirname24,join as join41}from"node:path";var LOCAL_PROVIDER_IDS=["ollama","lmstudio","local-openai"],DEFAULT_LOCAL_BASE_URLS={ollama:"http://127.0.0.1:11434/v1",lmstudio:"http://127.0.0.1:1234/v1","local-openai":void 0},LOCAL_PROVIDER_NAMES={ollama:"Ollama",lmstudio:"LM Studio","local-openai":"Local OpenAI-compatible"},LOCAL_CLIENT_PLACEHOLDER="local",LOCAL_DISCOVERY_TIMEOUT_MS=2e3;function localModel(id,baseUrl,name=id){return{id,name,api:"openai-completions",baseUrl,reasoning:!1,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:32768,maxTokens:4096}}function storedLocalModelsPath(poolId,agentDirectory=getAgentDir()){return join41(agentDirectory,`${poolId}-models.json`)}function readStoredEntries(poolId,agentDirectory){try{let parsed=JSON.parse(readFileSync15(storedLocalModelsPath(poolId,agentDirectory),"utf8"));return Array.isArray(parsed)?parsed.flatMap(entry=>{if(typeof entry!="object"||entry===null)return[];let candidate=entry;return typeof candidate.id!="string"||candidate.id.length===0?[]:typeof candidate.baseUrl!="string"||candidate.baseUrl.length===0?[]:[{id:candidate.id,name:typeof candidate.name=="string"?candidate.name:candidate.id,baseUrl:candidate.baseUrl}]}):[]}catch{return[]}}function readStoredLocalModels(poolId,agentDirectory,slots){let entries=readStoredEntries(poolId,agentDirectory),allowed=slots===void 0?void 0:new Set(slots.map(slot=>slot.baseUrl)),models=entries.filter(entry=>allowed===void 0||allowed.has(entry.baseUrl)).map(entry=>localModel(entry.id,entry.baseUrl,entry.name));return models.length===0?void 0:models}function writeStoredLocalModels(poolId,models,agentDirectory){let path14=storedLocalModelsPath(poolId,agentDirectory),temporaryPath=`${path14}.${process.pid}.tmp`,entries=models.map(entry=>({id:entry.id,name:entry.name,baseUrl:entry.baseUrl??""}));try{mkdirSync11(dirname24(path14),{recursive:!0}),writeFileSync10(temporaryPath,`${JSON.stringify(entries,null,2)}
1313
+ `,{encoding:"utf8",mode:384}),renameSync3(temporaryPath,path14)}catch{}}function readModelIds(entries,idField){if(!Array.isArray(entries))return;let ids=[];for(let entry of entries){if(typeof entry!="object"||entry===null)return;let value=entry[idField];if(typeof value!="string"||value.length===0)return;ids.push(value)}return ids}function discoveryHeaders(token){return token===void 0||token.length===0?void 0:{authorization:`Bearer ${token}`}}async function fetchJson(url,options){let fetchImpl=options.fetchImpl??fetch,controller=new AbortController,timer=setTimeout(()=>controller.abort(),options.timeoutMs??LOCAL_DISCOVERY_TIMEOUT_MS),abort=()=>controller.abort();options.signal?.addEventListener("abort",abort,{once:!0});try{let response=await fetchImpl(url,{headers:discoveryHeaders(options.token),signal:controller.signal});return response.ok?{ok:!0,payload:await response.json()}:{ok:!1}}catch{return{ok:!1}}finally{clearTimeout(timer),options.signal?.removeEventListener("abort",abort)}}function apiRoot(baseUrl){return baseUrl.replace(/\/+$/u,"")}async function discoverLocalModels(poolId,options){let root=apiRoot(options.baseUrl),list=await fetchJson(`${root}/models`,options);if(list.ok){let ids2=readModelIds(list.payload?.data,"id");return ids2!==void 0?ids2.map(id=>localModel(id,options.baseUrl)):void 0}if(poolId!=="ollama")return;let tags=await fetchJson(`${apiRoot(root.replace(/\/v1$/u,""))}/api/tags`,options);if(!tags.ok)return;let ids=readModelIds(tags.payload?.models,"name");return ids===void 0?void 0:ids.map(id=>localModel(id,options.baseUrl))}async function refreshLocalModels(poolId,context,dependencies){let slots=await dependencies.resolveSlots(poolId),stored=readStoredLocalModels(poolId,dependencies.agentDirectory,slots)??[];if(!context.allowNetwork||slots.length===0)return stored;let discovered=[],seen=new Set,answered=!1;for(let slot of slots){let models=await discoverLocalModels(poolId,{baseUrl:slot.baseUrl,signal:context.signal,fetchImpl:dependencies.fetchImpl,timeoutMs:dependencies.timeoutMs,token:await dependencies.resolveToken?.(poolId,slot.slotId)});if(models!==void 0){answered=!0;for(let model2 of models)seen.has(model2.id)||(seen.add(model2.id),discovered.push(model2))}}return answered?discovered.length===0?[]:(writeStoredLocalModels(poolId,discovered,dependencies.agentDirectory),discovered):stored}function registerLocalProviders(pi,dependencies){if(typeof pi.registerProvider=="function")for(let poolId of LOCAL_PROVIDER_IDS){let stored=readStoredLocalModels(poolId,dependencies.agentDirectory);pi.registerProvider(poolId,{name:LOCAL_PROVIDER_NAMES[poolId],api:"openai-completions",apiKey:LOCAL_CLIENT_PLACEHOLDER,authHeader:!1,...stored===void 0?{}:{models:stored},async refreshModels(context){return refreshLocalModels(poolId,context,dependencies)}})}}var DEFAULT_SNAPSHOT={slotKind:"api_key"},snapshot={...DEFAULT_SNAPSHOT},changeListener;function setFooterRouteChangeListener(listener){changeListener=listener}function setFooterRouteSnapshot(next){let previous=snapshot;snapshot={slotKind:next.slotKind,...next.route===void 0?{}:{route:next.route},...next.remainingPercent===void 0?{}:{remainingPercent:next.remainingPercent}},(previous.slotKind!==snapshot.slotKind||previous.route!==snapshot.route||previous.remainingPercent!==snapshot.remainingPercent)&&changeListener?.()}function getFooterRouteSnapshot(){return{...snapshot}}var LOW_QUOTA_REMAINING_PERCENT=5;var AccountBalancer=class{constructor(now=Date.now){this.cooling=new Map,this.sticky=new Map,this.cursors=new Map,this.advanced=new Map,this.now=now}markCooling(poolId,slotId,until){this.cooling.set(`${poolId}/${slotId}`,until),this.sticky.get(poolId)===slotId&&this.sticky.delete(poolId)}isHealthy(poolId,slotId){return(this.cooling.get(`${poolId}/${slotId}`)??0)<=this.now()}cooldownUntil(poolId,slotId){let until=this.cooling.get(`${poolId}/${slotId}`);return until!==void 0&&until>this.now()?until:void 0}pinned(poolId){return this.sticky.get(poolId)}pin(poolId,slotId){this.sticky.set(poolId,slotId)}pinSlot(poolId,slotId){this.advanced.delete(poolId),this.pin(poolId,slotId)}advance(poolId){let pinned=this.sticky.get(poolId);this.sticky.delete(poolId),pinned!==void 0&&this.advanced.set(poolId,pinned)}releaseSlot(poolId,slotId){this.cooling.delete(`${poolId}/${slotId}`),this.sticky.get(poolId)===slotId&&this.sticky.delete(poolId)}release(poolId){this.sticky.delete(poolId)}selectInFamily(poolId,accounts,usage){let pool=accounts.pools[poolId];if(pool===void 0)return;let healthy=pool.slots.filter(slot=>this.isHealthy(poolId,slot.id));if(healthy.length===0)return;let pinned=this.sticky.get(poolId),sticky=healthy.find(slot=>slot.id===pinned);if(sticky!==void 0){let remainingPercent=usage?.remainingPercent(poolId,sticky.id);if(remainingPercent!==void 0){let alternatives=healthy.filter(slot=>slot.id!==sticky.id),replacement=this.chooseByQuota(poolId,alternatives,usage)??(alternatives.length===0?void 0:{poolId,slot:this.rotate(poolId,alternatives),reason:"round-robin"});if(remainingPercent<=LOW_QUOTA_REMAINING_PERCENT&&replacement!==void 0&&(replacement.remainingPercent===void 0||replacement.remainingPercent>remainingPercent))return this.pin(poolId,replacement.slot.id),replacement}return{poolId,slot:sticky,reason:"sticky",remainingPercent}}let skipped=this.advanced.get(poolId),preferred=skipped===void 0?healthy:healthy.filter(slot=>slot.id!==skipped),candidates=preferred.length>0?preferred:healthy;this.advanced.delete(poolId);let selection=(pool.strategy==="quota-first"?this.chooseByQuota(poolId,candidates,usage):void 0)??{poolId,slot:pool.strategy==="sticky"?candidates[0]:this.rotate(poolId,candidates),reason:"round-robin",remainingPercent:void 0};return this.pin(poolId,selection.slot.id),selection}select(requestedPool,accounts,usage){for(let poolId of this.poolOrder(requestedPool,accounts)){let selection=this.selectInFamily(poolId,accounts,usage);if(selection!==void 0)return selection}}chooseByQuota(poolId,healthy,usage){if(usage===void 0)return;let best;for(let slot of healthy){let remainingPercent=usage.remainingPercent(poolId,slot.id);remainingPercent!==void 0&&(best===void 0||remainingPercent>(best.remainingPercent??-1))&&(best={poolId,slot,reason:"quota-first",remainingPercent})}return best}rotate(poolId,healthy){let cursor=this.cursors.get(poolId)??0;return this.cursors.set(poolId,cursor+1),healthy[cursor%healthy.length]}planFailover(from,accounts,available,source2,usage,preferredModelSlugs){let sibling=this.selectInFamily(from.poolId,accounts,usage);if(sibling!==void 0&&sibling.slot.id!==from.slot.id)return{from,to:sibling,sameFamily:!0};if(preferredModelSlugs!==void 0){for(let slug of preferredModelSlugs){let slash=slug.indexOf("/"),poolName=slash<1?void 0:slug.slice(0,slash);if(poolName===void 0||!isPoolId(poolName)||poolName===from.poolId)continue;let model3=available.find(candidate=>candidate.provider===poolName&&candidate.id===slug.slice(slash+1));if(model3===void 0)continue;let to2=this.selectInFamily(poolName,accounts,usage);if(to2!==void 0)return{from,to:to2,sameFamily:!1,model:model3}}return}let to=this.select(from.poolId,accounts,usage);if(to===void 0||to.poolId===from.poolId)return;let model2=source2===void 0?void 0:this.findFallbackModel(source2,to.poolId,available);return{from,to,sameFamily:!1,model:model2}}findFallbackModel(source2,poolId,available){let candidates=available.filter(model2=>model2.provider===poolId);if(candidates.length===0)return;let tier=/opus|pro|max/iu.test(source2.id)?/opus|pro|max/iu:/sonnet|medium|flash/iu.test(source2.id)?/sonnet|medium|flash/iu:void 0;return(tier===void 0?void 0:candidates.find(model2=>tier.test(model2.id)))??candidates[0]}poolOrder(requested,accounts){let configured=accounts.fallback;if(!isLocalPool(requested))return[requested,...configured.filter(poolId=>poolId!==requested)];let placed=configured.indexOf(requested);if(placed>=0)return[requested,...configured.slice(placed+1)];let locals=Object.keys(accounts.pools).filter(poolId=>isLocalPool(poolId)&&poolId!==requested);return[requested,...configured.filter(poolId=>locals.includes(poolId)),...locals.filter(poolId=>!configured.includes(poolId))]}};var QUOTA_TOKENS=/usage[ _-]?limit|rate[ _-]?limit|extra[ _-]?usage|quota/iu;function header(headers,name){if(headers===void 0)return;let key=Object.keys(headers).find(candidate=>candidate.toLowerCase()===name);return key===void 0?void 0:headers[key]}function parsedReset(failure,now){let retryAfter=header(failure.headers,"retry-after");if(retryAfter!==void 0){let seconds=Number(retryAfter);if(Number.isFinite(seconds)&&seconds>=0)return now+seconds*1e3;let timestamp=Date.parse(retryAfter);if(Number.isFinite(timestamp))return timestamp}for(let name of["x-ratelimit-reset","x-rate-limit-reset","anthropic-ratelimit-unified-reset"]){let value=header(failure.headers,name);if(value===void 0)continue;let numeric2=Number(value);if(Number.isFinite(numeric2))return numeric2>1e10?numeric2:numeric2*1e3;let timestamp=Date.parse(value);if(Number.isFinite(timestamp))return timestamp}}function classify(failure,quotaText,now,allowQuotaBadRequest=!1){let quotaShaped=(failure.status===403||allowQuotaBadRequest&&failure.status===400)&&QUOTA_TOKENS.test(quotaText);if(!(failure.status!==429&&failure.status!==402&&!quotaShaped))return{kind:"cooldown",until:parsedReset(failure,now)??now+18e6,reason:`provider response ${failure.status}`}}function classifyProviderFailure(failure,now=Date.now()){return classify(failure,Object.values(failure.headers??{}).filter(Boolean).join(" "),now)}function classifyProviderBodyFailure(failure,now=Date.now()){return classify(failure,[failure.body,...Object.values(failure.headers??{})].filter(Boolean).join(" "),now,!0)}var LIMIT_FAMILIES=[{limit:"anthropic-ratelimit-unified-limit",remaining:"anthropic-ratelimit-unified-remaining",reset:"anthropic-ratelimit-unified-reset"},{limit:"anthropic-ratelimit-requests-limit",remaining:"anthropic-ratelimit-requests-remaining",reset:"anthropic-ratelimit-requests-reset"},{limit:"anthropic-ratelimit-tokens-limit",remaining:"anthropic-ratelimit-tokens-remaining",reset:"anthropic-ratelimit-tokens-reset"},{limit:"anthropic-ratelimit-input-tokens-limit",remaining:"anthropic-ratelimit-input-tokens-remaining",reset:"anthropic-ratelimit-input-tokens-reset"},{limit:"anthropic-ratelimit-output-tokens-limit",remaining:"anthropic-ratelimit-output-tokens-remaining",reset:"anthropic-ratelimit-output-tokens-reset"},{limit:"x-ratelimit-limit-requests",remaining:"x-ratelimit-remaining-requests",reset:"x-ratelimit-reset-requests"},{limit:"x-ratelimit-limit-tokens",remaining:"x-ratelimit-remaining-tokens",reset:"x-ratelimit-reset-tokens"},{limit:"ratelimit-limit",remaining:"ratelimit-remaining",reset:"ratelimit-reset"},{limit:"x-ratelimit-limit",remaining:"x-ratelimit-remaining",reset:"x-ratelimit-reset"}],USED_PERCENT_FAMILIES=[{used:"x-codex-primary-used-percent",resetAt:"x-codex-primary-reset-at",resetAfter:"x-codex-primary-reset-after-seconds",windowMinutes:"x-codex-primary-window-minutes"},{used:"x-codex-secondary-used-percent",resetAt:"x-codex-secondary-reset-at",resetAfter:"x-codex-secondary-reset-after-seconds",windowMinutes:"x-codex-secondary-window-minutes"}],WINDOW_HEADERS=["anthropic-ratelimit-unified-window","x-ratelimit-window","ratelimit-policy"];function headerValue(headers,name){let key=Object.keys(headers).find(candidate=>candidate.toLowerCase()===name);return key===void 0?void 0:headers[key]}function parseCount(raw){if(raw===void 0)return;let match2=/^\s*([\d.]+)\s*([km])?\s*$/iu.exec(raw);if(match2===null)return;let value=Number(match2[1]);if(!Number.isFinite(value)||value<0)return;let scale=match2[2]?.toLowerCase()==="k"?1e3:match2[2]?.toLowerCase()==="m"?1e6:1;return value*scale}function parseReset(raw,nowMs){if(raw===void 0)return;let duration=/^\s*(?:(\d+)h)?(?:(\d+)m)?(?:([\d.]+)s)?\s*$/iu.exec(raw);if(duration!==null&&(duration[1]??duration[2]??duration[3])!==void 0){let hours=Number(duration[1]??0),minutes=Number(duration[2]??0),seconds=Number(duration[3]??0);return nowMs+((hours*60+minutes)*60+seconds)*1e3}let numeric2=Number(raw);if(Number.isFinite(numeric2))return numeric2>1e10?numeric2:numeric2*1e3;let parsed=Date.parse(raw);return Number.isFinite(parsed)?parsed:void 0}function readUsageHeaders(headers,nowMs){let remainingPercent,resetAt,bindingWindow;for(let family2 of LIMIT_FAMILIES){let limit=parseCount(headerValue(headers,family2.limit)),remaining=parseCount(headerValue(headers,family2.remaining));if(limit===void 0||remaining===void 0||limit<=0)continue;let percent=Math.max(0,Math.min(100,Math.round(remaining/limit*100)));(remainingPercent===void 0||percent<remainingPercent)&&(remainingPercent=percent,resetAt=parseReset(headerValue(headers,family2.reset),nowMs))}for(let family2 of USED_PERCENT_FAMILIES){let used=parseCount(headerValue(headers,family2.used));if(used===void 0)continue;let percent=Math.max(0,Math.min(100,Math.round(100-used)));if(remainingPercent===void 0||percent<remainingPercent){remainingPercent=percent;let resetAfterSeconds=parseCount(headerValue(headers,family2.resetAfter));resetAt=parseReset(headerValue(headers,family2.resetAt),nowMs)??(resetAfterSeconds===void 0?void 0:nowMs+resetAfterSeconds*1e3);let windowMinutes=headerValue(headers,family2.windowMinutes);bindingWindow=parseCount(windowMinutes)===void 0?void 0:`${windowMinutes}m`}}let retryAfter=parseReset(headerValue(headers,"retry-after"),nowMs);resetAt===void 0&&retryAfter!==void 0&&(resetAt=retryAfter);let window=WINDOW_HEADERS.map(name=>headerValue(headers,name)).find(value=>value!==void 0&&value.length>0)??bindingWindow;if(!(remainingPercent===void 0&&resetAt===void 0&&window===void 0))return{remainingPercent,resetAt,window}}var UsageCache=class{constructor(options={}){this.snapshots=new Map,this.now=options.now??Date.now,this.readers=options.readers??{}}get(poolId,slotId){return this.snapshots.get(`${poolId}/${slotId}`)}remainingPercent(poolId,slotId){return this.snapshots.get(`${poolId}/${slotId}`)?.remainingPercent}entries(){return[...this.snapshots.values()]}hasReader(poolId){return this.readers[poolId]!==void 0}write(poolId,slotId,source2,reading){let percent=reading.remainingPercent,resetAt=reading.resetAt,window=reading.window,snapshot2={poolId,slotId,remainingPercent:typeof percent=="number"&&Number.isFinite(percent)?Math.max(0,Math.min(100,Math.round(percent))):void 0,resetAt:typeof resetAt=="number"&&Number.isFinite(resetAt)?resetAt:void 0,window:typeof window=="string"&&window.length>0?window:void 0,source:source2,observedAtMs:this.now()};return this.snapshots.set(`${poolId}/${slotId}`,snapshot2),snapshot2}recordHeaders(poolId,slotId,headers){let reading=readUsageHeaders(headers,this.now());return reading===void 0?void 0:this.write(poolId,slotId,"headers",reading)}async refresh(poolId,slotId,signal){let reader=this.readers[poolId];if(reader!==void 0)try{let reading=await reader({poolId,slotId,signal});return reading===void 0?void 0:this.write(poolId,slotId,"reader",reading)}catch{return}}async refreshAll(slots,signal){return(await Promise.all(slots.filter(slot=>this.hasReader(slot.poolId)).map(slot=>this.refresh(slot.poolId,slot.slotId,signal)))).filter(snapshot2=>snapshot2!==void 0)}forget(poolId,slotId){this.snapshots.delete(`${poolId}/${slotId}`)}};function renderAccountsWidget(document,options={}){let now=options.now??Date.now(),lines=["ACCOUNTS"];for(let[poolId,pool]of Object.entries(document.pools)){if(pool===void 0||pool.slots.length===0)continue;let slots=pool.slots.map(slot=>{let snapshot2=options.usage?.get(poolId,slot.id),percent=slot.kind==="local"?"(local) $0":snapshot2?.remainingPercent===void 0?"?%":`${snapshot2.remainingPercent}%`,window=snapshot2?.window===void 0?"":` ${snapshot2.window}`,cooldownUntil=options.health?.cooldownUntil(poolId,slot.id),cooldown=cooldownUntil===void 0||cooldownUntil<=now?"":` cd ${Math.ceil((cooldownUntil-now)/6e4)}m`;return`${slot.label??slot.id} ${percent}${window}${cooldown}`});lines.push(` ${poolId.toUpperCase()} ${slots.join(" ")}`)}return options.route!==void 0&&lines.push(`ROUTE ${options.route.provider}/${options.route.model} via ${options.route.slot}`),lines.join(`
1314
1314
  `)}var ANTHROPIC_EXTRA_USAGE_WARNING=`Claude Pro/Max in this harness uses Anthropic\u2019s subscription OAuth, same as Pi and Atomic.
1315
1315
 
1316
1316
  Anthropic\u2019s own docs: third-party harness usage draws from extra usage and is billed per token, not against the in-app Claude plan bar.
@@ -1322,11 +1322,13 @@ You are responsible for the seats you attach.
1322
1322
  Continue?`,CODEX_BILLING_CONFIRM="OpenAI Codex in this harness bills your Codex plan for every token this seat sends. Continue?",CURSOR_BILLING_CONFIRM="Cursor in this harness bills your Cursor plan for every token this seat sends. Continue?",ZAI_PERSONAL_USE_NOTE="z.ai Coding Plan is personal-use and official-tool-only; K-\u03C0 routes it through Pi's supported zai provider.";function authHeaderName(api,credentialType){if(credentialType!=="api_key")return"authorization";switch(api){case"anthropic-messages":return"x-api-key";case"google-generative-ai":case"google-vertex":return"x-goog-api-key";case"azure-openai-responses":return"api-key";default:return"authorization"}}function setAuthHeader(headers,api,credentialType,token){let name=authHeaderName(api,credentialType);for(let competing of["authorization","x-api-key","x-goog-api-key","api-key"])competing!==name&&headers[competing]!==void 0&&(headers[competing]=null);headers[name]=name==="authorization"?`Bearer ${token}`:token}function providerNotice(poolId){if(poolId==="anthropic")return{kind:"confirm",title:"Anthropic extra-usage warning",message:ANTHROPIC_EXTRA_USAGE_WARNING};if(poolId==="openai-codex")return{kind:"confirm",title:"Codex billing",message:CODEX_BILLING_CONFIRM};if(poolId==="cursor")return{kind:"confirm",title:"Cursor billing",message:CURSOR_BILLING_CONFIRM};if(poolId==="zai"||poolId==="zai-coding-cn")return{kind:"note",title:"z.ai Coding Plan",message:ZAI_PERSONAL_USE_NOTE}}var LoginCancelledError=class extends Error{constructor(){super("Login cancelled")}};function authEventMessage(event){if(event.type==="auth_url")return[event.instructions,event.url].filter(Boolean).join(`
1323
1323
  `);if(event.type==="device_code")return`${event.verificationUri}
1324
1324
  Code: ${event.userCode}`;let links=event.type==="info"?event.links??[]:[];return[event.message,...links.map(link2=>link2.url)].join(`
1325
- `)}async function answerAuthPrompt(prompt,context){if(prompt.type==="select"){let labels=prompt.options.map(option2=>option2.label),selected=await context.ui.select(prompt.message,labels,{signal:prompt.signal}),option=prompt.options.find(candidate=>candidate.label===selected);if(option===void 0)throw new LoginCancelledError;return option.id}let answer=await context.ui.input(prompt.message,prompt.placeholder,{signal:prompt.signal});if(answer===void 0)throw new LoginCancelledError;return answer}function openAuthUrl(pi,url){let command=process.platform==="darwin"?{name:"open",args:[url]}:process.platform==="win32"?{name:"cmd",args:["/c","start","",url]}:{name:"xdg-open",args:[url]};pi.exec(command.name,command.args).catch(()=>{})}async function loginWithOfficialProvider(providerId,_slotId,context,showAuthUrl){let auth=context.modelRegistry.getProvider(providerId)?.auth;if(auth?.oauth!==void 0){let interaction={signal:context.signal??new AbortController().signal,prompt:prompt=>answerAuthPrompt(prompt,context),notify:event=>{event.type==="auth_url"&&showAuthUrl(event.url),context.ui.notify(authEventMessage(event),"info")}};return auth.oauth.login(interaction)}if(auth?.apiKey!==void 0){let key=(await context.ui.input(auth.apiKey.name,"Paste the key, or Enter to cancel",{signal:context.signal})??"").trim();if(key.length===0)throw new LoginCancelledError;return{type:"api_key",key}}throw new Error(`Provider ${providerId} offers neither subscription OAuth nor an API key`)}function accountLines(document){return Object.entries(document.pools).flatMap(([poolId,pool])=>pool===void 0?[]:pool.slots.map(slot=>`${poolId}/${slot.id} ${slot.kind} ${slot.label??slot.id}`))}async function showAccounts(store,context){let lines=accountLines(await store.read());context.ui.notify(lines.length===0?"No accounts configured":lines.join(`
1326
- `),"info")}async function loginAccount(providerName,requestedSlotId,store,login2,now,context){if(providerName===void 0||!isPoolId(providerName))throw new Error("Usage: /accounts login <provider> [slot]");let slotId=requestedSlotId??await store.nextSlotId(providerName),existing=await store.getSlot(providerName,slotId),warningAcceptedAt=existing?.warningAcceptedAt,notice=warningAcceptedAt===void 0?providerNotice(providerName):void 0;if(notice!==void 0){if(notice.kind==="confirm"&&!await context.ui.confirm(notice.title,notice.message)){context.ui.notify(`${providerName} login cancelled`,"info");return}notice.kind==="note"&&context.ui.notify(notice.message,"info"),warningAcceptedAt=now().toISOString()}if(isLocalPool(providerName)){let fallbackUrl=DEFAULT_LOCAL_BASE_URLS[providerName],answer=await context.ui.input(`Base URL for ${providerName}`,fallbackUrl??"http://127.0.0.1:8000/v1"),baseUrl=(answer??"").trim().length>0?answer.trim():fallbackUrl;if(baseUrl===void 0||baseUrl.length===0)throw new Error(`${providerName} needs a base URL`);await store.putLocalSlot(providerName,{id:slotId,kind:"local",label:existing?.label??slotId,warningAcceptedAt,baseUrl}),context.ui.notify(`Added local account ${providerName}/${slotId} on ${baseUrl}`,"info");return}let credential=await login2(providerName,slotId,context);await store.putSlot(providerName,{id:slotId,kind:credential.type,label:existing?.label??slotId,warningAcceptedAt},credential),context.ui.notify(`Added account ${providerName}/${slotId}`,"info")}function isResearchService(value){return value==="exa"||value==="perplexity"}async function loginResearchService(service,context){let trimmed=(await context.ui.input(`${service} API key for research`,"Paste the key, or Enter to cancel")??"").trim();if(trimmed.length===0){context.ui.notify(`Cancelled ${service} research login`,"info");return}await saveResearchKeys(service==="exa"?{exa:trimmed}:{perplexity:trimmed}),await writeResearchMode(context.cwd,"auto"),context.ui.notify(`Saved ${service} research credential`,"info")}function resolveSlotReference(reference,document){if(reference===void 0)throw new Error("Usage: /accounts logout <pool/slot>");let slash=reference.indexOf("/");if(slash>=0){let poolName=reference.slice(0,slash),slotId=reference.slice(slash+1);if(!isPoolId(poolName)||slotId.length===0)throw new Error(`Unknown account slot: ${reference}`);return{poolId:poolName,slotId}}let matches=Object.entries(document.pools).flatMap(([poolId,pool])=>pool?.slots.some(slot=>slot.id===reference)?[{poolId,slotId:reference}]:[]);if(matches.length!==1)throw new Error(matches.length===0?`Unknown account slot: ${reference}`:`Ambiguous account slot ${reference}; use pool/slot`);return matches[0]}async function logoutAccount(reference,store,context,onRemoved){let slot=resolveSlotReference(reference,await store.read());if(!await store.removeSlot(slot.poolId,slot.slotId))throw new Error(`Unknown account slot: ${slot.poolId}/${slot.slotId}`);onRemoved(slot.poolId,slot.slotId),context.ui.notify(`Removed account ${slot.poolId}/${slot.slotId}`,"info")}async function handleAccountsCommand(args,context,dependencies,onSlotRemoved,routing){let words2=args.trim().length===0?[]:args.trim().split(/\s+/u),[action,first,second,...extra]=words2;if(action===void 0||action==="list")return await showAccounts(dependencies.store,context),!1;if(extra.length>0)throw new Error("Too many /accounts arguments");if(action==="login"){if(isResearchService(first)){if(second!==void 0)throw new Error(`Usage: /accounts login ${first}`);return await loginResearchService(first,context),!1}return await loginAccount(first,second,dependencies.store,dependencies.login,dependencies.now,context),!0}if(action==="logout"){if(isResearchService(first)){if(second!==void 0)throw new Error(`Usage: /accounts logout ${first}`);let removed=await removeResearchKey(first);return context.ui.notify(removed?`Removed ${first} research credential`:`No ${first} research credential to remove`,"info"),!1}if(second!==void 0)throw new Error("Usage: /accounts logout <pool/slot>");return await logoutAccount(first,dependencies.store,context,onSlotRemoved),!0}if(action==="next"){if(first!==void 0)throw new Error("Usage: /accounts next");let current=routing.activePool();if(current===void 0)throw new Error("No active route to advance; run a turn first");return await routing.advance(current),context.ui.notify(`Advanced past the pinned ${current} slot`,"info"),!0}if(action==="pin"){if(second!==void 0)throw new Error("Usage: /accounts pin <pool/slot>");let reference=resolveSlotReference(first,await dependencies.store.read());if(await dependencies.store.getSlot(reference.poolId,reference.slotId)===void 0)throw new Error(`Unknown account slot: ${reference.poolId}/${reference.slotId}`);return await routing.pin(reference.poolId,reference.slotId),context.ui.notify(`Pinned ${reference.poolId}/${reference.slotId} for this session`,"info"),!0}throw new Error(`Unknown /accounts command: ${action}`)}async function handlePoolCommand(args,context,store){let words2=args.trim().length===0?[]:args.trim().split(/\s+/u),[action,first,second,...extra]=words2;if(extra.length>0)throw new Error("Too many /pool arguments");if(action==="strategy"){if(first===void 0||second===void 0)throw new Error("Usage: /pool strategy <provider> <quota-first|round-robin|sticky>");if(!isPoolId(first))throw new Error(`Unknown pool id: ${first}`);return await store.setStrategy(first,second),context.ui.notify(`${first} strategy is ${second}`,"info"),!0}if(action==="chain"){if(first===void 0||second!==void 0)throw new Error("Usage: /pool chain a,b,c");let chain=first.split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0);return await store.setChain(chain),context.ui.notify(`Fallback chain is ${chain.join(", ")}`,"info"),!0}throw new Error("Usage: /pool strategy <provider> <name> | /pool chain a,b,c")}function registerAccounts(pi,dependencies={}){let resolved={store:dependencies.store??new AccountsStore,now:dependencies.now??(()=>new Date),login:dependencies.login??((providerId,slotId,context)=>loginWithOfficialProvider(providerId,slotId,context,url=>openAuthUrl(pi,url))),usageReaders:dependencies.usageReaders??{}},nowMs=()=>resolved.now().getTime(),balancer=new AccountBalancer(nowMs),usage=new UsageCache({now:nowMs,readers:resolved.usageReaders}),active,activeModel,requestSlots=new Map,REQUEST_SLOT_LIMIT=64,recordRequestSlot=(requestId,selection)=>{for(requestSlots.delete(requestId),requestSlots.set(requestId,selection);requestSlots.size>REQUEST_SLOT_LIMIT;){let oldest=requestSlots.keys().next();if(oldest.done===!0)break;requestSlots.delete(oldest.value)}},configuredSlots=accounts=>Object.entries(accounts.pools).flatMap(([poolId,pool])=>(pool?.slots??[]).map(slot=>({poolId,slotId:slot.id}))),publishWidget=async(context,accounts)=>{let doc=accounts??await resolved.store.read(),route=active===void 0||activeModel===void 0?void 0:{provider:active.poolId,model:activeModel,slot:active.slot.id},widget=renderAccountsWidget(doc,{usage,health:balancer,route,now:nowMs()});if(context.ui.setStatus("accounts",widget==="ACCOUNTS"?void 0:widget),active!==void 0){let snapshot2=usage.get(active.poolId,active.slot.id);setFooterRouteSnapshot({slotKind:active.slot.kind,...route===void 0?{}:{route:`${route.provider}/${route.model}`},...active.slot.kind==="local"||snapshot2?.remainingPercent===void 0?{}:{remainingPercent:snapshot2.remainingPercent}})}},reroute=async poolId=>{if(active?.poolId!==poolId)return;let next=balancer.selectInFamily(poolId,await resolved.store.read(),usage);active=next===void 0?void 0:{poolId:next.poolId,slot:next.slot},next===void 0&&(activeModel=void 0)};typeof pi.on=="function"&&(pi.on("before_provider_headers",async(event,context)=>{let modelProvider=context.model?.provider,provider2=modelProvider===void 0?void 0:poolIdForProvider(modelProvider);if(provider2===void 0)return;let accounts=await resolved.store.read();if(active=balancer.selectInFamily(provider2,accounts,usage),isLocalPool(provider2)){let origin=context.model?.baseUrl,pinned=(accounts.pools[provider2]?.slots??[]).find(slot=>slot.kind==="local"&&slot.baseUrl===origin);pinned!==void 0?active={poolId:provider2,slot:pinned}:origin!==void 0&&(active=void 0)}if(activeModel=context.model?.id,await publishWidget(context,accounts),active===void 0||active.poolId!==provider2)return;let secretName=active.slot.kind==="local"?active.slot.secretRef:`${active.poolId}/${active.slot.id}`,credential=secretName===void 0?void 0:(await resolved.store.readSecrets())[secretName],token=credential?.type==="oauth"?credential.access:credential?.type==="api_key"?credential.key:void 0;token!==void 0?(setAuthHeader(event.headers,context.model?.api,credential?.type,token),recordRequestSlot(event.requestId,active)):active.slot.kind==="local"&&(event.headers.authorization=null,recordRequestSlot(event.requestId,active))}),pi.on("after_provider_response",async(event,context)=>{let served=requestSlots.get(event.requestId);if(served===void 0)return;usage.recordHeaders(served.poolId,served.slot.id,event.headers??{});let classification=classifyProviderFailure({status:event.status,headers:event.headers},nowMs());if(classification===void 0){await publishWidget(context);return}balancer.markCooling(served.poolId,served.slot.id,classification.until);let accounts=await resolved.store.read(),plan=balancer.planFailover(served,accounts,context.modelRegistry.getAvailable(),context.model,usage);if(plan===void 0){await publishWidget(context,accounts);return}let moved=!1,stillCurrent=active?.poolId===served.poolId&&active.slot.id===served.slot.id;if(plan.sameFamily?(stillCurrent&&(active={poolId:plan.to.poolId,slot:plan.to.slot}),moved=!0):plan.model!==void 0&&await pi.setModel(plan.model)&&(stillCurrent&&(active={poolId:plan.to.poolId,slot:plan.to.slot},activeModel=plan.model.id),moved=!0),moved){let job=await readActiveJob(context.cwd);job!==void 0&&await appendEvent(job.eventsPath,{ts:resolved.now().toISOString(),type:"accounts.failover",job_id:job.jobId,round:typeof job.state.round=="number"?job.state.round:0,node:typeof job.state.node=="string"?job.state.node:"accounts",from:`${plan.from.poolId}/${plan.from.slot.id}`,to:`${plan.to.poolId}/${plan.to.slot.id}`})}await publishWidget(context,accounts)}),pi.on("session_start",async(_event,context)=>{let imported=await resolved.store.importOfficialCredentials();imported.length>0&&context.ui.notify(`Imported official credentials as ${imported.join(", ")}`,"info"),await usage.refreshAll(configuredSlots(await resolved.store.read()),context.signal),await publishWidget(context)})),pi.registerCommand("pool",{description:"Set a K-\u03C0 pool strategy or the fallback chain",handler:async(args,context)=>{try{await handlePoolCommand(args,context,resolved.store)&&await publishWidget(context)}catch(error){let message=error instanceof Error?error.message:String(error);context.ui.notify(`K-\u03C0 pool: ${message}`,"error")}}}),pi.registerCommand("accounts",{description:"Manage K-\u03C0 subscription accounts",handler:async(args,context)=>{try{await handleAccountsCommand(args,context,resolved,(poolId,slotId)=>{balancer.releaseSlot(poolId,slotId),usage.forget(poolId,slotId),active?.poolId===poolId&&active.slot.id===slotId&&(active=void 0,activeModel=void 0)},{activePool:()=>active?.poolId,advance:async poolId=>{balancer.advance(poolId),await reroute(poolId)},pin:async(poolId,slotId)=>{balancer.pinSlot(poolId,slotId),await reroute(poolId)}})&&await publishWidget(context)}catch(error){let message=error instanceof Error?error.message:String(error);context.ui.notify(`K-\u03C0 accounts: ${message}`,"error")}}})}import{readFileSync as readFileSync16,statSync as statSync11}from"node:fs";import{join as join42}from"node:path";var APPEND_SYSTEM_FILE="APPEND_SYSTEM.md";function shippedAppendSystemPath(){return join42(getKpiResourceDir(),"templates",APPEND_SYSTEM_FILE)}function installedAppendSystemPath(agentDirectory=getAgentDir()){return join42(agentDirectory,APPEND_SYSTEM_FILE)}function readIfPresent(path14){try{return readFileSync16(path14,"utf8")}catch(error){if(error.code==="ENOENT")return;throw error}}function ensureAppendSystemInstalled(agentDirectory=getAgentDir()){let target=installedAppendSystemPath(agentDirectory),shipped=readIfPresent(shippedAppendSystemPath());if(shipped===void 0)return{outcome:"unavailable",path:target};let existing=readIfPresent(target);return existing!==void 0?{outcome:existing===shipped?"current":"operator-owned",path:target}:(atomicWriteSync(target,shipped),{outcome:"installed",path:target})}async function installAppendSystemCommand(ctx,agentDirectory=getAgentDir()){let status=ensureAppendSystemInstalled(agentDirectory);if(status.outcome==="unavailable")return ctx.ui.notify(`No shipped ${APPEND_SYSTEM_FILE} found at ${shippedAppendSystemPath()}`,"warning"),status;if(status.outcome==="installed")return ctx.ui.notify(`Installed K-\u03C0 ${APPEND_SYSTEM_FILE} at ${status.path}`,"info"),status;if(status.outcome==="current")return ctx.ui.notify(`${status.path} already matches the shipped ${APPEND_SYSTEM_FILE}`,"info"),status;if(!await ctx.ui.confirm(`Replace ${APPEND_SYSTEM_FILE}?`,`${status.path} differs from the shipped prompt. Replace your version with K-\u03C0's?`))return ctx.ui.notify(`Kept your ${status.path}`,"info"),{outcome:"kept",path:status.path};let shipped=readIfPresent(shippedAppendSystemPath());return shipped===void 0?{outcome:"unavailable",path:status.path}:(atomicWriteSync(status.path,shipped),ctx.ui.notify(`Replaced ${status.path} with the shipped ${APPEND_SYSTEM_FILE}`,"info"),{outcome:"replaced",path:status.path})}function registerAppendSystem(pi){ensureAppendSystemInstalled(),pi.registerCommand("append-system",{description:"Install K-\u03C0's concise-output system prompt, or report the file already in place",handler:async(_args,ctx)=>{await installAppendSystemCommand(ctx)}})}import{lstat,mkdir as mkdir5,readdir as readdir4,readFile as readFile13,readlink,realpath as realpath2,stat as stat4,writeFile}from"node:fs/promises";import{dirname as dirname25,isAbsolute as isAbsolute4,join as join43,parse as parse4,relative as relative5,resolve as resolve13,sep as sep9}from"node:path";var LAYER_FOLDERS=new Set(["components","hooks","lib","libs","services","controllers","models","views","api","apis","ui","frontend","backend","routes","handlers","middleware","pages"]),GENERIC_FOLDERS=new Set(["utils","helpers","common","misc","core","shared-utils"]),GENERIC_FOLDER_FILE_BUDGET=5,NO_STACK_PLAYBOOKS=new Set(["typo","unslop","comment-strip"]),LAYER_SWEEP_PATTERN=/\ball\s+(?:the\s+)?(?:apis?|endpoints?|controllers?|routes?|screens?|uis?|views?|pages?|components?)\b/iu,DuneStackError=class extends Error{constructor(message){super(message),this.name="DuneStackError"}};function normalizeProjectPath(projectRoot,value){if(value.length===0)return;let absolute=isAbsolute4(value)?resolve13(value):resolve13(projectRoot,value),relativePath=relative5(resolve13(projectRoot),absolute);if(!(relativePath.length===0||relativePath===".."||relativePath.startsWith(`..${sep9}`)||isAbsolute4(relativePath)))return relativePath.split(sep9).join("/")}function patternSegments(pattern){return pattern.replaceAll("\\","/").split("/").filter(segment2=>segment2.length>0&&segment2!==".")}function segmentMatcher(segment2){let source2=segment2.replaceAll(/[.+^${}()|[\]\\]/gu,"\\$&").replaceAll("*","[^/]*").replaceAll("?","[^/]");return new RegExp(`^${source2}$`,"u")}function matchesPathPattern(pattern,candidate){let patternParts=patternSegments(pattern),candidateParts=patternSegments(candidate),walk=(patternIndex,candidateIndex)=>{if(patternIndex===patternParts.length)return candidateIndex===candidateParts.length;let part=patternParts[patternIndex];if(part==="**"){for(let skip=candidateIndex;skip<=candidateParts.length;skip+=1)if(walk(patternIndex+1,skip))return!0;return!1}return candidateIndex===candidateParts.length?!1:segmentMatcher(part).test(candidateParts[candidateIndex])&&walk(patternIndex+1,candidateIndex+1)};return walk(0,0)?!0:!patternParts.some(part=>part.includes("*")||part.includes("?"))&&candidateParts.length>patternParts.length?patternParts.every((part,index3)=>part===candidateParts[index3]):!1}function assertDeclaredPath(value,label,options){if(typeof value!="string"||value.length===0||value!==value.trim())throw new DuneStackError(`${label} must be a trimmed, non-empty path`);if(/^[/\\]/u.test(value)||/^[A-Za-z]:[/\\]/u.test(value))throw new DuneStackError(`${label} must be repository-relative, not absolute: ${value}`);let parts=value.replaceAll("\\","/").split("/");for(let part of parts){if(part.length===0)throw new DuneStackError(`${label} must not contain an empty path segment: ${value}`);if(part==="."||part==="..")throw new DuneStackError(`${label} must not contain a ${part} segment: ${value}`)}if(!options.allowGlob&&/[*?[\]]/u.test(value))throw new DuneStackError(`${label} must name an exact path, not a pattern: ${value}`);return parts}function testTwinFor(module){return`test/${module.id}`}function moduleOwnsPath(projectRoot,module,path14){let normalized=normalizeProjectPath(projectRoot,path14);return normalized===void 0?!1:[...module.allowed_paths,module.folder,module.interface,testTwinFor(module)].some(pattern=>matchesPathPattern(pattern,normalized))}function assertStringField(value,label){if(typeof value!="string"||value.trim().length===0)throw new DuneStackError(`${label} must be a non-empty string`)}function assertModuleShape(value,index3){if(!isJsonObject(value))throw new DuneStackError(`modules[${index3}] must be an object`);if(assertStringField(value.id,`modules[${index3}].id`),assertDeclaredPath(value.id,`modules[${index3}].id`,{allowGlob:!1}).length!==1)throw new DuneStackError(`modules[${index3}].id must be a single path segment: ${String(value.id)}`);if(assertStringField(value.purpose,`modules[${index3}].purpose`),assertDeclaredPath(value.folder,`modules[${index3}].folder`,{allowGlob:!1}),assertDeclaredPath(value.interface,`modules[${index3}].interface`,{allowGlob:!1}),!Array.isArray(value.allowed_paths)||value.allowed_paths.some(entry=>typeof entry!="string"))throw new DuneStackError(`modules[${index3}].allowed_paths must be an array of strings`);if(value.allowed_paths.length===0)throw new DuneStackError(`modules[${index3}].allowed_paths must not be empty`);for(let[entryIndex,entry]of value.allowed_paths.entries())assertDeclaredPath(entry,`modules[${index3}].allowed_paths[${entryIndex}]`,{allowGlob:!0});if(!Array.isArray(value.depends_on)||value.depends_on.some(entry=>typeof entry!="string"))throw new DuneStackError(`modules[${index3}].depends_on must be an array of strings`)}function assertDuneStack(value){if(!isJsonObject(value))throw new DuneStackError("stack must be an object");if(value.version!==1||value.shape!=="dune"||value.scaffold_first!==!0)throw new DuneStackError("Invalid Dune stack header");if(value.delivery!=="vertical"&&value.delivery!=="horizontal")throw new DuneStackError("delivery must be vertical or horizontal");if(value.delivery==="horizontal"&&(typeof value.delivery_reason!="string"||value.delivery_reason.trim().length===0))throw new DuneStackError("Horizontal delivery requires a reason");if(assertStringField(value.root,"root"),assertDeclaredPath(value.root,"root",{allowGlob:!1}),!Array.isArray(value.modules)||value.modules.length===0)throw new DuneStackError("stack must declare at least one module");let ids=new Set,modules=[];for(let[index3,entry]of value.modules.entries()){if(assertModuleShape(entry,index3),ids.has(entry.id))throw new DuneStackError(`duplicate module id: ${entry.id}`);ids.add(entry.id),modules.push(entry)}let root=patternSegments(value.root);for(let module of modules){let folder=patternSegments(module.folder);if(folder.length===0)throw new DuneStackError(`Module ${module.id} has no folder`);if(folder.at(-1)!==module.id)throw new DuneStackError(`Module folder must match id: ${module.id}`);if(folder.length<=root.length||!root.every((part,index3)=>part===folder[index3]))throw new DuneStackError(`Module ${module.id} folder must live under root ${value.root}: ${module.folder}`);let isTopLevel=folder.length===root.length+1;if(LAYER_FOLDERS.has(module.id)&&isTopLevel)throw new DuneStackError(`Layer folder ${module.id} cannot be a top-level module`);if(GENERIC_FOLDERS.has(module.id)&&module.purpose.trim().split(/\s+/u).length<3)throw new DuneStackError(`Generic module needs a tight purpose: ${module.id}`);if(module.id==="auth"&&folder.slice(0,-1).some(part=>LAYER_FOLDERS.has(part)))throw new DuneStackError("Auth must live in its auth folder");if(!matchesPathPattern(module.folder,module.interface))throw new DuneStackError(`Interface must live inside ${module.folder}`);let folderProbe=`${folder.join("/")}/index.ts`;if(!module.allowed_paths.some(pattern=>matchesPathPattern(pattern,folderProbe)))throw new DuneStackError(`Module ${module.id} does not allow its own folder`);let twinProbe=`${testTwinFor(module)}/index.test.ts`;if(!module.allowed_paths.some(pattern=>matchesPathPattern(pattern,twinProbe)))throw new DuneStackError(`Module ${module.id} lacks its test twin`);for(let dependency of module.depends_on)if(!ids.has(dependency))throw new DuneStackError(`Module ${module.id} depends on unknown module ${dependency}`)}for(let module of modules){if(module.id!=="shared")continue;let consumers=modules.filter(candidate=>candidate.depends_on.includes(module.id));if(consumers.length<2)throw new DuneStackError(`shared needs two consuming slices before extraction; ${consumers.length} declared`)}if(value.delivery==="vertical"){for(let module of modules)if(LAYER_SWEEP_PATTERN.test(module.purpose)||LAYER_SWEEP_PATTERN.test(module.id))throw new DuneStackError(`Vertical delivery cannot stage a layer sweep: ${module.id} (${module.purpose})`);let layerModules=modules.filter(module=>LAYER_FOLDERS.has(module.id));if(layerModules.length>=2)throw new DuneStackError(`Vertical delivery cannot be a layer staging plan: ${layerModules.map(module=>module.id).join(", ")}`)}}function stackRequiredFor(task){let playbook=task.playbook?.trim().toLowerCase();return playbook===void 0||!NO_STACK_PLAYBOOKS.has(playbook)}function stackTaskHash(task){return contractHash(task)}function resolveCurrentModule(stack,task){let requested=task.current_module_id?.trim();if(requested===void 0||requested.length===0)throw new DuneStackError("task.json must name current_module_id; modules[0] is never the current slice");let matches=stack.modules.filter(module=>module.id===requested);if(matches.length!==1)throw new DuneStackError(`current_module_id ${requested} does not name exactly one module`);return matches[0]}async function countFiles(directory){let entries;try{entries=await readdir4(directory,{withFileTypes:!0})}catch(error){if(error.code==="ENOENT")return 0;throw error}let total=0;for(let entry of entries)total+=entry.isDirectory()?await countFiles(join43(directory,entry.name)):1;return total}async function assertGenericFolderBudget(projectRoot,stack){for(let module of stack.modules){if(!GENERIC_FOLDERS.has(module.id))continue;let files=await countFiles(join43(projectRoot,module.folder));if(files>=GENERIC_FOLDER_FILE_BUDGET)throw new DuneStackError(`Generic folder ${module.folder} holds ${files} files; the budget is ${GENERIC_FOLDER_FILE_BUDGET}`)}}async function readDuneStack(runDirectory){let raw;try{raw=await readFile13(join43(runDirectory,"stack.json"),"utf8")}catch(error){throw error.code==="ENOENT"?new DuneStackError("stack.json is missing; implement has no frozen map to read"):error}let parsed;try{parsed=JSON.parse(raw)}catch{throw new DuneStackError("stack.json is not valid JSON")}return assertDuneStack(parsed),parsed}async function assertStackFresh(runDirectory,task,stack){if(stack.task_hash!==void 0){if(stack.task_hash!==stackTaskHash(task))throw new DuneStackError("stack.json was frozen against a different task.json");return}let stackStat=await stat4(join43(runDirectory,"stack.json")),taskStat;try{taskStat=await stat4(join43(runDirectory,"task.json"))}catch(error){throw error.code==="ENOENT"?new DuneStackError("task.json is missing, so stack.json freshness cannot be established"):error}if(stackStat.mtimeMs<taskStat.mtimeMs)throw new DuneStackError("stack.json is older than task.json")}async function freezeCurrentSlice(projectRoot,runDirectory,task){let stack=await readDuneStack(runDirectory);if(await assertStackFresh(runDirectory,task,stack),await assertGenericFolderBudget(projectRoot,stack),task.current_module_id!==void 0&&stack.current_module_id!==void 0&&task.current_module_id.trim()!==stack.current_module_id.trim())throw new DuneStackError(`stack.json names slice ${stack.current_module_id} while task.json names ${task.current_module_id}`);if(task.current_module_id===void 0&&stack.current_module_id!==void 0){let frozen={...task,current_module_id:stack.current_module_id};resolveCurrentModule(stack,frozen),await atomicWrite(join43(runDirectory,"task.json"),`${JSON.stringify(frozen,null,2)}
1325
+ `)}async function answerAuthPrompt(prompt,context){if(prompt.type==="select"){let labels=prompt.options.map(option2=>option2.label),selected=await context.ui.select(prompt.message,labels,{signal:prompt.signal}),option=prompt.options.find(candidate=>candidate.label===selected);if(option===void 0)throw new LoginCancelledError;return option.id}let answer=await context.ui.input(prompt.message,prompt.placeholder,{signal:prompt.signal});if(answer===void 0)throw new LoginCancelledError;return answer}function openAuthUrl(pi,url){let command=process.platform==="darwin"?{name:"open",args:[url]}:process.platform==="win32"?{name:"cmd",args:["/c","start","",url]}:{name:"xdg-open",args:[url]};pi.exec(command.name,command.args).catch(()=>{})}async function loginWithOfficialProvider(providerId,_slotId,context,showAuthUrl){let auth=context.modelRegistry.getProvider(providerId)?.auth;if(auth?.oauth!==void 0){let interaction={signal:context.signal??new AbortController().signal,prompt:prompt=>answerAuthPrompt(prompt,context),notify:event=>{event.type==="auth_url"&&showAuthUrl(event.url),context.ui.notify(authEventMessage(event),"info")}};return context.modelRegistry.login(providerId,"oauth",interaction)}if(auth?.apiKey!==void 0){let key=(await context.ui.input(auth.apiKey.name,"Paste the key, or Enter to cancel",{signal:context.signal})??"").trim();if(key.length===0)throw new LoginCancelledError;return{type:"api_key",key}}throw new Error(`Provider ${providerId} offers neither subscription OAuth nor an API key`)}function accountLines(document){return Object.entries(document.pools).flatMap(([poolId,pool])=>pool===void 0?[]:pool.slots.map(slot=>`${poolId}/${slot.id} ${slot.kind} ${slot.label??slot.id}`))}async function showAccounts(store,context){let lines=accountLines(await store.read());context.ui.notify(lines.length===0?"No accounts configured":lines.join(`
1326
+ `),"info")}async function loginAccount(providerName,requestedSlotId,store,login2,now,context){if(providerName===void 0||!isPoolId(providerName))throw new Error("Usage: /accounts login <provider> [slot]");let slotId=requestedSlotId??await store.nextSlotId(providerName),existing=await store.getSlot(providerName,slotId),warningAcceptedAt=existing?.warningAcceptedAt,notice=warningAcceptedAt===void 0?providerNotice(providerName):void 0;if(notice!==void 0){if(notice.kind==="confirm"&&!await context.ui.confirm(notice.title,notice.message)){context.ui.notify(`${providerName} login cancelled`,"info");return}notice.kind==="note"&&context.ui.notify(notice.message,"info"),warningAcceptedAt=now().toISOString()}if(isLocalPool(providerName)){let fallbackUrl=DEFAULT_LOCAL_BASE_URLS[providerName],answer=await context.ui.input(`Base URL for ${providerName}`,fallbackUrl??"http://127.0.0.1:8000/v1"),baseUrl=(answer??"").trim().length>0?answer.trim():fallbackUrl;if(baseUrl===void 0||baseUrl.length===0)throw new Error(`${providerName} needs a base URL`);return await store.putLocalSlot(providerName,{id:slotId,kind:"local",label:existing?.label??slotId,warningAcceptedAt,baseUrl}),context.ui.notify(`Added local account ${providerName}/${slotId} on ${baseUrl}`,"info"),{poolId:providerName,slotId}}let credential=await login2(providerName,slotId,context);return await store.putSlot(providerName,{id:slotId,kind:credential.type,label:existing?.label??slotId,warningAcceptedAt},credential),context.ui.notify(`Added account ${providerName}/${slotId}`,"info"),{poolId:providerName,slotId}}function isResearchService(value){return value==="exa"||value==="perplexity"}async function loginResearchService(service,context){let trimmed=(await context.ui.input(`${service} API key for research`,"Paste the key, or Enter to cancel")??"").trim();if(trimmed.length===0){context.ui.notify(`Cancelled ${service} research login`,"info");return}await saveResearchKeys(service==="exa"?{exa:trimmed}:{perplexity:trimmed}),await writeResearchMode(context.cwd,"auto"),context.ui.notify(`Saved ${service} research credential`,"info")}function resolveSlotReference(reference,document){if(reference===void 0)throw new Error("Usage: /accounts logout <pool/slot>");let slash=reference.indexOf("/");if(slash>=0){let poolName=reference.slice(0,slash),slotId=reference.slice(slash+1);if(!isPoolId(poolName)||slotId.length===0)throw new Error(`Unknown account slot: ${reference}`);return{poolId:poolName,slotId}}let matches=Object.entries(document.pools).flatMap(([poolId,pool])=>pool?.slots.some(slot=>slot.id===reference)?[{poolId,slotId:reference}]:[]);if(matches.length!==1)throw new Error(matches.length===0?`Unknown account slot: ${reference}`:`Ambiguous account slot ${reference}; use pool/slot`);return matches[0]}async function logoutAccount(reference,store,context,onRemoved){let slot=resolveSlotReference(reference,await store.read());if(!await store.removeSlot(slot.poolId,slot.slotId))throw new Error(`Unknown account slot: ${slot.poolId}/${slot.slotId}`);onRemoved(slot.poolId,slot.slotId),context.ui.notify(`Removed account ${slot.poolId}/${slot.slotId}`,"info")}async function handleAccountsCommand(args,context,dependencies,onSlotRemoved,routing){let words2=args.trim().length===0?[]:args.trim().split(/\s+/u),[action,first,second,...extra]=words2;if(action===void 0||action==="list")return await showAccounts(dependencies.store,context),!1;if(extra.length>0)throw new Error("Too many /accounts arguments");if(action==="login"||action==="login-active"){if(isResearchService(first)){if(action==="login-active"||second!==void 0)throw new Error(`Usage: /accounts login ${first}`);return await loginResearchService(first,context),!1}let loggedIn=await loginAccount(first,second,dependencies.store,dependencies.login,dependencies.now,context);return loggedIn===void 0?!1:(action==="login-active"&&await routing.pin(loggedIn.poolId,loggedIn.slotId),!0)}if(action==="logout"){if(isResearchService(first)){if(second!==void 0)throw new Error(`Usage: /accounts logout ${first}`);let removed=await removeResearchKey(first);return context.ui.notify(removed?`Removed ${first} research credential`:`No ${first} research credential to remove`,"info"),!1}if(second!==void 0)throw new Error("Usage: /accounts logout <pool/slot>");return await logoutAccount(first,dependencies.store,context,onSlotRemoved),!0}if(action==="next"){if(first!==void 0)throw new Error("Usage: /accounts next");let current=routing.activePool();if(current===void 0)throw new Error("No active route to advance; run a turn first");return await routing.advance(current),context.ui.notify(`Advanced past the pinned ${current} slot`,"info"),!0}if(action==="pin"){if(second!==void 0)throw new Error("Usage: /accounts pin <pool/slot>");let reference=resolveSlotReference(first,await dependencies.store.read());if(await dependencies.store.getSlot(reference.poolId,reference.slotId)===void 0)throw new Error(`Unknown account slot: ${reference.poolId}/${reference.slotId}`);return await routing.pin(reference.poolId,reference.slotId),context.ui.notify(`Pinned ${reference.poolId}/${reference.slotId} for this session`,"info"),!0}throw new Error(`Unknown /accounts command: ${action}`)}async function handlePoolCommand(args,context,store){let words2=args.trim().length===0?[]:args.trim().split(/\s+/u),[action,first,second,...extra]=words2;if(extra.length>0)throw new Error("Too many /pool arguments");if(action==="strategy"){if(first===void 0||second===void 0)throw new Error("Usage: /pool strategy <provider> <quota-first|round-robin|sticky>");if(!isPoolId(first))throw new Error(`Unknown pool id: ${first}`);return await store.setStrategy(first,second),context.ui.notify(`${first} strategy is ${second}`,"info"),!0}if(action==="chain"){if(first===void 0||second!==void 0)throw new Error("Usage: /pool chain a,b,c");let chain=first.split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0);return await store.setChain(chain),context.ui.notify(`Fallback chain is ${chain.join(", ")}`,"info"),!0}throw new Error("Usage: /pool strategy <provider> <name> | /pool chain a,b,c")}function registerAccounts(pi,dependencies={}){let resolved={store:dependencies.store??new AccountsStore,now:dependencies.now??(()=>new Date),login:dependencies.login??((providerId,slotId,context)=>loginWithOfficialProvider(providerId,slotId,context,url=>openAuthUrl(pi,url))),usageReaders:dependencies.usageReaders??{},fallbackModels:dependencies.fallbackModels??resolveFallbackModels},nowMs=()=>resolved.now().getTime(),balancer=new AccountBalancer(nowMs),usage=new UsageCache({now:nowMs,readers:resolved.usageReaders}),active,activeModel,requestSlots=new Map,REQUEST_SLOT_LIMIT=64,recordRequestSlot=(requestId,selection)=>{for(requestSlots.delete(requestId),requestSlots.set(requestId,selection);requestSlots.size>REQUEST_SLOT_LIMIT;){let oldest=requestSlots.keys().next();if(oldest.done===!0)break;requestSlots.delete(oldest.value)}},configuredSlots=accounts=>Object.entries(accounts.pools).flatMap(([poolId,pool])=>(pool?.slots??[]).map(slot=>({poolId,slotId:slot.id}))),refreshExpiringCredentials=async context=>{if(context.modelRegistry===void 0)return;let[accounts,secrets]=await Promise.all([resolved.store.read(),resolved.store.readSecrets()]);for(let[poolName,pool]of Object.entries(accounts.pools)){if(pool===void 0||!isPoolId(poolName))continue;let oauth=context.modelRegistry.getProvider(poolName)?.auth?.oauth;if(oauth!==void 0)for(let slot of pool.slots){let credential=secrets[`${poolName}/${slot.id}`];if(!(credential?.type!=="oauth"||credential.expires===void 0||credential.expires>nowMs()+300*1e3))try{let refreshed=await oauth.refresh(credential,context.signal??new AbortController().signal);await resolved.store.putSlot(poolName,slot,refreshed)}catch(error){balancer.markCooling(poolName,slot.id,nowMs()+18e6);let reason=error instanceof Error?error.message:String(error);context.ui.notify(`Could not refresh ${poolName}/${slot.id}: ${reason}`,"warning")}}}},publishWidget=async(context,accounts)=>{let doc=accounts??await resolved.store.read(),route=active===void 0||activeModel===void 0?void 0:{provider:active.poolId,model:activeModel,slot:active.slot.id},widget=renderAccountsWidget(doc,{usage,health:balancer,route,now:nowMs()});if(context.ui.setStatus("accounts",widget==="ACCOUNTS"?void 0:widget),active!==void 0){let snapshot2=usage.get(active.poolId,active.slot.id);setFooterRouteSnapshot({slotKind:active.slot.kind,...route===void 0?{}:{route:`${route.provider}/${route.model}`},...active.slot.kind==="local"||snapshot2?.remainingPercent===void 0?{}:{remainingPercent:snapshot2.remainingPercent}})}},reroute=async poolId=>{if(active?.poolId!==poolId)return;let next=balancer.selectInFamily(poolId,await resolved.store.read(),usage);active=next===void 0?void 0:{poolId:next.poolId,slot:next.slot},next===void 0&&(activeModel=void 0)},applyFailure=async(served,until,context)=>{balancer.markCooling(served.poolId,served.slot.id,until);let accounts=await resolved.store.read(),preferredModels=await resolved.fallbackModels().catch(()=>{}),plan=balancer.planFailover(served,accounts,context.modelRegistry.getAvailable(),context.model,usage,preferredModels);if(plan===void 0)return await publishWidget(context,accounts),!1;let stillCurrent=active?.poolId===served.poolId&&active.slot.id===served.slot.id,moved=!1;if(plan.sameFamily&&stillCurrent?(active={poolId:plan.to.poolId,slot:plan.to.slot},moved=!0):!plan.sameFamily&&stillCurrent&&plan.model!==void 0&&await pi.setModel(plan.model)&&(active={poolId:plan.to.poolId,slot:plan.to.slot},activeModel=plan.model.id,moved=!0),moved){let job=await readActiveJob(context.cwd);job!==void 0&&await appendEvent(job.eventsPath,{ts:resolved.now().toISOString(),type:"accounts.failover",job_id:job.jobId,round:typeof job.state.round=="number"?job.state.round:0,node:typeof job.state.node=="string"?job.state.node:"accounts",from:`${plan.from.poolId}/${plan.from.slot.id}`,to:`${plan.to.poolId}/${plan.to.slot.id}`})}return await publishWidget(context,accounts),moved},MAX_PENDING_RESPONSES=8,pendingResponses=new Map,slotName=response=>`${response.served.poolId}/${response.served.slot.id}`,evictionReported=!1,rememberResponse=(requestId,response,context)=>{for(pendingResponses.delete(requestId),pendingResponses.set(requestId,response);pendingResponses.size>MAX_PENDING_RESPONSES;){let oldestEntry=pendingResponses.entries().next();if(oldestEntry.done===!0)break;let[oldestId,oldest]=oldestEntry.value;pendingResponses.delete(oldestId),evictionReported||(evictionReported=!0,context.ui.notify(`K-\u03C0 accounts: more than ${MAX_PENDING_RESPONSES} responses in flight; the one on ${slotName(oldest)} is no longer attributable, and further evictions this run are not reported`,"warning"))}},releaseSucceededResponse=context=>{if(pendingResponses.size===1){let[,only]=pendingResponses.entries().next().value??[];pendingResponses.clear(),only!==void 0&&only.status>=400&&context.ui.notify(`K-\u03C0 accounts: the ${only.status} response on ${slotName(only)} ended without an assistant error and was not cooled`,"info");return}let succeeded=[...pendingResponses].filter(([,response])=>response.status<400);succeeded.length===1&&pendingResponses.delete(succeeded[0][0])},takeErroredResponse=()=>{let failed=[...pendingResponses].filter(([,response])=>response.status>=400),candidates=failed.length>0?failed:[...pendingResponses];return candidates.length===1?(pendingResponses.delete(candidates[0][0]),{response:candidates[0][1]}):{ambiguous:candidates.map(([,response])=>slotName(response))}},reportedAmbiguities=new Set;typeof pi.on=="function"&&(pi.on("before_provider_headers",async(event,context)=>{let modelProvider=context.model?.provider,provider2=modelProvider===void 0?void 0:poolIdForProvider(modelProvider);if(provider2===void 0)return;let accounts=await resolved.store.read();if(active=balancer.selectInFamily(provider2,accounts,usage),isLocalPool(provider2)){let origin=context.model?.baseUrl,pinned=(accounts.pools[provider2]?.slots??[]).find(slot=>slot.kind==="local"&&slot.baseUrl===origin);pinned!==void 0?active={poolId:provider2,slot:pinned}:origin!==void 0&&(active=void 0)}if(activeModel=context.model?.id,await publishWidget(context,accounts),active===void 0||active.poolId!==provider2){if(accounts.pools[provider2]!==void 0)for(let name of["authorization","x-api-key","x-goog-api-key","api-key"])event.headers[name]!==void 0&&(event.headers[name]=null);return}let secretName=active.slot.kind==="local"?active.slot.secretRef:`${active.poolId}/${active.slot.id}`,credential=secretName===void 0?void 0:(await resolved.store.readSecrets())[secretName],token=credential?.type==="oauth"?credential.access:credential?.type==="api_key"?credential.key:void 0;token!==void 0?(setAuthHeader(event.headers,context.model?.api,credential?.type,token),recordRequestSlot(event.requestId,active)):active.slot.kind==="local"&&(event.headers.authorization=null,recordRequestSlot(event.requestId,active))}),pi.on("after_provider_response",async(event,context)=>{let served=requestSlots.get(event.requestId);if(served===void 0)return;let snapshot2=usage.recordHeaders(served.poolId,served.slot.id,event.headers??{}),classification=classifyProviderFailure({status:event.status,headers:event.headers},nowMs()),lowQuota=event.status>=200&&event.status<400&&snapshot2?.remainingPercent!==void 0&&snapshot2.remainingPercent<=LOW_QUOTA_REMAINING_PERCENT,pending={served,status:event.status,classificationHandled:classification!==void 0||lowQuota,retryOnMovedRoute:!1};if(rememberResponse(event.requestId,pending,context),classification!==void 0){pending.retryOnMovedRoute=await applyFailure(served,classification.until,context);return}if(lowQuota&&snapshot2!==void 0){await applyFailure(served,snapshot2.resetAt??nowMs()+18e6,context);return}await publishWidget(context)}),pi.on("message_end",async(event,context)=>{if(event.message.role!=="assistant")return;let message=event.message;if(message.stopReason!=="error"||message.errorMessage===void 0){releaseSucceededResponse(context);return}let taken=takeErroredResponse();if("ambiguous"in taken){if(taken.ambiguous.length===0)return;let key=taken.ambiguous.join(",");return reportedAmbiguities.has(key)||(reportedAmbiguities.add(key),context.ui.notify(`K-\u03C0 accounts: an assistant error could not be attributed between ${taken.ambiguous.join(" and ")}; no slot was cooled`,"warning")),{message:{...message,diagnostics:[...message.diagnostics??[],{type:"kpi_account_unattributed",timestamp:nowMs(),details:{candidates:taken.ambiguous.join(",")}}]}}}let{response}=taken,moved=response.retryOnMovedRoute;if(!response.classificationHandled){let classification=classifyProviderBodyFailure({status:response.status,body:message.errorMessage},nowMs());if(classification===void 0)return;moved=await applyFailure(response.served,classification.until,context)}if(moved)return{message:{...message,diagnostics:[...message.diagnostics??[],{type:"kpi_account_failover",timestamp:nowMs(),details:{from:`${response.served.poolId}/${response.served.slot.id}`}}]}}}),pi.on("agent_end",async()=>{pendingResponses.clear(),reportedAmbiguities.clear(),evictionReported=!1}),pi.on("turn_start",async(_event,context)=>{await refreshExpiringCredentials(context)}),pi.on("session_start",async(_event,context)=>{let imported=await resolved.store.importOfficialCredentials();imported.length>0&&context.ui.notify(`Imported official credentials as ${imported.join(", ")}`,"info"),await refreshExpiringCredentials(context),await usage.refreshAll(configuredSlots(await resolved.store.read()),context.signal),await publishWidget(context)})),pi.registerCommand("pool",{description:"Set a K-\u03C0 pool strategy or the fallback chain",handler:async(args,context)=>{try{await handlePoolCommand(args,context,resolved.store)&&await publishWidget(context)}catch(error){let message=error instanceof Error?error.message:String(error);context.ui.notify(`K-\u03C0 pool: ${message}`,"error")}}}),pi.registerCommand("accounts",{description:"Manage K-\u03C0 subscription accounts",handler:async(args,context)=>{try{await handleAccountsCommand(args,context,resolved,(poolId,slotId)=>{balancer.releaseSlot(poolId,slotId),usage.forget(poolId,slotId),active?.poolId===poolId&&active.slot.id===slotId&&(active=void 0,activeModel=void 0)},{activePool:()=>active?.poolId,advance:async poolId=>{balancer.advance(poolId),await reroute(poolId)},pin:async(poolId,slotId)=>{balancer.pinSlot(poolId,slotId),await reroute(poolId)}})&&await publishWidget(context)}catch(error){let message=error instanceof Error?error.message:String(error);context.ui.notify(`K-\u03C0 accounts: ${message}`,"error")}}})}import{readFileSync as readFileSync16,statSync as statSync11}from"node:fs";import{join as join42}from"node:path";var APPEND_SYSTEM_FILE="APPEND_SYSTEM.md";function shippedAppendSystemPath(){return join42(getKpiResourceDir(),"templates",APPEND_SYSTEM_FILE)}function installedAppendSystemPath(agentDirectory=getAgentDir()){return join42(agentDirectory,APPEND_SYSTEM_FILE)}function readIfPresent(path14){try{return readFileSync16(path14,"utf8")}catch(error){if(error.code==="ENOENT")return;throw error}}function ensureAppendSystemInstalled(agentDirectory=getAgentDir()){let target=installedAppendSystemPath(agentDirectory),shipped=readIfPresent(shippedAppendSystemPath());if(shipped===void 0)return{outcome:"unavailable",path:target};let existing=readIfPresent(target);return existing!==void 0?{outcome:existing===shipped?"current":"operator-owned",path:target}:(atomicWriteSync(target,shipped),{outcome:"installed",path:target})}async function installAppendSystemCommand(ctx,agentDirectory=getAgentDir()){let status=ensureAppendSystemInstalled(agentDirectory);if(status.outcome==="unavailable")return ctx.ui.notify(`No shipped ${APPEND_SYSTEM_FILE} found at ${shippedAppendSystemPath()}`,"warning"),status;if(status.outcome==="installed")return ctx.ui.notify(`Installed K-\u03C0 ${APPEND_SYSTEM_FILE} at ${status.path}`,"info"),status;if(status.outcome==="current")return ctx.ui.notify(`${status.path} already matches the shipped ${APPEND_SYSTEM_FILE}`,"info"),status;if(!await ctx.ui.confirm(`Replace ${APPEND_SYSTEM_FILE}?`,`${status.path} differs from the shipped prompt. Replace your version with K-\u03C0's?`))return ctx.ui.notify(`Kept your ${status.path}`,"info"),{outcome:"kept",path:status.path};let shipped=readIfPresent(shippedAppendSystemPath());return shipped===void 0?{outcome:"unavailable",path:status.path}:(atomicWriteSync(status.path,shipped),ctx.ui.notify(`Replaced ${status.path} with the shipped ${APPEND_SYSTEM_FILE}`,"info"),{outcome:"replaced",path:status.path})}function registerAppendSystem(pi){ensureAppendSystemInstalled(),pi.registerCommand("append-system",{description:"Install K-\u03C0's concise-output system prompt, or report the file already in place",handler:async(_args,ctx)=>{await installAppendSystemCommand(ctx)}})}var ParseError3=class extends Error{},READ_ONLY={readOnly:!0};function notReadOnly(reason,segment2){return segment2===void 0?{readOnly:!1,reason}:{readOnly:!1,reason,segment:segment2}}var Scanner=class{constructor(source2){this.index=0,this.word="",this.wordStarted=!1,this.current={words:[],redirects:[],substitutions:[]},this.commands=[],this.caseDepth=0,this.source=source2}scan(){for(;this.index<this.source.length;)this.step();return this.endWord(),this.endCommand(),this.commands}peek(offset=0){return this.source[this.index+offset]??""}take(){let character=this.source[this.index]??"";return this.index+=1,character}append(text){this.word+=text,this.wordStarted=!0}endWord(){this.wordStarted&&this.current.words.push(this.word),this.word="",this.wordStarted=!1}endCommand(){this.endWord();let{words:words2,redirects,substitutions}=this.current;(words2.length>0||redirects.length>0||substitutions.length>0)&&(this.commands.push(this.current),this.trackCase(words2)),this.current={words:[],redirects:[],substitutions:[]}}trackCase(words2){words2[0]==="case"&&(this.caseDepth+=1),words2.includes("esac")&&this.caseDepth>0&&(this.caseDepth-=1)}step(){let character=this.peek();if(character===" "||character===" "){this.take(),this.endWord();return}if(character==="#"&&!this.wordStarted){this.skipComment();return}this.stepOperator(character)||this.stepQuote(character)||this.stepExpansion(character)||this.stepRedirect(character)||this.stepGroup(character)||this.append(this.take())}skipComment(){for(;this.index<this.source.length&&this.peek()!==`
1327
+ `;)this.take()}stepOperator(character){if(character===`
1328
+ `||character===";"){for(this.take();this.peek()===";"||this.peek()==="&";)this.take();return this.endCommand(),!0}if(character==="|")return this.take(),(this.peek()==="|"||this.peek()==="&")&&this.take(),this.endCommand(),!0;if(character==="&"){if(this.peek(1)==="&")return this.take(),this.take(),this.endCommand(),!0;if(this.peek(1)===">")return!1;throw new ParseError3("a background job (&) cannot be classified")}return!1}stepQuote(character){return character==="\\"?(this.take(),this.append(this.take()),!0):character==="'"||character==="$"&&this.peek(1)==="'"?(character==="$"&&this.take(),this.take(),this.append(this.readUntil("'","an unterminated single quote")),this.take(),!0):character==='"'?(this.take(),this.readDoubleQuoted(),!0):!1}readUntil(terminator,failure){let end=this.source.indexOf(terminator,this.index);if(end<0)throw new ParseError3(failure);let text=this.source.slice(this.index,end);return this.index=end,text}readDoubleQuoted(){for(this.wordStarted=!0;;){if(this.index>=this.source.length)throw new ParseError3("an unterminated double quote");let character=this.peek();if(character==='"'){this.take();return}if(character==="\\"){this.take(),this.append(this.take());continue}if(character==="`"||character==="$"&&this.peek(1)==="("){this.captureSubstitution();continue}if(character==="$"&&this.peek(1)==="{"){this.take(),this.append(this.readParameterExpansion());continue}this.append(this.take())}}stepExpansion(character){return character==="`"?(this.captureSubstitution(),!0):character!=="$"?!1:this.peek(1)==="("&&this.peek(2)==="("?(this.take(),this.append(this.readBalanced("(",")")),!0):this.peek(1)==="("?(this.captureSubstitution(),!0):this.peek(1)==="{"?(this.take(),this.append(this.readParameterExpansion()),!0):(this.append(this.take()),!0)}captureSubstitution(){if(this.wordStarted=!0,this.peek()==="`"){this.take();let body2=this.readUntil("`","an unterminated backtick");this.take(),this.current.substitutions.push(body2),this.append("`\u2026`");return}this.take();let body=this.readBalanced("(",")");this.current.substitutions.push(body.slice(1,-1)),this.append("$(\u2026)")}readBalanced(open10,close){let depth=0,start=this.index;for(;this.index<this.source.length;){let character=this.take();if(character==="\\"){this.take();continue}if(character==="'"){this.readUntil("'","an unterminated single quote"),this.take();continue}if(character===open10&&(depth+=1),character===close&&(depth-=1,depth===0))return this.source.slice(start,this.index)}throw new ParseError3(`an unbalanced ${open10}`)}readParameterExpansion(){let body=this.readBalanced("{","}");if(body.includes("$(")||body.includes("`"))throw new ParseError3("a command substitution inside a parameter expansion");return`$${body}`}stepRedirect(character){if(character!=="<"&&character!==">"&&!(character==="&"&&this.peek(1)===">"))return!1;let descriptor="";this.wordStarted&&/^\d$/u.test(this.word)?(descriptor=this.word,this.word="",this.wordStarted=!1):this.endWord();let operator2=this.readRedirectOperator(),target=this.readRedirectTarget();return this.current.redirects.push(`${descriptor}${operator2}${target}`),!0}readRedirectOperator(){let operator2=this.take();for(operator2==="&"&&(operator2+=this.take());this.peek()===">"||this.peek()==="<"||this.peek()==="&"||this.peek()==="|";)operator2+=this.take();if(operator2.includes("<<"))throw new ParseError3("a heredoc or here-string");if(this.peek()==="(")throw new ParseError3("a process substitution");return operator2}readRedirectTarget(){for(;this.peek()===" "||this.peek()===" ";)this.take();let target="";for(;this.index<this.source.length&&!/[\s;&|<>()]/u.test(this.peek());){let character=this.take();if(character==="'"||character==='"'){target+=this.readUntil(character,"an unterminated quote in a redirect"),this.take();continue}target+=character}return target}stepGroup(character){if(character==="("){if(this.wordStarted)throw new ParseError3("a function definition or a stray paren");let body=this.readBalanced("(",")");return this.current.substitutions.push(body.slice(1,-1)),this.append("(\u2026)"),!0}if(character===")"){if(this.current.words[0]==="case"&&(this.caseDepth+=1),this.caseDepth===0)throw new ParseError3("an unbalanced )");return this.take(),this.word="",this.wordStarted=!1,this.current.words=[],!0}return!1}};function tokenizeShellCommand(command){return new Scanner(command).scan()}var PREFIX_CONTROL_WORDS=new Set(["if","then","else","elif","while","until","do","!","{","time"]),STANDALONE_CONTROL_WORDS=new Set(["fi","done","esac","}","]]",";;",":","true","false","exit"]),SHELL_STATE_BUILTINS=new Set(["read","local","export","unset","shift","break","continue","return","wait"]),HARMLESS_REDIRECT=/^(?:\d?>&[12-]|\d?>>?\/dev\/null|&>>?\/dev\/null|\d?>&-|<[^<]*)$/u,ASSIGNMENT=/^[A-Za-z_][A-Za-z0-9_]*=/u,HELP_OR_VERSION=new Set(["--help","--version","-h","-v","-V","-version"]),always=()=>!0,withoutFlags=(...forbidden)=>args=>!args.some(arg=>forbidden.some(flag=>arg===flag||arg.startsWith(`${flag}=`))),GIT_READ_VERBS=new Set(["status","log","diff","show","rev-parse","rev-list","ls-files","ls-remote","ls-tree","blame","describe","shortlog","name-rev","cat-file","help","--version","var","check-ignore","merge-base"]),GIT_BRANCH_LIST_FLAGS=/^(?:--show-current|--list|-a|-r|-v|-vv|--all|--remotes|--verbose|--contains=?.*|--merged=?.*|--no-merged=?.*|--format=.*|--sort=.*|--points-at=?.*|--column|--no-column)$/u;function gitRefinement(rawArgs){let args=[...rawArgs];for(;args[0]==="--no-pager"||args[0]==="-P"||args[0]==="-C";)args.shift()==="-C"&&args.shift();if(args.some(arg=>arg.startsWith("--output")))return!1;let[verb,...rest]=args;if(verb===void 0)return!1;if(GIT_READ_VERBS.has(verb))return!0;switch(verb){case"branch":return rest.every(arg=>GIT_BRANCH_LIST_FLAGS.test(arg));case"remote":return rest.length===0||rest[0]==="-v"||rest[0]==="show"||rest[0]==="get-url";case"config":return["--get","--get-all","--get-regexp","--list","-l"].includes(rest[0]??"");case"stash":return rest[0]==="list"||rest[0]==="show";case"reflog":return rest.length===0||rest[0]==="show";case"tag":return rest.length===0||rest.every(arg=>arg==="-l"||arg==="--list"||arg==="-n"||!arg.startsWith("-"));case"worktree":return rest[0]==="list";default:return!1}}function ghRefinement(args){let[group,verb]=args;if(group===void 0)return!1;switch(group){case"--version":return!0;case"pr":return["view","list","status","checks","diff"].includes(verb??"");case"auth":return verb==="status";case"repo":return verb==="view";case"run":return verb==="list"||verb==="view";default:return!1}}function npmRefinement(args){let[verb,...rest]=args;return verb===void 0?!1:["ls","list","ll","la","view","info","show","outdated","why","explain","--version","-v"].includes(verb)?!0:verb==="audit"?!rest.includes("fix"):verb==="config"?["get","list","ls"].includes(rest[0]??""):verb==="pkg"?rest[0]==="get":!1}function sedRefinement(args){return!args.some(arg=>arg==="-n"||arg==="--quiet"||arg==="--silent"||/^-[a-zA-Z]*n[a-zA-Z]*$/u.test(arg))||args.some(arg=>arg==="-i"||arg.startsWith("--in-place")||/^-[a-zA-Z]*i/u.test(arg))?!1:!args.some(arg=>/(?:^|[;{\s])[wW]\s/u.test(arg))}function awkRefinement(args){return args.some(arg=>arg==="-i"||arg.startsWith("--in-place"))?!1:!args.some(arg=>/system\s*\(|>|\|/u.test(arg))}var findRefinement=withoutFlags("-exec","-execdir","-ok","-okdir","-delete","-fprint","-fprint0","-fprintf","-fls"),READ_ONLY_HEADS={cat:always,head:always,tail:always,less:always,more:always,grep:always,egrep:always,fgrep:always,rg:withoutFlags("--pre"),ls:always,pwd:always,echo:always,printf:always,wc:always,sort:withoutFlags("-o","--output"),uniq:always,cut:always,tr:always,diff:always,cmp:always,comm:always,file:always,stat:always,du:always,df:always,tree:withoutFlags("-o"),which:always,whereis:always,type:always,env:always,printenv:always,uname:always,whoami:always,id:always,hostname:always,arch:always,nproc:always,uptime:always,ps:always,lsof:always,date:withoutFlags("-s","--set"),basename:always,dirname:always,realpath:always,readlink:always,jq:always,column:always,nl:always,tac:always,fold:always,paste:always,seq:always,expr:always,sleep:always,md5sum:always,sha1sum:always,sha256sum:always,shasum:always,strings:always,od:always,hexdump:always,test:always,"[":always,"[[":always,sed:sedRefinement,awk:awkRefinement,gawk:awkRefinement,mawk:awkRefinement,find:findRefinement,fd:withoutFlags("-x","--exec","-X","--exec-batch"),git:gitRefinement,gh:ghRefinement,npm:npmRefinement,pnpm:args=>["ls","list","why","outdated","--version","-v"].includes(args[0]??""),yarn:args=>["--version","-v","list","why","info"].includes(args[0]??""),bun:args=>args[0]==="--version"||args[0]==="-v",node:args=>args.length===1&&(args[0]==="--version"||args[0]==="-v"),java:args=>args.length===1&&(args[0]==="-version"||args[0]==="--version"),go:args=>args[0]==="version"};function dropFlags(args,valued,bare){let rest=[...args];for(;rest.length>0;){let head=rest[0]??"";if(valued.test(head))rest.splice(0,head.includes("=")||/^-[a-zA-Z]\S+$/u.test(head)?1:2);else if(bare.test(head)||ASSIGNMENT.test(head))rest.shift();else break}return rest}var WRAPPERS={env:{unwrap:args=>dropFlags(args,/^(?:-u|--unset)/u,/^(?:-i|-0|--ignore-environment|--null)$/u)},command:{unwrap:args=>{if(!(args[0]==="-v"||args[0]==="-V"))return args[0]==="-p"?args.slice(1):args}},xargs:{unwrap:args=>{let rest=dropFlags(args,/^(?:-n|-I|-d|-P|-L|-s|-E|--max-args|--replace|--delimiter|--max-procs|--max-lines)/u,/^(?:-0|-r|-t|-p|--null|--no-run-if-empty|--verbose)$/u);return rest.length===0?void 0:rest}},timeout:{unwrap:args=>dropFlags(args,/^(?:-s|-k|--signal|--kill-after)/u,/^(?:--foreground|--preserve-status|-v|--verbose)$/u).slice(1)},nice:{unwrap:args=>dropFlags(args,/^(?:-n|--adjustment)/u,/^-\d+$/u)},time:{unwrap:args=>dropFlags(args,/^(?:-f|-o|--format|--output)/u,/^(?:-p|-v|--verbose|--portability)$/u)}};function headName(word){return word.startsWith("/")?word.split("/").pop()??word:word}function classifyWords(rawWords,depth){let words2=[...rawWords];for(;words2.length>0&&PREFIX_CONTROL_WORDS.has(words2[0]??"");)words2.shift();for(;words2.length>0&&ASSIGNMENT.test(words2[0]??"");)words2.shift();if(words2.length===0)return READ_ONLY;let head=headName(words2[0]??""),args=words2.slice(1),segment2=words2.join(" ");if(STANDALONE_CONTROL_WORDS.has(head)||SHELL_STATE_BUILTINS.has(head))return READ_ONLY;if(head==="(\u2026)")return args.length===0?READ_ONLY:notReadOnly("a subshell with trailing words",segment2);if(head==="$(\u2026)"||head==="`\u2026`")return notReadOnly("a command taken from substitution output",segment2);if(head==="for"||head==="case"||head==="select"||head==="in")return READ_ONLY;if(head==="set")return args.every(arg=>/^[-+][a-zA-Z]+$/u.test(arg)||arg==="-o"||arg==="+o"||/^[a-z]+$/u.test(arg))?READ_ONLY:notReadOnly("set with positional parameters",segment2);if(head==="cd")return args.length<=1?READ_ONLY:notReadOnly("cd with extra arguments",segment2);let wrapper=WRAPPERS[head];if(wrapper!==void 0){let inner=wrapper.unwrap(args);return inner===void 0?READ_ONLY:depth>8?notReadOnly("wrappers nested too deeply",segment2):classifyWords(inner,depth+1)}let refinement=READ_ONLY_HEADS[head];return refinement!==void 0?refinement(args)?READ_ONLY:notReadOnly(`${head} with an argument that writes or executes`,segment2):args.length===1&&HELP_OR_VERSION.has(args[0]??"")?READ_ONLY:notReadOnly(`unknown head "${head}"`,segment2)}function classifySimple(command,depth){for(let body of command.substitutions){let nested=classifyCommand(body,depth+1);if(!nested.readOnly)return nested}let redirect=command.redirects.find(entry=>!HARMLESS_REDIRECT.test(entry));return redirect!==void 0?notReadOnly(`a redirect that writes a file (${redirect})`,command.words.join(" ")):classifyWords(command.words,depth)}function classifyCommand(command,depth){if(depth>8)return notReadOnly("substitutions nested too deeply");let commands;try{commands=tokenizeShellCommand(command)}catch(error){if(error instanceof ParseError3)return notReadOnly(error.message);throw error}for(let simple of commands){let verdict=classifySimple(simple,depth);if(!verdict.readOnly)return verdict}return READ_ONLY}function classifyShellCommand(command){return command.trim().length===0?READ_ONLY:classifyCommand(command,0)}import{lstat,mkdir as mkdir5,readdir as readdir4,readFile as readFile13,readlink,realpath as realpath2,stat as stat4,writeFile}from"node:fs/promises";import{dirname as dirname25,isAbsolute as isAbsolute4,join as join43,parse as parse4,relative as relative5,resolve as resolve13,sep as sep9}from"node:path";var LAYER_FOLDERS=new Set(["components","hooks","lib","libs","services","controllers","models","views","api","apis","ui","frontend","backend","routes","handlers","middleware","pages"]),GENERIC_FOLDERS=new Set(["utils","helpers","common","misc","core","shared-utils"]),GENERIC_FOLDER_FILE_BUDGET=5,NO_STACK_PLAYBOOKS=new Set(["typo","unslop","comment-strip"]),LAYER_SWEEP_PATTERN=/\ball\s+(?:the\s+)?(?:apis?|endpoints?|controllers?|routes?|screens?|uis?|views?|pages?|components?)\b/iu,DuneStackError=class extends Error{constructor(message){super(message),this.name="DuneStackError"}};function normalizeProjectPath(projectRoot,value){if(value.length===0)return;let absolute=isAbsolute4(value)?resolve13(value):resolve13(projectRoot,value),relativePath=relative5(resolve13(projectRoot),absolute);if(!(relativePath.length===0||relativePath===".."||relativePath.startsWith(`..${sep9}`)||isAbsolute4(relativePath)))return relativePath.split(sep9).join("/")}function patternSegments(pattern){return pattern.replaceAll("\\","/").split("/").filter(segment2=>segment2.length>0&&segment2!==".")}function segmentMatcher(segment2){let source2=segment2.replaceAll(/[.+^${}()|[\]\\]/gu,"\\$&").replaceAll("*","[^/]*").replaceAll("?","[^/]");return new RegExp(`^${source2}$`,"u")}function matchesPathPattern(pattern,candidate){let patternParts=patternSegments(pattern),candidateParts=patternSegments(candidate),walk=(patternIndex,candidateIndex)=>{if(patternIndex===patternParts.length)return candidateIndex===candidateParts.length;let part=patternParts[patternIndex];if(part==="**"){for(let skip=candidateIndex;skip<=candidateParts.length;skip+=1)if(walk(patternIndex+1,skip))return!0;return!1}return candidateIndex===candidateParts.length?!1:segmentMatcher(part).test(candidateParts[candidateIndex])&&walk(patternIndex+1,candidateIndex+1)};return walk(0,0)?!0:!patternParts.some(part=>part.includes("*")||part.includes("?"))&&candidateParts.length>patternParts.length?patternParts.every((part,index3)=>part===candidateParts[index3]):!1}function assertDeclaredPath(value,label,options){if(typeof value!="string"||value.length===0||value!==value.trim())throw new DuneStackError(`${label} must be a trimmed, non-empty path`);if(/^[/\\]/u.test(value)||/^[A-Za-z]:[/\\]/u.test(value))throw new DuneStackError(`${label} must be repository-relative, not absolute: ${value}`);let parts=value.replaceAll("\\","/").split("/");for(let part of parts){if(part.length===0)throw new DuneStackError(`${label} must not contain an empty path segment: ${value}`);if(part==="."||part==="..")throw new DuneStackError(`${label} must not contain a ${part} segment: ${value}`)}if(!options.allowGlob&&/[*?[\]]/u.test(value))throw new DuneStackError(`${label} must name an exact path, not a pattern: ${value}`);return parts}function testTwinFor(module){return`test/${module.id}`}function moduleOwnsPath(projectRoot,module,path14){let normalized=normalizeProjectPath(projectRoot,path14);return normalized===void 0?!1:[...module.allowed_paths,module.folder,module.interface,testTwinFor(module)].some(pattern=>matchesPathPattern(pattern,normalized))}function assertStringField(value,label){if(typeof value!="string"||value.trim().length===0)throw new DuneStackError(`${label} must be a non-empty string`)}function assertModuleShape(value,index3){if(!isJsonObject(value))throw new DuneStackError(`modules[${index3}] must be an object`);if(assertStringField(value.id,`modules[${index3}].id`),assertDeclaredPath(value.id,`modules[${index3}].id`,{allowGlob:!1}).length!==1)throw new DuneStackError(`modules[${index3}].id must be a single path segment: ${String(value.id)}`);if(assertStringField(value.purpose,`modules[${index3}].purpose`),assertDeclaredPath(value.folder,`modules[${index3}].folder`,{allowGlob:!1}),assertDeclaredPath(value.interface,`modules[${index3}].interface`,{allowGlob:!1}),!Array.isArray(value.allowed_paths)||value.allowed_paths.some(entry=>typeof entry!="string"))throw new DuneStackError(`modules[${index3}].allowed_paths must be an array of strings`);if(value.allowed_paths.length===0)throw new DuneStackError(`modules[${index3}].allowed_paths must not be empty`);for(let[entryIndex,entry]of value.allowed_paths.entries())assertDeclaredPath(entry,`modules[${index3}].allowed_paths[${entryIndex}]`,{allowGlob:!0});if(!Array.isArray(value.depends_on)||value.depends_on.some(entry=>typeof entry!="string"))throw new DuneStackError(`modules[${index3}].depends_on must be an array of strings`)}function assertDuneStack(value){if(!isJsonObject(value))throw new DuneStackError("stack must be an object");if(value.version!==1||value.shape!=="dune"||value.scaffold_first!==!0)throw new DuneStackError("Invalid Dune stack header");if(value.delivery!=="vertical"&&value.delivery!=="horizontal")throw new DuneStackError("delivery must be vertical or horizontal");if(value.delivery==="horizontal"&&(typeof value.delivery_reason!="string"||value.delivery_reason.trim().length===0))throw new DuneStackError("Horizontal delivery requires a reason");if(assertStringField(value.root,"root"),assertDeclaredPath(value.root,"root",{allowGlob:!1}),!Array.isArray(value.modules)||value.modules.length===0)throw new DuneStackError("stack must declare at least one module");let ids=new Set,modules=[];for(let[index3,entry]of value.modules.entries()){if(assertModuleShape(entry,index3),ids.has(entry.id))throw new DuneStackError(`duplicate module id: ${entry.id}`);ids.add(entry.id),modules.push(entry)}let root=patternSegments(value.root);for(let module of modules){let folder=patternSegments(module.folder);if(folder.length===0)throw new DuneStackError(`Module ${module.id} has no folder`);if(folder.at(-1)!==module.id)throw new DuneStackError(`Module folder must match id: ${module.id}`);if(folder.length<=root.length||!root.every((part,index3)=>part===folder[index3]))throw new DuneStackError(`Module ${module.id} folder must live under root ${value.root}: ${module.folder}`);let isTopLevel=folder.length===root.length+1;if(LAYER_FOLDERS.has(module.id)&&isTopLevel)throw new DuneStackError(`Layer folder ${module.id} cannot be a top-level module`);if(GENERIC_FOLDERS.has(module.id)&&module.purpose.trim().split(/\s+/u).length<3)throw new DuneStackError(`Generic module needs a tight purpose: ${module.id}`);if(module.id==="auth"&&folder.slice(0,-1).some(part=>LAYER_FOLDERS.has(part)))throw new DuneStackError("Auth must live in its auth folder");if(!matchesPathPattern(module.folder,module.interface))throw new DuneStackError(`Interface must live inside ${module.folder}`);let folderProbe=`${folder.join("/")}/index.ts`;if(!module.allowed_paths.some(pattern=>matchesPathPattern(pattern,folderProbe)))throw new DuneStackError(`Module ${module.id} does not allow its own folder`);let twinProbe=`${testTwinFor(module)}/index.test.ts`;if(!module.allowed_paths.some(pattern=>matchesPathPattern(pattern,twinProbe)))throw new DuneStackError(`Module ${module.id} lacks its test twin`);for(let dependency of module.depends_on)if(!ids.has(dependency))throw new DuneStackError(`Module ${module.id} depends on unknown module ${dependency}`)}for(let module of modules){if(module.id!=="shared")continue;let consumers=modules.filter(candidate=>candidate.depends_on.includes(module.id));if(consumers.length<2)throw new DuneStackError(`shared needs two consuming slices before extraction; ${consumers.length} declared`)}if(value.delivery==="vertical"){for(let module of modules)if(LAYER_SWEEP_PATTERN.test(module.purpose)||LAYER_SWEEP_PATTERN.test(module.id))throw new DuneStackError(`Vertical delivery cannot stage a layer sweep: ${module.id} (${module.purpose})`);let layerModules=modules.filter(module=>LAYER_FOLDERS.has(module.id));if(layerModules.length>=2)throw new DuneStackError(`Vertical delivery cannot be a layer staging plan: ${layerModules.map(module=>module.id).join(", ")}`)}}function stackRequiredFor(task){let playbook=task.playbook?.trim().toLowerCase();return playbook===void 0||!NO_STACK_PLAYBOOKS.has(playbook)}function stackTaskHash(task){return contractHash(task)}function resolveCurrentModule(stack,task){let requested=task.current_module_id?.trim();if(requested===void 0||requested.length===0)throw new DuneStackError("task.json must name current_module_id; modules[0] is never the current slice");let matches=stack.modules.filter(module=>module.id===requested);if(matches.length!==1)throw new DuneStackError(`current_module_id ${requested} does not name exactly one module`);return matches[0]}async function countFiles(directory){let entries;try{entries=await readdir4(directory,{withFileTypes:!0})}catch(error){if(error.code==="ENOENT")return 0;throw error}let total=0;for(let entry of entries)total+=entry.isDirectory()?await countFiles(join43(directory,entry.name)):1;return total}async function assertGenericFolderBudget(projectRoot,stack){for(let module of stack.modules){if(!GENERIC_FOLDERS.has(module.id))continue;let files=await countFiles(join43(projectRoot,module.folder));if(files>=GENERIC_FOLDER_FILE_BUDGET)throw new DuneStackError(`Generic folder ${module.folder} holds ${files} files; the budget is ${GENERIC_FOLDER_FILE_BUDGET}`)}}async function readDuneStack(runDirectory){let raw;try{raw=await readFile13(join43(runDirectory,"stack.json"),"utf8")}catch(error){throw error.code==="ENOENT"?new DuneStackError("stack.json is missing; implement has no frozen map to read"):error}let parsed;try{parsed=JSON.parse(raw)}catch{throw new DuneStackError("stack.json is not valid JSON")}return assertDuneStack(parsed),parsed}async function assertStackFresh(runDirectory,task,stack){if(stack.task_hash!==void 0){if(stack.task_hash!==stackTaskHash(task))throw new DuneStackError("stack.json was frozen against a different task.json");return}let stackStat=await stat4(join43(runDirectory,"stack.json")),taskStat;try{taskStat=await stat4(join43(runDirectory,"task.json"))}catch(error){throw error.code==="ENOENT"?new DuneStackError("task.json is missing, so stack.json freshness cannot be established"):error}if(stackStat.mtimeMs<taskStat.mtimeMs)throw new DuneStackError("stack.json is older than task.json")}async function freezeCurrentSlice(projectRoot,runDirectory,task){let stack=await readDuneStack(runDirectory);if(await assertStackFresh(runDirectory,task,stack),await assertGenericFolderBudget(projectRoot,stack),task.current_module_id!==void 0&&stack.current_module_id!==void 0&&task.current_module_id.trim()!==stack.current_module_id.trim())throw new DuneStackError(`stack.json names slice ${stack.current_module_id} while task.json names ${task.current_module_id}`);if(task.current_module_id===void 0&&stack.current_module_id!==void 0){let frozen={...task,current_module_id:stack.current_module_id};resolveCurrentModule(stack,frozen),await atomicWrite(join43(runDirectory,"task.json"),`${JSON.stringify(frozen,null,2)}
1327
1329
  `),task.current_module_id=stack.current_module_id}return{stack,module:resolveCurrentModule(stack,task)}}var MAX_LINK_RESOLUTION_STEPS=64,MAX_PATH_COMPONENT_STEPS=4096;function splitAbsolute(absolute){let parsed=parse4(absolute),remainder=absolute.slice(parsed.root.length);return{root:parsed.root,parts:remainder.split(/[/\\]+/u).filter(part=>part.length>0)}}async function resolveClaimTarget(startAbsolute){let start=splitAbsolute(resolve13(startAbsolute)),base=start.root,pending=start.parts,hops=0,steps=0;for(;pending.length>0;){if(steps+=1,steps>MAX_PATH_COMPONENT_STEPS)return{kind:"exhausted"};let segment2=pending.shift();if(segment2===".")continue;if(segment2===".."){base=dirname25(base);continue}let candidate=join43(base,segment2),link2;try{link2=(await lstat(candidate)).isSymbolicLink()?await readlink(candidate):void 0}catch(error){let code=error.code;if(code==="ELOOP")return{kind:"exhausted"};if(code!=="ENOENT"&&code!=="ENOTDIR")throw error;return{kind:"resolved",absolute:join43(candidate,...pending)}}if(link2===void 0){base=candidate;continue}if(hops+=1,hops>MAX_LINK_RESOLUTION_STEPS)return{kind:"exhausted"};let target=splitAbsolute(isAbsolute4(link2)?resolve13(link2):resolve13(base,link2));base=target.root,pending=[...target.parts,...pending]}return{kind:"resolved",absolute:base}}async function canonicalProjectPath(projectRoot,path14){let normalized=normalizeProjectPath(projectRoot,path14);if(normalized===void 0)throw new DuneStackError(`UNSAFE claim outside the project: ${path14}`);let realRoot;try{realRoot=await realpath2(projectRoot)}catch(error){if(error.code!=="ENOENT")throw error;realRoot=resolve13(projectRoot)}let resolution=await resolveClaimTarget(join43(projectRoot,normalized));if(resolution.kind==="exhausted")throw new DuneStackError(`UNSAFE claim follows too many links to resolve: ${path14}`);let insideRoot=relative5(realRoot,resolution.absolute);if(insideRoot===".."||insideRoot.startsWith(`..${sep9}`)||isAbsolute4(insideRoot))throw new DuneStackError(`UNSAFE claim escapes the project through a link: ${path14}`);let resolved=insideRoot.split(sep9).join("/");return resolved.length>0?resolved:normalized}async function assertClaimInModule(projectRoot,path14,module){let normalized=normalizeProjectPath(projectRoot,path14);if(normalized===void 0||!moduleOwnsPath(projectRoot,module,normalized))throw new DuneStackError(`UNSAFE claim outside module ${module.id}: ${path14}`);let canonical=await canonicalProjectPath(projectRoot,path14);if(!moduleOwnsPath(projectRoot,module,canonical))throw new DuneStackError(`UNSAFE claim outside module ${module.id} after link resolution: ${path14}`);return canonical}async function createIfAbsent(path14){try{await writeFile(path14,`export {};
1328
1330
  `,{flag:"wx"})}catch(error){if(error.code!=="EEXIST")throw error}}async function scaffoldModule(projectRoot,module){let folder=join43(projectRoot,module.folder),interfacePath=join43(projectRoot,module.interface),testTwin=join43(projectRoot,testTwinFor(module),"index.test.ts"),steps=[];return await mkdir5(folder,{recursive:!0}),steps.push(module.folder),await mkdir5(dirname25(interfacePath),{recursive:!0}),await createIfAbsent(interfacePath),steps.push(module.interface),await mkdir5(dirname25(testTwin),{recursive:!0}),await createIfAbsent(testTwin),steps.push(`${testTwinFor(module)}/index.test.ts`),{steps,folder,interface:interfacePath,testTwin}}async function assertScaffoldedBeforeBehavior(projectRoot,module){let behaviour=[],scan2=async(directory,prefix)=>{let entries;try{entries=await readdir4(join43(projectRoot,directory),{withFileTypes:!0})}catch{return}for(let entry of entries){let child=`${directory}/${entry.name}`;if(entry.isDirectory()){await scan2(child,prefix);continue}child!==module.interface&&behaviour.push(child)}};if(await scan2(patternSegments(module.folder).join("/"),module.id),behaviour.length===0)return;let missing=[];for(let required of[module.interface,`${testTwinFor(module)}/index.test.ts`])try{await stat4(join43(projectRoot,required))}catch{missing.push(required)}if(missing.length>0)throw new DuneStackError(`Module ${module.id} has behaviour (${behaviour[0]}) before its scaffold: missing ${missing.join(", ")}`)}import{mkdir as mkdir6,open as open7}from"node:fs/promises";import{join as join44}from"node:path";async function appendBusDenial(runDirectory,jobId,denial){await mkdir6(runDirectory,{recursive:!0});let record={ts:new Date().toISOString(),type:"agent.denied",job_id:jobId,...denial},file=await open7(join44(runDirectory,"bus.jsonl"),"a",384);try{await file.writeFile(`${JSON.stringify(record)}
1329
- `),await file.sync()}finally{await file.close()}}import{randomUUID as randomUUID8}from"node:crypto";import{stat as stat5}from"node:fs/promises";import{basename as basename12,isAbsolute as isAbsolute5,join as join45,resolve as resolve14}from"node:path";var WORKER_ROLES=["implementer","reviewer","tester","arena","explorer"];function isWorkerRole(value){return typeof value=="string"&&WORKER_ROLES.includes(value)}var MUTATION_TOOLS=new Set(["write","edit","apply_patch","multi_edit"]),ROLE_TOOLS={implementer:["read","grep","find","ls","bash","write","edit","claim_path","release_path"],reviewer:["read","grep","find","ls","bash","write_contract"],tester:["read","grep","find","ls","bash","write_contract"],arena:["read","grep","find","ls","bash","write","edit","claim_path","release_path"],explorer:["read","grep","find","ls"]},TEST_SHELL_ROLES=new Set(["reviewer","tester"]);function hasTestShellOnly(role){return TEST_SHELL_ROLES.has(role)}var ROLE_CONTRACT_FILE={reviewer:{file:"verdict.json",schema:"verdict.schema.json"},tester:{file:"evidence.json",schema:"evidence.schema.json"}},ROLE_RESULT_FILE={reviewer:"verdict.json",tester:"evidence.json",implementer:"candidate.json",arena:"candidate.json"};function resolveRoleTools(role,requested){let allowed=ROLE_TOOLS[role];if(requested===void 0)return[...allowed];let forbidden=requested.filter(tool=>!allowed.includes(tool));if(forbidden.length>0)throw new Error(`role ${role} may not hold ${forbidden.join(", ")}`);return[...new Set(requested)]}function isWriterToolSet(tools){return tools.some(tool=>MUTATION_TOOLS.has(tool))}var WORKER_DESCRIPTOR_ENV="KPI_WORKER_DESCRIPTOR",WorkerIdentityError=class extends Error{constructor(message){super(message),this.name="WorkerIdentityError"}};function mintCapabilityId(){return randomUUID8()}function mintWorkerDescriptor(options){let contract=ROLE_CONTRACT_FILE[options.role];return Object.freeze({agentId:options.agentId,jobId:options.jobId,role:options.role,runDirectory:resolve14(options.runDirectory),contractPath:contract?.file,tools:Object.freeze([...options.tools]),capabilityId:contract===void 0?void 0:options.capabilityId,qualityGates:hasTestShellOnly(options.role)?Object.freeze(normalizeGates(options.qualityGates)):void 0})}function normalizeGates(gates){let seen=new Set;for(let gate of gates??[])typeof gate=="string"&&gate.trim().length>0&&seen.add(gate.trim());return[...seen]}function descriptorEnv(descriptor){return{[WORKER_DESCRIPTOR_ENV]:JSON.stringify(descriptor)}}var RAW_DESCRIPTOR=process.env[WORKER_DESCRIPTOR_ENV];function rawWorkerDescriptor(env2){return env2===void 0?RAW_DESCRIPTOR:env2[WORKER_DESCRIPTOR_ENV]}function hasWorkerDescriptor(env2){let raw=rawWorkerDescriptor(env2);return typeof raw=="string"&&raw.trim().length>0}function parseDescriptor(raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new WorkerIdentityError(`${WORKER_DESCRIPTOR_ENV} is not valid JSON`)}if(!isJsonObject(parsed))throw new WorkerIdentityError(`${WORKER_DESCRIPTOR_ENV} is not an object`);let{agentId,jobId,role,runDirectory,contractPath,tools,capabilityId,qualityGates}=parsed;if(typeof agentId!="string"||agentId.trim().length===0)throw new WorkerIdentityError("worker descriptor has no agentId");if(typeof jobId!="string"||jobId.trim().length===0)throw new WorkerIdentityError("worker descriptor has no jobId");if(!isWorkerRole(role))throw new WorkerIdentityError(`worker descriptor has an unknown role: ${String(role)}`);if(typeof runDirectory!="string"||!isAbsolute5(runDirectory))throw new WorkerIdentityError("worker descriptor needs an absolute runDirectory");if(!agentId.startsWith(`${role}-`))throw new WorkerIdentityError(`worker descriptor agentId ${agentId} does not belong to role ${role}`);let declared=ROLE_CONTRACT_FILE[role]?.file;if(contractPath!==void 0&&contractPath!==declared)throw new WorkerIdentityError(`worker descriptor claims contract ${String(contractPath)}; role ${role} publishes ${declared??"nothing"}`);if(declared!==void 0&&(typeof capabilityId!="string"||capabilityId.trim().length===0))throw new WorkerIdentityError(`role ${role} publishes ${declared} and needs a capability id`);let allowed=ROLE_TOOLS[role],granted=(Array.isArray(tools)?tools.filter(tool=>typeof tool=="string"):[]).filter(tool=>allowed.includes(tool)),gates=hasTestShellOnly(role)?Object.freeze(normalizeGates(Array.isArray(qualityGates)?qualityGates:[])):void 0;return Object.freeze({agentId,jobId,role,runDirectory:resolve14(runDirectory),contractPath:declared,tools:Object.freeze(granted),capabilityId:declared===void 0?void 0:capabilityId,qualityGates:gates})}var validated=new Map;async function resolveWorkerIdentity(cwd,env2){let raw=rawWorkerDescriptor(env2);if(raw===void 0||raw.trim().length===0)return;let key=`${resolve14(cwd)}\0${raw}`,cached=validated.get(key);if(cached!==void 0)return cached;let descriptor=parseDescriptor(raw);if(basename12(descriptor.runDirectory)!==descriptor.jobId)throw new WorkerIdentityError(`worker descriptor run directory ${descriptor.runDirectory} is not job ${descriptor.jobId}`);let expected=resolve14(cwd,CONFIG_DIR_NAME,"runs",descriptor.jobId);if(expected!==descriptor.runDirectory)throw new WorkerIdentityError(`worker descriptor belongs to another project: expected ${expected}, got ${descriptor.runDirectory}`);let info=await stat5(descriptor.runDirectory).catch(()=>{});if(info===void 0||!info.isDirectory())throw new WorkerIdentityError(`worker descriptor run directory does not exist: ${descriptor.runDirectory}`);if(await readTaskForJob(cwd,descriptor.jobId).catch(()=>{})===void 0)throw new WorkerIdentityError(`worker descriptor names job ${descriptor.jobId}, which has no task.json`);let identity=Object.freeze({...descriptor,cwd:resolve14(cwd)});return validated.set(key,identity),identity}async function requireWorkerIdentity(cwd,env2){let identity=await resolveWorkerIdentity(cwd,env2);if(identity===void 0)throw new WorkerIdentityError("this tool belongs to a background K-\u03C0 worker; a parent session has no worker identity");return identity}function authorizeWorkerTool(identity,tool){if(!identity.tools.includes(tool))throw new WorkerIdentityError(`worker ${identity.agentId} (${identity.role}) does not hold ${tool}`)}import{randomUUID as randomUUID9}from"node:crypto";import{link,mkdir as mkdir7,open as open8,readFile as readFile14,rm as rm5,stat as stat6}from"node:fs/promises";import{join as join46}from"node:path";var LEASE_LOCK_TIMEOUT_MS=1e4,LEASE_LOCK_STALE_MS=3e4,LEASE_LOCK_RETRY_MS=5;function defaultIsProcessAlive(pid){if(!Number.isInteger(pid)||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error){return error.code==="EPERM"}}var defaultSleep=ms=>new Promise(resolvePromise=>setTimeout(resolvePromise,ms));function parseLockOwner(contents){try{let parsed=JSON.parse(contents);if(isJsonObject(parsed)&&typeof parsed.pid=="number"&&typeof parsed.nonce=="string"&&typeof parsed.at=="string")return{pid:parsed.pid,nonce:parsed.nonce,at:parsed.at}}catch{return}}async function acquireLock(path14,payload){let temporary=`${path14}.${process.pid}.${randomUUID9()}.tmp`,handle=await open8(temporary,"wx",384);try{await handle.writeFile(payload),await handle.sync()}finally{await handle.close()}try{return await link(temporary,path14),!0}catch(error){if(error.code!=="EEXIST")throw error;return!1}finally{await rm5(temporary,{force:!0}).catch(()=>{})}}function leasesFilePath(runDirectory){return join46(runDirectory,"leases.json")}function leaseLockPath(runDirectory){return join46(runDirectory,"leases.lock")}async function withLeaseLock(runDirectory,operation,dependencies={}){let now=dependencies.now??(()=>new Date),isAlive=dependencies.isProcessAlive??defaultIsProcessAlive,sleep5=dependencies.sleep??defaultSleep,timeoutMs=dependencies.lockTimeoutMs??LEASE_LOCK_TIMEOUT_MS,staleMs=dependencies.lockStaleMs??LEASE_LOCK_STALE_MS,retryMs=dependencies.lockRetryMs??LEASE_LOCK_RETRY_MS,path14=leaseLockPath(runDirectory),deadline=now().getTime()+timeoutMs;await mkdir7(runDirectory,{recursive:!0});let payload=`${JSON.stringify({pid:process.pid,nonce:randomUUID9(),at:now().toISOString()})}
1331
+ `),await file.sync()}finally{await file.close()}}import{randomUUID as randomUUID8}from"node:crypto";import{stat as stat5}from"node:fs/promises";import{basename as basename12,isAbsolute as isAbsolute5,join as join45,resolve as resolve14}from"node:path";var WORKER_ROLES=["implementer","reviewer","tester","arena","explorer"];function isWorkerRole(value){return typeof value=="string"&&WORKER_ROLES.includes(value)}var MUTATION_TOOLS=new Set(["write","edit","apply_patch","multi_edit"]),ROLE_TOOLS={implementer:["read","grep","find","ls","bash","write","edit","claim_path","release_path"],reviewer:["read","grep","find","ls","bash","write_contract"],tester:["read","grep","find","ls","bash","write_contract"],arena:["read","grep","find","ls","bash","write","edit","claim_path","release_path"],explorer:["read","grep","find","ls","bash"]},TEST_SHELL_ROLES=new Set(["reviewer","tester"]),READ_ONLY_SHELL_ROLES=new Set(["explorer"]);function hasTestShellOnly(role){return TEST_SHELL_ROLES.has(role)}function hasReadOnlyShell(role){return READ_ONLY_SHELL_ROLES.has(role)}var ROLE_CONTRACT_FILE={reviewer:{file:"verdict.json",schema:"verdict.schema.json"},tester:{file:"evidence.json",schema:"evidence.schema.json"}},ROLE_RESULT_FILE={reviewer:"verdict.json",tester:"evidence.json",implementer:"candidate.json",arena:"candidate.json"};function resolveRoleTools(role,requested){let allowed=ROLE_TOOLS[role];if(requested===void 0)return[...allowed];let forbidden=requested.filter(tool=>!allowed.includes(tool));if(forbidden.length>0)throw new Error(`role ${role} may not hold ${forbidden.join(", ")}`);return[...new Set(requested)]}function isWriterToolSet(tools){return tools.some(tool=>MUTATION_TOOLS.has(tool))}var WORKER_DESCRIPTOR_ENV="KPI_WORKER_DESCRIPTOR",WorkerIdentityError=class extends Error{constructor(message){super(message),this.name="WorkerIdentityError"}};function mintCapabilityId(){return randomUUID8()}function mintWorkerDescriptor(options){let contract=ROLE_CONTRACT_FILE[options.role];return Object.freeze({agentId:options.agentId,jobId:options.jobId,role:options.role,runDirectory:resolve14(options.runDirectory),contractPath:contract?.file,tools:Object.freeze([...options.tools]),capabilityId:contract===void 0?void 0:options.capabilityId,qualityGates:hasTestShellOnly(options.role)?Object.freeze(normalizeGates(options.qualityGates)):void 0})}function normalizeGates(gates){let seen=new Set;for(let gate of gates??[])typeof gate=="string"&&gate.trim().length>0&&seen.add(gate.trim());return[...seen]}function descriptorEnv(descriptor){return{[WORKER_DESCRIPTOR_ENV]:JSON.stringify(descriptor)}}var RAW_DESCRIPTOR=process.env[WORKER_DESCRIPTOR_ENV];function rawWorkerDescriptor(env2){return env2===void 0?RAW_DESCRIPTOR:env2[WORKER_DESCRIPTOR_ENV]}function hasWorkerDescriptor(env2){let raw=rawWorkerDescriptor(env2);return typeof raw=="string"&&raw.trim().length>0}function parseDescriptor(raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new WorkerIdentityError(`${WORKER_DESCRIPTOR_ENV} is not valid JSON`)}if(!isJsonObject(parsed))throw new WorkerIdentityError(`${WORKER_DESCRIPTOR_ENV} is not an object`);let{agentId,jobId,role,runDirectory,contractPath,tools,capabilityId,qualityGates}=parsed;if(typeof agentId!="string"||agentId.trim().length===0)throw new WorkerIdentityError("worker descriptor has no agentId");if(typeof jobId!="string"||jobId.trim().length===0)throw new WorkerIdentityError("worker descriptor has no jobId");if(!isWorkerRole(role))throw new WorkerIdentityError(`worker descriptor has an unknown role: ${String(role)}`);if(typeof runDirectory!="string"||!isAbsolute5(runDirectory))throw new WorkerIdentityError("worker descriptor needs an absolute runDirectory");if(!agentId.startsWith(`${role}-`))throw new WorkerIdentityError(`worker descriptor agentId ${agentId} does not belong to role ${role}`);let declared=ROLE_CONTRACT_FILE[role]?.file;if(contractPath!==void 0&&contractPath!==declared)throw new WorkerIdentityError(`worker descriptor claims contract ${String(contractPath)}; role ${role} publishes ${declared??"nothing"}`);if(declared!==void 0&&(typeof capabilityId!="string"||capabilityId.trim().length===0))throw new WorkerIdentityError(`role ${role} publishes ${declared} and needs a capability id`);let allowed=ROLE_TOOLS[role],granted=(Array.isArray(tools)?tools.filter(tool=>typeof tool=="string"):[]).filter(tool=>allowed.includes(tool)),gates=hasTestShellOnly(role)?Object.freeze(normalizeGates(Array.isArray(qualityGates)?qualityGates:[])):void 0;return Object.freeze({agentId,jobId,role,runDirectory:resolve14(runDirectory),contractPath:declared,tools:Object.freeze(granted),capabilityId:declared===void 0?void 0:capabilityId,qualityGates:gates})}var validated=new Map;async function resolveWorkerIdentity(cwd,env2){let raw=rawWorkerDescriptor(env2);if(raw===void 0||raw.trim().length===0)return;let key=`${resolve14(cwd)}\0${raw}`,cached=validated.get(key);if(cached!==void 0)return cached;let descriptor=parseDescriptor(raw);if(basename12(descriptor.runDirectory)!==descriptor.jobId)throw new WorkerIdentityError(`worker descriptor run directory ${descriptor.runDirectory} is not job ${descriptor.jobId}`);let expected=resolve14(cwd,CONFIG_DIR_NAME,"runs",descriptor.jobId);if(expected!==descriptor.runDirectory)throw new WorkerIdentityError(`worker descriptor belongs to another project: expected ${expected}, got ${descriptor.runDirectory}`);let info=await stat5(descriptor.runDirectory).catch(()=>{});if(info===void 0||!info.isDirectory())throw new WorkerIdentityError(`worker descriptor run directory does not exist: ${descriptor.runDirectory}`);if(await readTaskForJob(cwd,descriptor.jobId).catch(()=>{})===void 0)throw new WorkerIdentityError(`worker descriptor names job ${descriptor.jobId}, which has no task.json`);let identity=Object.freeze({...descriptor,cwd:resolve14(cwd)});return validated.set(key,identity),identity}async function requireWorkerIdentity(cwd,env2){let identity=await resolveWorkerIdentity(cwd,env2);if(identity===void 0)throw new WorkerIdentityError("this tool belongs to a background K-\u03C0 worker; a parent session has no worker identity");return identity}function authorizeWorkerTool(identity,tool){if(!identity.tools.includes(tool))throw new WorkerIdentityError(`worker ${identity.agentId} (${identity.role}) does not hold ${tool}`)}import{randomUUID as randomUUID9}from"node:crypto";import{link,mkdir as mkdir7,open as open8,readFile as readFile14,rm as rm5,stat as stat6}from"node:fs/promises";import{join as join46}from"node:path";var LEASE_LOCK_TIMEOUT_MS=1e4,LEASE_LOCK_STALE_MS=3e4,LEASE_LOCK_RETRY_MS=5;function defaultIsProcessAlive(pid){if(!Number.isInteger(pid)||pid<=0)return!1;try{return process.kill(pid,0),!0}catch(error){return error.code==="EPERM"}}var defaultSleep=ms=>new Promise(resolvePromise=>setTimeout(resolvePromise,ms));function parseLockOwner(contents){try{let parsed=JSON.parse(contents);if(isJsonObject(parsed)&&typeof parsed.pid=="number"&&typeof parsed.nonce=="string"&&typeof parsed.at=="string")return{pid:parsed.pid,nonce:parsed.nonce,at:parsed.at}}catch{return}}async function acquireLock(path14,payload){let temporary=`${path14}.${process.pid}.${randomUUID9()}.tmp`,handle=await open8(temporary,"wx",384);try{await handle.writeFile(payload),await handle.sync()}finally{await handle.close()}try{return await link(temporary,path14),!0}catch(error){if(error.code!=="EEXIST")throw error;return!1}finally{await rm5(temporary,{force:!0}).catch(()=>{})}}function leasesFilePath(runDirectory){return join46(runDirectory,"leases.json")}function leaseLockPath(runDirectory){return join46(runDirectory,"leases.lock")}async function withLeaseLock(runDirectory,operation,dependencies={}){let now=dependencies.now??(()=>new Date),isAlive=dependencies.isProcessAlive??defaultIsProcessAlive,sleep5=dependencies.sleep??defaultSleep,timeoutMs=dependencies.lockTimeoutMs??LEASE_LOCK_TIMEOUT_MS,staleMs=dependencies.lockStaleMs??LEASE_LOCK_STALE_MS,retryMs=dependencies.lockRetryMs??LEASE_LOCK_RETRY_MS,path14=leaseLockPath(runDirectory),deadline=now().getTime()+timeoutMs;await mkdir7(runDirectory,{recursive:!0});let payload=`${JSON.stringify({pid:process.pid,nonce:randomUUID9(),at:now().toISOString()})}
1330
1332
  `;for(;!await acquireLock(path14,payload);){let existing=await readFile14(path14,"utf8").catch(()=>{});if(existing===void 0)continue;let holder=parseLockOwner(existing);if(holder!==void 0){if(isAlive(holder.pid)){if(now().getTime()>=deadline)throw new Error(`lease lock held by pid ${holder.pid} was not released within ${timeoutMs}ms`);await sleep5(retryMs);continue}await readFile14(path14,"utf8").catch(()=>{})===existing&&await rm5(path14,{force:!0}).catch(()=>{});continue}let info=await stat6(path14).catch(()=>{}),age=info===void 0?void 0:now().getTime()-info.mtimeMs;if(age!==void 0&&age>staleMs){await readFile14(path14,"utf8").catch(()=>{})===existing&&await rm5(path14,{force:!0}).catch(()=>{});continue}if(now().getTime()>=deadline)throw new Error(`lease lock is held by an unreadable owner and was not released within ${timeoutMs}ms`);await sleep5(retryMs)}try{return await operation()}finally{await readFile14(path14,"utf8").catch(()=>{})===payload&&await rm5(path14,{force:!0}).catch(()=>{})}}async function readLeasesFile(runDirectory,dependencies={}){let now=dependencies.now??(()=>new Date);try{let parsed=JSON.parse(await readFile14(leasesFilePath(runDirectory),"utf8"));if(!isJsonObject(parsed))return{};let leases={};for(let[path14,value]of Object.entries(parsed))isJsonObject(value)&&typeof value.agent_id=="string"&&typeof value.pid=="number"&&(leases[path14]={agent_id:value.agent_id,pid:value.pid,at:typeof value.at=="string"?value.at:now().toISOString()});return leases}catch(error){if(error.code==="ENOENT")return{};throw error}}async function writeLeasesFile(runDirectory,leases){await atomicWrite(leasesFilePath(runDirectory),`${JSON.stringify(leases,null,2)}
1331
1333
  `)}async function claimLease(runDirectory,request2,dependencies={}){let now=dependencies.now??(()=>new Date),isAlive=dependencies.isProcessAlive??defaultIsProcessAlive;return withLeaseLock(runDirectory,async()=>{let leases=await readLeasesFile(runDirectory,dependencies),holder=leases[request2.key];if(holder!==void 0&&holder.agent_id!==request2.agentId){if(isAlive(holder.pid))throw new Error(`Path already claimed by ${holder.agent_id}: ${request2.key}`);delete leases[request2.key]}let lease={agent_id:request2.agentId,pid:request2.pid,at:now().toISOString()};return leases[request2.key]=lease,await writeLeasesFile(runDirectory,leases),lease},dependencies)}async function releaseLease(runDirectory,request2,dependencies={}){return withLeaseLock(runDirectory,async()=>{let leases=await readLeasesFile(runDirectory,dependencies);return leases[request2.key]?.agent_id!==request2.agentId?!1:(delete leases[request2.key],await writeLeasesFile(runDirectory,leases),!0)},dependencies)}async function releaseAllLeasesFor(runDirectory,agentId,dependencies={}){await withLeaseLock(runDirectory,async()=>{let leases=await readLeasesFile(runDirectory,dependencies),changed=!1;for(let[key,lease]of Object.entries(leases))lease.agent_id===agentId&&(delete leases[key],changed=!0);changed&&await writeLeasesFile(runDirectory,leases)},dependencies)}async function releaseDeadLeases(runDirectory,dependencies={}){let isAlive=dependencies.isProcessAlive??defaultIsProcessAlive;await withLeaseLock(runDirectory,async()=>{let leases=await readLeasesFile(runDirectory,dependencies),changed=!1;for(let[key,lease]of Object.entries(leases))isAlive(lease.pid)||(delete leases[key],changed=!0);changed&&await writeLeasesFile(runDirectory,leases)},dependencies)}var provider=()=>0;function setLiveWorkerCountProvider(next){provider=next}function liveWorkerCount(){return provider()}import{randomUUID as randomUUID12}from"node:crypto";import{mkdir as mkdir8,open as open9,readFile as readFile17}from"node:fs/promises";import{join as join50}from"node:path";import{readFile as readFile15}from"node:fs/promises";import{join as join47}from"node:path";var LADDER_RUNGS=["yagni","reuse","standard-library","native-platform","existing-dependency","one-liner","minimum-code"],RUNG_SET=new Set(LADDER_RUNGS),FUNCTION_PATTERN=/\b(?:export\s+)?(?:async\s+)?function\b|\b(?:export\s+)?const\s+\w+\s*=\s*(?:async\s*)?\(/u,CLASS_PATTERN=/\b(?:export\s+)?(?:abstract\s+)?class\b/u,ABSTRACTION_PATTERN=/\b(?:export\s+)?(?:interface|type|abstract\s+class|enum)\b|\bextends\b|\bimplements\b/u;function meaningfulText(value,field2){if(typeof value!="string")throw new Error(`candidate.json.ladder.${field2} must be a non-empty string`);let trimmed=value.trim();if(trimmed.length===0)throw new Error(`candidate.json.ladder.${field2} must be a non-empty string`);if(/^(n\/?a|none|todo|tbd|\.+|-)$/i.test(trimmed))throw new Error(`candidate.json.ladder.${field2} must name a real decision, not ${JSON.stringify(trimmed)}`);return trimmed}function normalizeRung(raw){if(typeof raw!="string")throw new Error("candidate.json.ladder must name a known rung");let rung=raw.trim().toLowerCase().replace(/[_\s]+/g,"-");if(!RUNG_SET.has(rung))throw new Error(`unknown ladder rung ${JSON.stringify(raw)}; expected one of ${LADDER_RUNGS.join(", ")}`);return rung}function parseLadderDecision(candidate){if(candidate===null||typeof candidate!="object"||Array.isArray(candidate))throw new Error("candidate.json.ladder is required before implementation");let root=candidate,ladderRaw=root.ladder,usedRaw=root.used,skippedRaw=root.skipped;if(ladderRaw!==void 0&&typeof ladderRaw=="object"&&ladderRaw!==null&&!Array.isArray(ladderRaw)){let nested=ladderRaw;ladderRaw=nested.ladder??nested.rung??nested.name,usedRaw=nested.used??usedRaw,skippedRaw=nested.skipped??skippedRaw}if(ladderRaw===void 0)throw new Error("candidate.json.ladder is required before implementation");return{ladder:normalizeRung(ladderRaw),used:meaningfulText(usedRaw,"used"),skipped:meaningfulText(skippedRaw,"skipped")}}function stripStringsAndComments(source2){return source2.replace(/\/\*[\s\S]*?\*\//g," ").replace(/(^|[^:])\/\/.*$/gm,"$1").replace(/(['"`])(?:\\.|(?!\1)[\s\S])*\1/g,'""')}function splitLines2(text){let normalized=text.replace(/\r\n/g,`
1332
1334
  `);if(normalized.length===0)return[];let parts=normalized.split(`
@@ -1338,29 +1340,27 @@ Code: ${event.userCode}`;let links=event.type==="info"?event.links??[]:[];return
1338
1340
  `);if(newlineIndex===-1){if(buffer.length+rest.length>limit){options.onReject({kind:"oversized",characters:buffer.length+rest.length}),buffer="",discarding=!0;return}buffer+=rest;return}let line=buffer+rest.slice(0,newlineIndex);if(buffer="",rest=rest.slice(newlineIndex+1),line.length>limit){options.onReject({kind:"oversized",characters:line.length});continue}if(line.endsWith("\r")){options.onReject({kind:"carriage-return"});continue}options.onLine(line)}},onData=chunk=>{consume(typeof chunk=="string"?chunk:decoder.write(chunk))},onEnd=()=>{if(consume(decoder.end()),discarding){discarding=!1,buffer="";return}buffer.length>0&&(options.onReject({kind:"unterminated",characters:buffer.length}),buffer="")};return stream2.on("data",onData),stream2.on("end",onEnd),()=>{stream2.off("data",onData),stream2.off("end",onEnd)}}async function writeRecordBounded(stream2,record,options={}){let limit=options.maxRecordCharacters??MAX_RECORD_CHARACTERS;if(record.length>limit)throw new Error(`outbound record is ${record.length} characters, over the ${limit} limit`);if(stream2.writableEnded||stream2.destroyed)throw new Error("worker stdin is closed");if(stream2.write(record))return;let drainTimeoutMs=options.drainTimeoutMs??MAX_DRAIN_WAIT_MS;await new Promise((resolvePromise,reject)=>{let settle=error=>{clearTimeout(timer),stream2.off("drain",onDrain),stream2.off("error",onError),stream2.off("close",onClose),error===void 0?resolvePromise():reject(error)},onDrain=()=>settle(),onError=error=>settle(error),onClose=()=>settle(new Error("worker stdin closed before the record was accepted")),timer=setTimeout(()=>settle(new Error(`worker did not accept a record within ${drainTimeoutMs}ms`)),drainTimeoutMs);stream2.once("drain",onDrain),stream2.once("error",onError),stream2.once("close",onClose)})}var WORKER_STARTUP_TIMEOUT_MS=3e4,WORKER_ACCEPTANCE_TIMEOUT_MS=3e4,WORKER_RESULT_TIMEOUT_MS=6e5,WORKER_SHUTDOWN_TIMEOUT_MS=5e3,MAX_DIAGNOSTIC_CHARACTERS=1e4;function clamp2(value){return value.length<=MAX_DIAGNOSTIC_CHARACTERS?value:value.slice(0,MAX_DIAGNOSTIC_CHARACTERS)}function scrub(value){return clamp2(redactJson(value))}function assistantMessageText(message){if(!isJsonObject(message)||message.role!=="assistant"||!Array.isArray(message.content))return;let parts=[];for(let entry of message.content)isJsonObject(entry)&&entry.type==="text"&&typeof entry.text=="string"&&parts.push(entry.text);return parts.length===0?void 0:parts.join("")}var WorkerProtocol=class{constructor(streams){if(this.pending=new Map,this.settledWaiters=[],this.diagnostics={stderr:"",rejectedRecords:0,notes:[]},this.closed=!1,this.streamingText="",this.settleCount=0,this.stdin=streams.stdin,this.drainTimeoutMs=streams.drainTimeoutMs??MAX_DRAIN_WAIT_MS,this.detachStdout=attachBoundedJsonlReader(streams.stdout,{onLine:line=>this.handleLine(line),onReject:rejection=>{this.diagnostics.rejectedRecords+=1,this.note(rejection.kind==="oversized"?`refused a ${rejection.characters} character record`:rejection.kind==="carriage-return"?"refused a record terminated with CRLF":`refused a ${rejection.characters} character record with no newline at end of stream`)}}),this.detachStderr=()=>{},streams.stderr!==void 0){let onData=chunk=>{let text=typeof chunk=="string"?chunk:chunk.toString("utf8");this.diagnostics.stderr=scrub(this.diagnostics.stderr+text)};streams.stderr.on("data",onData),this.detachStderr=()=>streams.stderr?.off("data",onData)}}get snapshot(){return{...this.diagnostics,notes:[...this.diagnostics.notes]}}get settles(){return this.settleCount}note(message){this.diagnostics.notes.length<32&&this.diagnostics.notes.push(clamp2(message))}handleLine(line){if(line.length===0)return;let parsed;try{parsed=JSON.parse(line)}catch{this.diagnostics.rejectedRecords+=1,this.note("refused an unparseable record");return}if(!isJsonObject(parsed)){this.diagnostics.rejectedRecords+=1,this.note("refused a record that is not an object");return}let record=parsed;if(record.type==="response"){let id=typeof record.id=="string"?record.id:void 0;if(id===void 0){this.note("refused a response with no id"),this.diagnostics.rejectedRecords+=1;return}let waiter=this.pending.get(id);if(waiter===void 0){this.note(`late response for ${id}`);return}this.pending.delete(id),clearTimeout(waiter.timer),waiter.resolve(record);return}if(record.type==="agent_settled"){this.settleCount+=1;let waiters=this.settledWaiters.splice(0,this.settledWaiters.length);for(let waiter of waiters)waiter.resolve();return}if(record.type==="message_update"){let event=record.assistantMessageEvent;isJsonObject(event)&&(event.type==="text_delta"&&typeof event.delta=="string"?(this.streamingText=clamp2(this.streamingText+event.delta),this.diagnostics.lastAssistantText=scrub(this.streamingText)):event.type==="text_end"&&typeof event.content=="string"?(this.streamingText=clamp2(event.content),this.diagnostics.lastAssistantText=scrub(this.streamingText)):event.type==="start"&&(this.streamingText=""));return}if(record.type==="message_end"){let text=assistantMessageText(record.message);text!==void 0&&(this.diagnostics.lastAssistantText=scrub(text)),this.streamingText=""}}async write(record){if(this.closed)throw this.closeReason??new Error("worker protocol is closed");await writeRecordBounded(this.stdin,serializeJsonLine(record),{drainTimeoutMs:this.drainTimeoutMs})}async request(command,timeoutMs=WORKER_ACCEPTANCE_TIMEOUT_MS){let id=typeof command.id=="string"?command.id:randomUUID10(),record={...command,id},response=new Promise((resolve26,reject)=>{let timer=setTimeout(()=>{this.pending.delete(id),reject(new Error(`worker did not answer ${String(command.type)} within ${timeoutMs}ms`))},timeoutMs);this.pending.set(id,{resolve:resolve26,reject,timer})});try{await this.write(record)}catch(error){let waiter=this.pending.get(id);throw waiter!==void 0&&(this.pending.delete(id),clearTimeout(waiter.timer)),error instanceof Error?error:new Error(String(error))}return response}async send(command){await this.write({...command,id:typeof command.id=="string"?command.id:randomUUID10()})}async prompt(message){let response=await this.request({type:"prompt",message});assertAccepted(response,"prompt")}async deliver(message,deliverAs){let response=await this.request(deliverAs==="steer"?{type:"steer",message}:{type:"follow_up",message});assertAccepted(response,deliverAs==="steer"?"steer":"follow_up")}waitForSettled(timeoutMs=WORKER_RESULT_TIMEOUT_MS,afterCount){if(this.closed)return Promise.reject(this.closeReason??new Error("worker protocol closed"));let baseline=afterCount??this.settleCount;return this.settleCount>baseline?Promise.resolve():new Promise((resolve26,reject)=>{let entry={resolve:()=>{clearTimeout(timer),resolve26()},reject:error=>{clearTimeout(timer),reject(error)}},timer=setTimeout(()=>{let index3=this.settledWaiters.indexOf(entry);index3>=0&&this.settledWaiters.splice(index3,1),reject(new Error(`worker did not settle within ${timeoutMs}ms`))},timeoutMs);this.settledWaiters.push(entry)})}async cancel(){await this.request({type:"clear_queue"}).catch(()=>{}),await this.request({type:"abort"}).catch(()=>{})}close(reason){this.closed=!0,this.closeReason=reason,this.detachStdout(),this.detachStderr();for(let[,waiter]of this.pending)clearTimeout(waiter.timer),waiter.reject(reason??new Error("worker protocol closed"));this.pending.clear();let settleWaiters=this.settledWaiters.splice(0,this.settledWaiters.length),closed=reason??new Error("worker protocol closed");for(let waiter of settleWaiters)waiter.reject(closed)}};function assertAccepted(response,command){if(response.success===!0)return;let reason=typeof response.error=="string"?response.error:"worker rejected the command";throw new Error(`${command} was not accepted: ${reason}`)}var CLI_ENTRY_NAMES=new Set(["cli.js","cli.mjs","cli.cjs","cli.ts","kpi","k-pi"]);async function isFile(path14){return(await stat7(path14).catch(()=>{}))?.isFile()===!0}function ancestors(from){let root=parse5(from).root,found=[],current=from;for(;;){if(found.push(current),current===root)return found;let next=dirname26(current);if(next===current)return found;current=next}}async function resolveCliPath(options={}){let self=fileURLToPath6(options.moduleUrl??import.meta.url),candidates=[];CLI_ENTRY_NAMES.has(basename13(self))&&candidates.push(self);let entry=(options.argv??process.argv)[1];if(typeof entry=="string"&&entry.length>0){let resolved=resolve15(entry);CLI_ENTRY_NAMES.has(basename13(resolved))&&candidates.push(resolved)}for(let ancestor of ancestors(dirname26(self)))candidates.push(join48(ancestor,"dist","bundle","cli.js"),join48(ancestor,"src","bun","cli.ts"));for(let candidate of candidates)if(await isFile(candidate))return candidate;throw new Error("Cannot find the K-\u03C0 CLI entry to launch a worker")}var launchWorkerProcess=async request2=>{let cliPath=request2.cliPath??await resolveCliPath();if(!isAbsolute6(cliPath))throw new Error(`worker CLI path must be absolute: ${cliPath}`);let execPath=request2.execPath??process.execPath,argv=[cliPath,"--mode","rpc","--session",request2.sessionPath,"--session-dir",request2.sessionDirectory,"--tools",[...request2.tools].join(",")];request2.model!==void 0&&argv.push("--model",request2.model);let child=spawn7(execPath,argv,{cwd:request2.cwd,stdio:["pipe","pipe","pipe"],shell:!1,env:{...process.env,...descriptorEnv(request2.descriptor)}}),startupTimeoutMs=request2.startupTimeoutMs??WORKER_STARTUP_TIMEOUT_MS;if(await new Promise((resolvePromise,reject)=>{let timer=setTimeout(()=>{child.kill("SIGKILL"),reject(new Error(`worker did not start within ${startupTimeoutMs}ms`))},startupTimeoutMs);child.once("spawn",()=>{clearTimeout(timer),resolvePromise()}),child.once("error",error=>{clearTimeout(timer),reject(new Error(`worker failed to start: ${error.message}`))})}),child.stdin===null||child.stdout===null)throw child.kill("SIGKILL"),new Error("worker was started without piped stdio");let protocol=new WorkerProtocol({stdin:child.stdin,stdout:child.stdout,stderr:child.stderr??void 0}),exited=child.exitCode!==null||child.signalCode!==null;return child.once("exit",()=>{exited=!0,protocol.close()}),{pid:child.pid??-1,argv,protocol,process:child,isAlive:()=>!exited,stop:async()=>{if(exited){protocol.close();return}await protocol.cancel().catch(()=>{}),protocol.close(),child.stdin?.end(),await new Promise(resolvePromise=>{let timer=setTimeout(()=>resolvePromise(!1),WORKER_SHUTDOWN_TIMEOUT_MS);child.once("exit",()=>{clearTimeout(timer),resolvePromise(!0)}),child.kill("SIGTERM")})||child.kill("SIGKILL")}}};import{createHash as createHash5,randomUUID as randomUUID11}from"node:crypto";import{readFile as readFile16,realpath as realpath3}from"node:fs/promises";import{basename as basename14,dirname as dirname27,isAbsolute as isAbsolute7,join as join49,resolve as resolve16}from"node:path";import{isDeepStrictEqual}from"node:util";var DATE_TIME_PATTERN=/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})$/u;function resolvePointer(ref,root){if(ref==="#")return root;if(!ref.startsWith("#/"))return;let current=root;for(let token of ref.slice(2).split("/")){if(typeof current!="object"||current===null)return;let segment2=token.replaceAll("~1","/").replaceAll("~0","~");current=current[segment2]}return current}function resolveSchema(schema,root){let current=schema,seen=new Set;for(;current.$ref!==void 0;){if(seen.has(current.$ref))return`has a cyclic $ref ${current.$ref}`;seen.add(current.$ref);let target=resolvePointer(current.$ref,root);if(target===void 0)return`references unknown schema ${current.$ref}`;current=target}return current}function valueType(value){return value===null?"null":Array.isArray(value)?"array":typeof value}function matchesType(value,expected){return expected==="integer"?typeof value=="number"&&Number.isInteger(value):expected==="number"?typeof value=="number"&&Number.isFinite(value):expected==="object"?typeof value=="object"&&value!==null&&!Array.isArray(value):valueType(value)===expected}function validateJsonSchema(value,schema,path14="$"){return validate2(value,schema,path14,schema)}function validate2(value,schema,path14,root){let resolved=resolveSchema(schema,root);if(typeof resolved=="string")return[`${path14} ${resolved}`];let errors=[];if(resolved.type!==void 0&&!matchesType(value,resolved.type))return[`${path14} must be ${resolved.type}`];if(resolved.enum!==void 0&&!resolved.enum.some(candidate=>isDeepStrictEqual(candidate,value))&&errors.push(`${path14} must be one of ${resolved.enum.join(", ")}`),"const"in resolved&&!isDeepStrictEqual(resolved.const,value)&&errors.push(`${path14} must equal ${JSON.stringify(resolved.const)}`),resolved.oneOf!==void 0){let branches=resolved.oneOf.map(branch=>validate2(value,branch,path14,root)),matched=branches.filter(branch=>branch.length===0).length;if(matched===0){let closest=branches.reduce((best,branch)=>branch.length<best.length?branch:best,branches[0]??[]);errors.push(`${path14} must match one of ${branches.length} variants`,...closest)}else matched>1&&errors.push(`${path14} must match exactly one variant, matched ${matched}`)}if(typeof value=="string"&&(resolved.minLength!==void 0&&value.length<resolved.minLength&&errors.push(`${path14} must have length >= ${resolved.minLength}`),resolved.maxLength!==void 0&&value.length>resolved.maxLength&&errors.push(`${path14} must have length <= ${resolved.maxLength}`),resolved.pattern!==void 0&&!new RegExp(resolved.pattern,"u").test(value)&&errors.push(`${path14} must match ${resolved.pattern}`),resolved.format==="date-time"&&!(DATE_TIME_PATTERN.test(value)&&!Number.isNaN(Date.parse(value)))&&errors.push(`${path14} must be a date-time`)),typeof value=="number"&&resolved.minimum!==void 0&&value<resolved.minimum&&errors.push(`${path14} must be >= ${resolved.minimum}`),Array.isArray(value)&&(resolved.minItems!==void 0&&value.length<resolved.minItems&&errors.push(`${path14} must have at least ${resolved.minItems} items`),resolved.items!==void 0))for(let[index3,item]of value.entries())errors.push(...validate2(item,resolved.items,`${path14}[${index3}]`,root));if(typeof value=="object"&&value!==null&&!Array.isArray(value)){let record=value;for(let required of resolved.required??[])required in record||errors.push(`${path14}.${required} is required`);let properties=resolved.properties??{};for(let[key,child]of Object.entries(record)){let childSchema=properties[key];childSchema!==void 0?errors.push(...validate2(child,childSchema,`${path14}.${key}`,root)):resolved.additionalProperties===!1&&errors.push(`${path14}.${key} is not allowed`)}}return errors}var ContractWriteError=class extends Error{constructor(message){super(message),this.name="ContractWriteError"}};function receiptPathFor(runDirectory,agentId){return join49(runDirectory,"agents",`${agentId}.receipt.json`)}function mintContractPin(options){let declared=ROLE_CONTRACT_FILE[options.role];if(declared!==void 0)return{agentId:options.agentId,jobId:options.jobId,role:options.role,capabilityId:options.capabilityId,absolutePath:resolve16(options.runDirectory,declared.file),declaredPath:declared.file,schema:declared.schema,receiptPath:receiptPathFor(options.runDirectory,options.agentId)}}async function loadSchema(name){return JSON.parse(await readFile16(join49(getKpiResourceDir(),"schemas",name),"utf8"))}function hashContractBytes(bytes){return createHash5("sha256").update(bytes).digest("hex")}async function resolvesToPin(requested,pin){let absolute=isAbsolute7(requested)?resolve16(requested):resolve16(dirname27(pin.absolutePath),requested),[realParent,realPinParent]=await Promise.all([realpath3(dirname27(absolute)).catch(()=>{}),realpath3(dirname27(pin.absolutePath)).catch(()=>{})]);if(realParent===void 0||realPinParent===void 0||realParent!==realPinParent||basename14(absolute)!==basename14(pin.absolutePath))return!1;let realFile=await realpath3(absolute).catch(()=>{});return!(realFile!==void 0&&realFile!==join49(realPinParent,basename14(pin.absolutePath)))}async function writeContract(options){let{pin}=options;if(pin===void 0)throw new ContractWriteError(`role ${options.role} has no pinned contract capability`);if(pin.agentId!==options.agentId||pin.jobId!==options.jobId||pin.role!==options.role)throw new ContractWriteError(`contract capability is pinned to ${pin.role} ${pin.agentId} in job ${pin.jobId}, not ${options.role} ${options.agentId} in job ${options.jobId}`);if(typeof options.requestedPath!="string"||options.requestedPath.trim().length===0)throw new ContractWriteError("write_contract requires a path");if(!await resolvesToPin(options.requestedPath,pin))throw new ContractWriteError(`write_contract may only write ${pin.declaredPath} for ${pin.role}; refused ${options.requestedPath}`);if(typeof options.payload!="object"||options.payload===null||Array.isArray(options.payload))throw new ContractWriteError("write_contract takes the parsed contract object, not a diff or prose");let schema=await(options.loadSchemaImpl??loadSchema)(pin.schema),errors=validateJsonSchema(options.payload,schema);if(errors.length>0)throw new ContractWriteError(`${pin.declaredPath} does not satisfy ${pin.schema}: ${errors.join("; ")}`);let bytes=`${JSON.stringify(options.payload,null,2)}
1339
1341
  `,receipt={publication_id:(options.newPublicationId??randomUUID11)(),capability_id:pin.capabilityId,agent_id:pin.agentId,job_id:pin.jobId,role:pin.role,declared_path:pin.declaredPath,content_sha256:hashContractBytes(bytes),published_at:(options.now??(()=>new Date))().toISOString()};return await atomicWrite(pin.absolutePath,bytes),await atomicWrite(pin.receiptPath,`${JSON.stringify(receipt,null,2)}
1340
1342
  `),{path:pin.declaredPath,receipt}}async function readPublicationReceipt(path14){let source2=await readFile16(path14,"utf8").catch(error=>{if(error.code!=="ENOENT")throw error});if(source2===void 0)return;let parsed;try{parsed=JSON.parse(source2)}catch{return}if(!isJsonObject(parsed))return;let fields=["publication_id","capability_id","agent_id","job_id","role","declared_path","content_sha256","published_at"];for(let field2 of fields)if(typeof parsed[field2]!="string"||parsed[field2].length===0)return;return parsed}function describeRejection(rejection){switch(rejection.kind){case"no-receipt":return"no publication receipt: the contract file was not published through write_contract";case"stale-receipt":return`receipt ${rejection.publicationId} is the one that was already there before this delivery`;case"wrong-capability":return"receipt was issued to a different agent or capability";case"wrong-path":return`receipt declares ${rejection.declaredPath}, not this role's contract`;case"missing-contract":return"receipt exists but the contract file does not";case"hash-mismatch":return"receipt hash does not match the contract bytes on disk";case"malformed-contract":return"contract file is not parseable JSON";case"invalid-contract":return`contract does not satisfy its schema: ${rejection.errors.join("; ")}`}}async function evaluatePublication(options){let{pin}=options,receipt=await readPublicationReceipt(pin.receiptPath);if(receipt===void 0)return{kind:"rejected",rejection:{kind:"no-receipt"}};if(receipt.publication_id===options.baselinePublicationId)return{kind:"rejected",rejection:{kind:"stale-receipt",publicationId:receipt.publication_id}};if(receipt.agent_id!==pin.agentId||receipt.capability_id!==pin.capabilityId)return{kind:"rejected",rejection:{kind:"wrong-capability"}};if(receipt.declared_path!==pin.declaredPath)return{kind:"rejected",rejection:{kind:"wrong-path",declaredPath:receipt.declared_path}};let bytes=await readFile16(pin.absolutePath,"utf8").catch(error=>{if(error.code!=="ENOENT")throw error});if(bytes===void 0)return{kind:"rejected",rejection:{kind:"missing-contract"}};if(hashContractBytes(bytes)!==receipt.content_sha256)return{kind:"rejected",rejection:{kind:"hash-mismatch"}};let document;try{document=JSON.parse(bytes)}catch{return{kind:"rejected",rejection:{kind:"malformed-contract"}}}if(!isJsonObject(document))return{kind:"rejected",rejection:{kind:"malformed-contract"}};let schema=await(options.loadSchemaImpl??loadSchema)(pin.schema),errors=validateJsonSchema(document,schema);return errors.length>0?{kind:"rejected",rejection:{kind:"invalid-contract",errors}}:{kind:"accepted",receipt,document}}var MAX_LIVE_WORKERS=2,MAX_LIVE_WRITERS=1,CONTRACT_WAIT_TIMEOUT_MS=12e4,STOP_GRACE_TIMEOUT_MS=6e4,STOP_MESSAGE="stop: publish your result file, then exit",CONTRACT_POLL_INTERVAL_MS=50;function createWorkerAdmission(limits={}){let maxWorkers=limits.maxWorkers??MAX_LIVE_WORKERS,maxWriters=limits.maxWriters??MAX_LIVE_WRITERS,slots=new Map,queue=Promise.resolve(),serialize2=operation=>{let result=queue.then(operation,operation);return queue=result.then(()=>{},()=>{}),result};return{async acquire(slot){return serialize2(()=>{if(slots.has(slot.key))throw new Error(`admission key already held: ${slot.key}`);if(slots.size>=maxWorkers)throw new Error(`Background worker limit is ${maxWorkers}`);if(slot.isWriter){let writers=0;for(let held of slots.values())held.isWriter&&(writers+=1);if(writers>=maxWriters)throw new Error("A writer worker is already live")}slots.set(slot.key,{isWriter:slot.isWriter});let released=!1;return()=>{released||(released=!0,slots.delete(slot.key))}})},counts(){let writers=0;for(let held of slots.values())held.isWriter&&(writers+=1);return{workers:slots.size,writers}}}}function admissionDenialReason(error){let message=error instanceof Error?error.message:String(error);return message.startsWith("A writer worker is already live")?"writer-live":message.startsWith("admission key already held")?"admission-held":"worker-limit"}var processWorkerAdmission=createWorkerAdmission(),BackgroundBus=class{constructor(cwd,runDirectory,jobId,dependencies={}){this.workers=new Map,this.queue=Promise.resolve(),this.closing=!1,this.cwd=cwd,this.runDirectory=runDirectory,this.jobId=jobId,this.agentsDirectory=join50(runDirectory,"agents"),this.busPath=join50(runDirectory,"bus.jsonl"),this.eventsPath=join50(runDirectory,"events.jsonl"),this.launcher=dependencies.launcher??launchWorkerProcess,this.now=dependencies.now??(()=>new Date),this.isProcessAlive=dependencies.isProcessAlive??defaultIsProcessAlive,this.sleep=dependencies.sleep??(ms=>new Promise(resolvePromise=>setTimeout(resolvePromise,ms))),this.dependencies=dependencies,this.admission=dependencies.admission??processWorkerAdmission}get leaseDependencies(){return{now:this.now,isProcessAlive:this.isProcessAlive,sleep:this.sleep,lockTimeoutMs:this.dependencies.lockTimeoutMs,lockStaleMs:this.dependencies.lockStaleMs,lockRetryMs:this.dependencies.lockRetryMs}}serialize(operation){let result=this.queue.then(operation,operation);return this.queue=result.then(()=>{},()=>{}),result}async logSpawned(payload){let ts=this.now().toISOString();await appendEvent(this.eventsPath,{ts,type:"agent.spawned",job_id:this.jobId,round:0,node:"bus",agent_id:payload.agent_id,role:payload.role,pid:payload.pid,session_path:payload.session_path}),await this.appendBus({ts,type:"agent.spawned",job_id:this.jobId,...payload})}async logDenied(payload){let ts=this.now().toISOString();await appendEvent(this.eventsPath,{ts,type:"agent.denied",job_id:this.jobId,round:0,node:"bus",reason:payload.reason,...payload.role===void 0?{}:{role:payload.role},...payload.agent_id===void 0?{}:{agent_id:payload.agent_id},...payload.key===void 0?{}:{key:payload.key},...payload.holder===void 0?{}:{holder:payload.holder},...payload.limit===void 0?{}:{limit:payload.limit}}),await this.appendBus({ts,type:"agent.denied",job_id:this.jobId,...payload})}async logMessage(payload){let ts=this.now().toISOString();await appendEvent(this.eventsPath,{ts,type:"agent.message",job_id:this.jobId,round:0,node:"bus",agent_id:payload.agent_id,deliver_as:payload.deliver_as,expect:payload.expect}),await this.appendBus({ts,type:"agent.message",job_id:this.jobId,...payload})}async appendBus(record){await mkdir8(this.runDirectory,{recursive:!0});let file=await open9(this.busPath,"a",384);try{await file.writeFile(`${JSON.stringify(record)}
1341
- `),await file.sync()}finally{await file.close()}}async reapUnlocked(){for(let[agentId,worker]of[...this.workers])worker.launch.isAlive()&&this.isProcessAlive(worker.pid)||(this.workers.delete(agentId),worker.releaseAdmission(),worker.launch.protocol.close());await releaseDeadLeases(this.runDirectory,this.leaseDependencies)}async reap(){await this.serialize(()=>this.reapUnlocked())}get live(){return this.workers.size}countLiveProcesses(){let count=0;for(let worker of this.workers.values())worker.launch.isAlive()&&this.isProcessAlive(worker.pid)&&(count+=1);return count}hasLiveWriter(){for(let worker of this.workers.values())if(worker.isWriter&&worker.launch.isAlive()&&this.isProcessAlive(worker.pid))return!0;return!1}async spawn(options){return this.serialize(async()=>{if(this.closing)throw new Error("this bus is shutting down and starts no new workers");await this.reapUnlocked();let tools=resolveRoleTools(options.role,options.tools),isWriter=isWriterToolSet(tools),agentId=`${options.role}-${(this.dependencies.newAgentSuffix??randomUUID12)()}`,releaseAdmission;try{releaseAdmission=await this.admission.acquire({key:`${this.jobId}:${agentId}`,isWriter})}catch(error){throw await this.logDenied({reason:admissionDenialReason(error),role:options.role,agent_id:agentId,limit:this.admission.counts().workers}).catch(()=>{}),error}let admissionHeld=!0,returnAdmission=()=>{admissionHeld&&(admissionHeld=!1,releaseAdmission())};try{let capabilityId=(this.dependencies.newCapabilityId??mintCapabilityId)(),sessionDirectory=this.agentsDirectory,sessionPath=join50(sessionDirectory,`${agentId}.jsonl`),task=await readTaskForJob(this.cwd,this.jobId).catch(()=>{}),descriptor=mintWorkerDescriptor({agentId,jobId:this.jobId,role:options.role,runDirectory:this.runDirectory,tools,capabilityId,qualityGates:task?.quality_gates}),contractPin=mintContractPin({agentId,jobId:this.jobId,role:options.role,runDirectory:this.runDirectory,capabilityId});await mkdir8(sessionDirectory,{recursive:!0}),await(await open9(sessionPath,"a",384)).close();let launch=await this.launcher({cwd:this.cwd,sessionPath,sessionDirectory,tools,model:options.model,descriptor,cliPath:this.dependencies.cliPath,execPath:this.dependencies.execPath,startupTimeoutMs:this.dependencies.startupTimeoutMs}),settleTimeout=this.dependencies.contractWaitTimeoutMs??WORKER_RESULT_TIMEOUT_MS,initialSettlement=launch.protocol.waitForSettled(settleTimeout,launch.protocol.settles);initialSettlement.catch(()=>{});let record={agentId,role:options.role,pid:launch.pid,sessionPath,sessionDirectory,tools,isWriter,contractPin,descriptor,launch,spawnedAt:this.now().toISOString(),lastEvent:"agent.spawned",initialSettlement,releaseAdmission:returnAdmission};this.workers.set(agentId,record);try{await this.logSpawned({agent_id:agentId,role:options.role,pid:launch.pid,tools:[...tools],session_path:sessionPath}),await launch.protocol.prompt(options.prompt)}catch(error){throw this.workers.delete(agentId),returnAdmission(),await launch.stop().catch(()=>{}),error}return record}catch(error){throw returnAdmission(),error}})}get(agentId){return this.workers.get(agentId)}list(){return[...this.workers.values()]}async status(){return this.serialize(async()=>(await this.reapUnlocked(),[...this.workers.values()].map(worker=>({agent_id:worker.agentId,role:worker.role,pid:worker.pid,alive:worker.launch.isAlive()&&this.isProcessAlive(worker.pid),is_writer:worker.isWriter,tools:[...worker.tools],session_path:worker.sessionPath,last_event:worker.lastEvent,contract_path:worker.contractPin?.declaredPath,diagnostics:worker.launch.protocol.snapshot}))))}async communicate(options){let deliverAs=options.deliverAs??"followUp",expect=options.expect??"none",worker=await this.serialize(async()=>{await this.reapUnlocked();let found=this.workers.get(options.agentId);if(found===void 0)throw new Error(`Unknown or stopped worker: ${options.agentId}`);return found.lastEvent="agent.message",await this.logMessage({agent_id:options.agentId,role:found.role,deliver_as:deliverAs,expect}),found});if(expect==="none")return await worker.launch.protocol.send(deliverAs==="steer"?{type:"steer",message:options.message}:{type:"follow_up",message:options.message}),{accepted:!1};if(expect==="ack")return await worker.launch.protocol.deliver(options.message,deliverAs),{accepted:!0};let resultFile=ROLE_RESULT_FILE[worker.role];if(resultFile===void 0)throw new Error(`role ${worker.role} produces no result file, so there is nothing to wait for`);let pin=worker.contractPin,limit=options.timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,baselineReceipt=pin===void 0?void 0:await readPublicationReceipt(pin.receiptPath),baselineBytes=pin===void 0?await this.readResultBytes(resultFile):void 0,settled=worker.launch.protocol.waitForSettled(limit);try{await worker.launch.protocol.deliver(options.message,deliverAs)}catch(error){throw settled.catch(()=>{}),error}if(await settled,pin!==void 0){let outcome=await this.waitForPublication(pin,baselineReceipt?.publication_id,limit);return{accepted:!0,contractPath:outcome.receipt.declared_path,publicationId:outcome.receipt.publication_id}}let written=await this.waitForWriterResult(resultFile,baselineBytes,limit);return{accepted:!0,contractPath:resultFile,contentSha256:written.contentSha256}}async awaitInitialContract(agentId,timeoutMs){let worker=this.workers.get(agentId);if(worker===void 0)throw new Error(`Unknown or stopped worker: ${agentId}`);let pin=worker.contractPin;if(pin===void 0)throw new Error(`worker ${agentId} (${worker.role}) has no contract pin to collect`);await worker.initialSettlement,worker.lastEvent="agent.settled";let published=await this.waitForPublication(pin,void 0,timeoutMs);return{receipt:published.receipt,document:published.document,agentId:worker.agentId,sessionPath:worker.sessionPath}}async readResultBytes(file){return readFile17(join50(this.runDirectory,file),"utf8").catch(error=>{if(error.code!=="ENOENT")throw error})}async waitForWriterResult(file,baselineBytes,timeoutMs){let limit=timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,interval=this.dependencies.contractPollIntervalMs??CONTRACT_POLL_INTERVAL_MS,deadline=this.now().getTime()+limit,last=`${file} was never written`;for(;;){let bytes=await this.readResultBytes(file);if(bytes===void 0)last=`${file} does not exist`;else if(bytes===baselineBytes)last=`${file} is unchanged from before this delivery`;else{let document;try{document=JSON.parse(bytes)}catch{document=void 0,last=`${file} is not parseable JSON`}if(document!==void 0)try{return parseLadderDecision(document),{contentSha256:hashContractBytes(bytes),document}}catch(error){last=error instanceof Error?error.message:String(error)}}if(this.now().getTime()>=deadline)throw new Error(`worker did not write ${file} within ${limit}ms: ${last}`);await this.sleep(interval)}}async waitForPublication(pin,baselinePublicationId,timeoutMs){let limit=timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,interval=this.dependencies.contractPollIntervalMs??CONTRACT_POLL_INTERVAL_MS,deadline=this.now().getTime()+limit,last="no attempt was made";for(;;){let outcome=await evaluatePublication({pin,baselinePublicationId});if(outcome.kind==="accepted")return{receipt:outcome.receipt,document:outcome.document};if(last=describeRejection(outcome.rejection),this.now().getTime()>=deadline)throw new Error(`worker did not publish ${pin.declaredPath} within ${limit}ms: ${last}`);await this.sleep(interval)}}async publishAndStop(agentId,graceMs){let worker=this.workers.get(agentId);if(worker===void 0)return{stopped:!1,graced:!1};let grace=graceMs??this.dependencies.stopGraceMs??STOP_GRACE_TIMEOUT_MS,published,reason;if(grace>0)try{if(ROLE_RESULT_FILE[worker.role]!==void 0)published=(await this.communicate({agentId,message:STOP_MESSAGE,deliverAs:"followUp",expect:"result",timeoutMs:grace})).contractPath;else{let settled=worker.launch.protocol.waitForSettled(grace);await this.communicate({agentId,message:STOP_MESSAGE,deliverAs:"followUp",expect:"ack"}),await settled}}catch(error){reason=error instanceof Error?error.message:String(error)}return{stopped:await this.stop(agentId),published,graced:published!==void 0||reason===void 0,reason}}async publishAndStopAll(graceMs){let agentIds=await this.serialize(async()=>(await this.reapUnlocked(),[...this.workers.keys()])),outcomes=[];for(let agentId of agentIds){let outcome=await this.publishAndStop(agentId,graceMs);outcomes.push({agentId,...outcome})}return outcomes}async stop(agentId){return this.serialize(()=>this.stopUnlocked(agentId))}async stopUnlocked(agentId){let worker=this.workers.get(agentId);return worker===void 0?!1:(this.workers.delete(agentId),worker.releaseAdmission(),await worker.launch.stop().catch(()=>{}),worker.launch.protocol.close(),await releaseAllLeasesFor(this.runDirectory,agentId,this.leaseDependencies),!0)}async stopAll(){await this.serialize(async()=>{this.closing=!0;for(let agentId of[...this.workers.keys()])await this.stopUnlocked(agentId)})}get isClosing(){return this.closing}async readLeases(){return readLeasesFile(this.runDirectory,this.leaseDependencies)}async releaseDeadLeases(){await releaseDeadLeases(this.runDirectory,this.leaseDependencies)}async claim(agentId,pid,key){return claimLease(this.runDirectory,{agentId,pid,key},this.leaseDependencies)}async release(agentId,key){return releaseLease(this.runDirectory,{agentId,key},this.leaseDependencies)}};var PARENT_WRITER_TOOLS=new Set(["write","edit","apply_patch","multi_edit","bash","powershell"]);function registerBackgroundBus(pi,options={}){if(hasWorkerDescriptor(options.env)){registerWorkerTools(pi,options);return}registerParentTools(pi,options)}function leaseDependenciesFrom(options){return{now:options.now,isProcessAlive:options.isProcessAlive,sleep:options.sleep,lockTimeoutMs:options.lockTimeoutMs,lockStaleMs:options.lockStaleMs,lockRetryMs:options.lockRetryMs}}async function canonicalClaimKey(cwd,jobId,runDirectory,path14){let task=await readTaskForJob(cwd,jobId);if(stackRequiredFor(task)){let{module}=await freezeCurrentSlice(cwd,runDirectory,task);return assertClaimInModule(cwd,path14,module)}return canonicalProjectPath(cwd,path14)}function registerWorkerTools(pi,options){let leaseDependencies=leaseDependenciesFrom(options),identityFor=cwd=>requireWorkerIdentity(cwd,options.env);typeof pi.registerTool=="function"&&(pi.registerTool({name:"write_contract",label:"Write Contract",description:"Publish this worker's one declared run-contract file after schema validation",parameters:typebox_exports.Object({path:typebox_exports.String(),content:typebox_exports.Object({},{additionalProperties:!0})}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);authorizeWorkerTool(identity,"write_contract");let pin=mintContractPin({agentId:identity.agentId,jobId:identity.jobId,role:identity.role,runDirectory:identity.runDirectory,capabilityId:identity.capabilityId??""}),result=await writeContract({pin,agentId:identity.agentId,jobId:identity.jobId,role:identity.role,requestedPath:params.path,payload:params.content,now:options.now}),details={path:result.path,agent_id:identity.agentId,publication_id:result.receipt.publication_id,content_sha256:result.receipt.content_sha256};return{content:[{type:"text",text:`published ${result.path}`}],details}}}),pi.registerTool({name:"claim_path",label:"Claim Path",description:"Acquire an exclusive same-tree path lease inside this job's frozen slice",parameters:typebox_exports.Object({path:typebox_exports.String()}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);if(authorizeWorkerTool(identity,"claim_path"),!identity.tools.some(tool=>MUTATION_TOOLS.has(tool)))throw new Error(`worker ${identity.agentId} (${identity.role}) holds no mutation tool to claim for`);let key=await canonicalClaimKey(context.cwd,identity.jobId,identity.runDirectory,params.path),lease;try{lease=await claimLease(identity.runDirectory,{agentId:identity.agentId,pid:process.pid,key},leaseDependencies)}catch(error){let held=/^Path already claimed by (\S+):/u.exec(error instanceof Error?error.message:"");throw held!==null&&await appendBusDenial(identity.runDirectory,identity.jobId,{reason:"claim-held",role:identity.role,agent_id:identity.agentId,key,holder:held[1]}).catch(()=>{}),error}let details={path:params.path,key,agent_id:identity.agentId,at:lease.at};return{content:[{type:"text",text:`claimed ${key}`}],details}}}),pi.registerTool({name:"release_path",label:"Release Path",description:"Release a same-tree path lease held by this worker",parameters:typebox_exports.Object({path:typebox_exports.String()}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);authorizeWorkerTool(identity,"release_path");let key=await canonicalClaimKey(context.cwd,identity.jobId,identity.runDirectory,params.path),released=await releaseLease(identity.runDirectory,{agentId:identity.agentId,key},leaseDependencies);return{content:[{type:"text",text:released?`released ${key}`:`no lease on ${key}`}],details:{path:params.path,key,released}}}})),typeof pi.on=="function"&&pi.on("tool_call",async(event,ctx)=>{let identity=await resolveWorkerIdentity(ctx.cwd,options.env).catch(()=>{});if(identity!==void 0)return evaluateWorkerToolCall(event,identity)})}function evaluateWorkerToolCall(event,identity){if(MUTATION_TOOLS.has(event.toolName)&&!identity.tools.some(tool=>MUTATION_TOOLS.has(tool)))return{block:!0,reason:`${identity.role} workers publish through write_contract and never write files directly`};if(isToolCallEventType("bash",event)&&hasTestShellOnly(identity.role)){let command=typeof event.input.command=="string"?event.input.command.trim():"",gates=identity.qualityGates??[];if(gates.length===0)return{block:!0,reason:`${identity.role} workers may only run this job's declared quality gates, and none are declared`};if(!gates.includes(command))return{block:!0,reason:`${identity.role} workers may only run a declared quality gate exactly; allowed: ${gates.join(" | ")}`}}}function registerParentTools(pi,options){let buses=new Map;setLiveWorkerCountProvider(()=>{let count=0;for(let bus of buses.values())count+=bus.countLiveProcesses();return count});let parentGate=Promise.resolve(),serializeParent=operation=>{let result=parentGate.then(operation,operation);return parentGate=result.then(()=>{},()=>{}),result},activeBus=async cwd=>{let job=await readActiveJob(cwd);if(job===void 0)throw new Error("No active K-\u03C0 job");let bus=buses.get(job.jobId);return bus===void 0&&(bus=new BackgroundBus(cwd,job.directory,job.jobId,options),buses.set(job.jobId,bus)),bus},busOwning=async(cwd,agentId)=>{for(let bus of buses.values())if(bus.get(agentId)!==void 0)return bus;return activeBus(cwd)},countLiveAcrossJobs=async()=>{let workers=0,writers=0;for(let bus of buses.values()){await bus.reap();for(let worker of bus.list())workers+=1,worker.isWriter&&(writers+=1)}return{workers,writers}},liveWriter=async()=>{for(let bus of buses.values()){await bus.reap();let writer=bus.list().find(worker=>worker.isWriter);if(writer!==void 0&&bus.hasLiveWriter())return{agentId:writer.agentId,jobId:bus.jobId}}};typeof pi.registerTool=="function"&&(pi.registerTool({name:"spawn_background",label:"Spawn Background",description:"Start one local background K-\u03C0 worker; at most two workers and one writer",parameters:typebox_exports.Object({role:typebox_exports.Union(WORKER_ROLES.map(role=>typebox_exports.Literal(role))),prompt:typebox_exports.String(),model:typebox_exports.Optional(typebox_exports.String()),tools:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String()))}),async execute(_id,params,_signal,_update,context){if(!isWorkerRole(params.role))throw new Error(`Unknown worker role: ${String(params.role)}`);let worker=await serializeParent(async()=>{let tools=resolveRoleTools(params.role,params.tools),wantsWriter=isWriterToolSet(tools),live=await countLiveAcrossJobs(),bus=await activeBus(context.cwd);if(live.workers>=MAX_LIVE_WORKERS)throw await bus.logDenied({reason:"worker-limit",role:params.role,limit:MAX_LIVE_WORKERS}).catch(()=>{}),new Error(`Background worker limit is ${MAX_LIVE_WORKERS}`);if(wantsWriter&&live.writers>=MAX_LIVE_WRITERS)throw await bus.logDenied({reason:"writer-live",role:params.role,limit:MAX_LIVE_WRITERS}).catch(()=>{}),new Error("A writer worker is already live");return bus.spawn({role:params.role,prompt:params.prompt,model:params.model,tools:params.tools})}),details={agent_id:worker.agentId,session_path:worker.sessionPath,pid:worker.pid,role:worker.role,tools:worker.tools,is_writer:worker.isWriter,contract_path:worker.contractPin?.declaredPath};return{content:[{type:"text",text:JSON.stringify(details)}],details}}}),pi.registerTool({name:"communicate",label:"Communicate",description:"Deliver steering or follow-up input to a background K-\u03C0 worker",parameters:typebox_exports.Object({to:typebox_exports.String(),message:typebox_exports.String(),deliverAs:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("steer"),typebox_exports.Literal("followUp")])),expect:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("none"),typebox_exports.Literal("ack"),typebox_exports.Literal("result")])),timeoutMs:typebox_exports.Optional(typebox_exports.Number())}),async execute(_id,params,_signal,_update,context){let outcome=await(await busOwning(context.cwd,params.to)).communicate({agentId:params.to,message:params.message,deliverAs:params.deliverAs,expect:params.expect,timeoutMs:params.timeoutMs}),details={to:params.to,expect:params.expect??"none",accepted:outcome.accepted,contract_path:outcome.contractPath,publication_id:outcome.publicationId};return{content:[{type:"text",text:JSON.stringify(details)}],details}}}),pi.registerTool({name:"agents_status",label:"Agents Status",description:"List live background workers, their pids, and their last bus event",parameters:typebox_exports.Object({}),async execute(_id,_params,_signal,_update,context){await activeBus(context.cwd).catch(()=>{});let status=(await Promise.all([...buses.values()].map(bus=>bus.status()))).flat();return{content:[{type:"text",text:JSON.stringify({agents:status.length,workers:status})}],details:{workers:status}}}}),pi.registerTool({name:"agents_stop",label:"Agents Stop",description:"Ask a worker to publish its contract and exit, then stop it",parameters:typebox_exports.Object({agent_id:typebox_exports.Optional(typebox_exports.String()),graceMs:typebox_exports.Optional(typebox_exports.Number())}),async execute(_id,params,_signal,_update,context){if(params.agent_id===void 0){let outcomes=await serializeParent(async()=>{await activeBus(context.cwd).catch(()=>{});let collected=[];for(let bus2 of buses.values()){let stopped=await bus2.publishAndStopAll(params.graceMs);for(let outcome2 of stopped)collected.push({agent_id:outcome2.agentId,job_id:bus2.jobId,stopped:outcome2.stopped,published:outcome2.published,graced:outcome2.graced,reason:outcome2.reason})}return collected});return{content:[{type:"text",text:`stopped ${outcomes.filter(entry=>entry.stopped).length} worker(s)`}],details:{stopped:outcomes}}}let outcome=await(await busOwning(context.cwd,params.agent_id)).publishAndStop(params.agent_id,params.graceMs);return{content:[{type:"text",text:outcome.stopped?`stopped ${params.agent_id}${outcome.published===void 0?"":` after publishing ${outcome.published}`}`:`no live worker ${params.agent_id}`}],details:outcome}}})),typeof pi.on=="function"&&(pi.on("tool_call",async event=>{if(!PARENT_WRITER_TOOLS.has(event.toolName))return;let writer=await liveWriter();if(writer===void 0)return;let holder=`${writer.agentId} (job ${writer.jobId})`;return{block:!0,reason:event.toolName==="bash"||event.toolName==="powershell"?`worker ${holder} holds the single-writer slot; a shell can write anything, so it is closed until that worker stops`:`worker ${holder} holds the single-writer slot; stop it before writing from this session`}}),pi.on("session_shutdown",async()=>{for(let bus of buses.values())await bus.stopAll().catch(()=>{});buses.clear()}))}import{readFile as readFile23,stat as stat10}from"node:fs/promises";import{join as join56}from"node:path";var BOARD_STAGES=[{id:"01",key:"ac-compile",label:"ac-compile"},{id:"02",key:"specify",label:"specify"},{id:"03",key:"plan",label:"plan"},{id:"04",key:"implement",label:"implement"},{id:"05",key:"test",label:"test"},{id:"06",key:"bounds",label:"bounds"},{id:"07",key:"review",label:"review"},{id:"08",key:"ship",label:"ship"}],RUN_FILE_NAMES=["task.json","context.md","candidate.json","evidence.json","verdict.json","events.jsonl"],STOP_VOCABULARY=new Set(["RUNNING","DONE","BLOCKED","EXHAUSTED","NO_PROGRESS","UNSAFE","NEEDS_HUMAN"]);function normalizeStop(raw){let upper=(raw??"RUNNING").toUpperCase();return upper==="APPROVAL"?"RUNNING":STOP_VOCABULARY.has(upper)?upper:upper==="COMPLETED"?"DONE":"RUNNING"}function stageIndex(stage){let normalized=stage.toLowerCase().replace(/^0?\d+\s+/,"").trim();if(normalized.length===0)return-1;let exact=BOARD_STAGES.findIndex(entry=>entry.key===normalized||entry.label===normalized);if(exact>=0)return exact;if(normalized==="ac_compile"||normalized==="accompile")return 0;if(normalized==="plan-check")return 2;if(normalized==="quality-green")return 4;if(normalized.endsWith("er")){let stem=normalized.slice(0,-2),byStem=BOARD_STAGES.findIndex(entry=>entry.key===stem);if(byStem>=0)return byStem}return normalized==="human-confirm"||normalized==="human_confirm"||normalized==="confirm"?7:-1}function resolveCurrentStageIndex(stage,node){let fromStage=stageIndex(stage);if(fromStage>=0)return fromStage;if(node!==void 0){let fromNode=stageIndex(node);if(fromNode>=0)return fromNode}return 0}function rowText(row){return row.map(span=>span.text).join("")}function verifierFor(model2){return model2.verifier!==void 0?model2.verifier:model2.passed===!0?"pass":model2.passed===!1?"fail":"pending"}function verifierLabel(verifier){return verifier==="pass"?"PASS":verifier==="fail"?"FAIL":"PASS/FAIL PENDING"}function shortFingerprint(value){if(value===void 0||value.length===0)return"\u2014";let hex=value.replace(/^sha256:/,"");return hex.length<=12?hex:hex.slice(0,12)}function stopTone(stop){return stop==="RUNNING"?"warning":stop==="DONE"?"success":stop==="NEEDS_HUMAN"?"accent":"error"}var LIT="\u25CF",DARK="\u25CB";function stageCells(current){return BOARD_STAGES.map((entry,index3)=>{let status=index3===current?"CURRENT":current>=0&&index3<current?"DONE":"PENDING",tone=status==="CURRENT"?"accent":status==="DONE"?"success":"dim";return{lines:[entry.id,entry.label,status],compact:`${entry.id} ${entry.label} ${status}`,tone,borderTone:status==="CURRENT"?"borderAccent":"border",lit:status==="CURRENT"}})}function stagesRegion(current,title){let cells=stageCells(current),labels=cells.map(cell=>cell.compact);return{kind:"cells",id:"stages",title,cells,compactRow:cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone})),flat:[`STAGES ${labels.slice(0,4).join(" ")}`,` ${labels.slice(4).join(" ")}`]}}function lampCells(fileLit){return RUN_FILE_NAMES.map(name=>{let lit=fileLit[name]===!0;return{lines:[name,lit?LIT:DARK,lit?"ON":"DIM"],compact:`${lit?LIT:DARK} ${name}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit}})}function lampRow(cells){return cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone}))}function lampsRegion(model2,paused){let cells=paused?RUN_FILE_NAMES.map(name=>{let lit=model2.fileLit[name]===!0;return{lines:[name,lit?LIT:DARK,name==="events.jsonl"?"APPEND":lit?"READY":"MISSING"],compact:`${lit?LIT:DARK} ${name}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit}}):lampCells(model2.fileLit),compactRow=lampRow(cells),flatLamps=rowText(compactRow);return{kind:"cells",id:"lamps",title:paused?"SHARED RUN STATE":"FILE LAMPS",cells,compactRow,flat:paused?["SHARED RUN STATE",` ${flatLamps}`]:[`FILES ${flatLamps}`]}}function contextRows(model2){let pack=model2.contextPack,rows=[[{text:`product ${pack.product?LIT:DARK}`,tone:pack.product?"text":"dim"},{text:" "},{text:`structure ${pack.structure?LIT:DARK}`,tone:pack.structure?"text":"dim"},{text:" "},{text:`tech ${pack.tech?LIT:DARK}`,tone:pack.tech?"text":"dim"}]];if(model2.research!==void 0&&(rows.push([{text:model2.research.cell,tone:"muted"}]),model2.research.struck!==void 0&&rows.push([{text:model2.research.struck,tone:"error"}])),model2.kstack!==void 0){let done=model2.kstack.todos.length;rows.push([{text:`K-STACK ${model2.kstack.playbook} ${done} steps`,tone:"text"}]),model2.kstack.todos.length>0&&rows.push([{text:`PROGRESS ${model2.kstack.todos[0]}${done>1?` \xB7 +${done-1}`:""}`,tone:"muted"}])}let cells=[{text:`AGENTS ${model2.agents}`,tone:"text"},{text:" "},{text:model2.busLit?`BUS ${LIT}`:`BUS ${DARK}`,tone:model2.busLit?"text":"dim"}];return model2.route!==void 0&&cells.push({text:" "},{text:`ROUTE ${model2.route}`,tone:"text"}),model2.usage!==void 0&&cells.push({text:" "},{text:`USAGE ${model2.usage}`,tone:"text"}),rows.push(cells),rows}function contextRegion(model2){let rows=contextRows(model2),[lamps,...rest]=rows;return{kind:"rows",id:"contextLayer",title:"CONTEXT LAYER",rows,frame:"panel",flat:[`CONTEXT LAYER ${rowText(lamps??[])}`,...rest.map(row=>` ${rowText(row)}`)]}}function iterationRegion(model2){let verifier=verifierFor(model2),fingerprint=shortFingerprint(model2.fingerprint),round=`ROUND ${model2.round}/${model2.maxRounds}`,rows=[[{text:round,tone:"text"}]];return verifier==="pending"?rows.push([{text:"PASS/FAIL PENDING",tone:"dim"}]):rows.push([{text:verifier==="pass"?`PASS ${LIT} last verifier`:`PASS ${DARK} none`,tone:verifier==="pass"?"success":"dim"}],[{text:verifier==="fail"?`FAIL ${LIT} last verifier`:`FAIL ${DARK} none`,tone:verifier==="fail"?"error":"dim"}]),rows.push([{text:`FINGERPRINT ${fingerprint}`,tone:"muted"}]),{kind:"rows",id:"iteration",title:"ITERATION LOOP",rows,frame:"panel",flat:[`${round} FINGERPRINT ${fingerprint} ${verifierLabel(verifier)}`]}}function oversightRegion(question){return{kind:"rows",id:"oversight",title:"HUMAN OVERSIGHT REQUIRED",rows:[[{text:"GATE human \u2014 ",tone:"accent"},{text:question===void 0?"confirm to continue":question,tone:"text"}]],frame:"accent",flat:["HUMAN OVERSIGHT REQUIRED"]}}function waitingRegion(question){return{kind:"rows",id:"waiting",title:"WAITING ON OPERATOR",rows:question===void 0?[]:[[{text:question,tone:"text"}]],frame:"accent",flat:[question===void 0?"WAITING ON OPERATOR":`WAITING ON OPERATOR ${question}`]}}function stopStatesRegion(stop){let cells=[["DONE",stop==="DONE"],["BLOCKED",stop==="BLOCKED"],["APPROVAL",!0]].map(([label,lit])=>({lines:[label,lit?LIT:DARK],compact:`${label} ${lit?LIT:DARK}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit})),compactRow=cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone}));return{kind:"cells",id:"stopStates",title:"STOP STATES",cells,compactRow,flat:[`STOP STATES ${rowText(compactRow)}`]}}var THREE_LAWS=["1. Outer loop owns the return path","2. Shared files are the contract","3. Irreversible effects stay outside the worker"];function threeLawsRegion(){return{kind:"rows",id:"threeLaws",title:"THREE LAWS",rows:THREE_LAWS.map(law=>[{text:law,tone:"muted"}]),frame:"panel",flat:["THREE LAWS",...THREE_LAWS.map(law=>` ${law}`)]}}function telemetryRegion(model2,current,gate){let stage=BOARD_STAGES[current]??BOARD_STAGES[0],row=[{text:`LOOP ${model2.jobId}`,tone:"text"},{text:" "},{text:`STAGE ${stage.id} ${stage.label}`,tone:"accent"},{text:" "},{text:`NODE ${model2.node}`,tone:"text"},{text:" "},{text:`GATE ${gate}`,tone:gate==="human"?"accent":"text"}];return{kind:"rows",id:"telemetry",rows:[row],frame:"none",flat:[rowText(row)]}}function headerRegion(model2,paused){let segments=[{text:paused?"K-\u03C0 PROTOCOL":"K-\u03C0 GRAPH CONTROL",tone:"accent"},{text:`MODE ${model2.mode}`,tone:"text"},{text:`JOB ${model2.jobId}`,tone:"text"},{text:`ROUND ${model2.round}/${model2.maxRounds}`,tone:"text"}];return paused&&segments.push({text:"GATE approval",tone:"accent"}),model2.kstack!==void 0&&segments.push({text:"K-STACK on",tone:"success"}),{kind:"strip",id:"header",segments,flat:[segments.map(segment2=>segment2.text).join(" ")]}}function buildBoardRegions(model2){let current=resolveCurrentStageIndex(model2.stage,model2.node),paused=model2.paused,gate=model2.gate??(paused?"human":"machine"),question=model2.pendingQuestion?.trim(),pending=question!==void 0&&question.length>0?question:void 0,regions=[headerRegion(model2,paused),telemetryRegion(model2,current,gate),contextRegion(model2),stagesRegion(current,paused?"STAGE RAIL":"STAGES 01\u201308"),iterationRegion(model2)];paused&&regions.push(oversightRegion(pending),waitingRegion(pending)),regions.push(lampsRegion(model2,paused)),paused&&regions.push(stopStatesRegion(model2.stop),threeLawsRegion()),regions.push({kind:"stop",id:"stop",text:`STOP ${model2.stop}`,tone:stopTone(model2.stop),flat:[`STOP ${model2.stop}`]});let byId={};for(let region of regions)byId[region.id]=region;return{variant:paused?"blue":"amber",regions,byId}}function flattenRegions(regions){return regions.regions.flatMap(region=>region.flat)}function renderBoard(model2){return fitBoard(flattenRegions(buildBoardRegions(model2)),model2.width)}var LAMP_SEPARATOR=" ";function isFileLampRow(line){return RUN_FILE_NAMES.every(name=>line.includes(name))}function foldLamps(line,width){let indent=line.slice(0,line.length-line.trimStart().length),body=line.slice(indent.length),label=body.startsWith("FILES")?"FILES":"",lamps=body.slice(label.length).trim().split(LAMP_SEPARATOR).filter(lamp=>lamp.length>0);if(lamps.length===0)return[line];let firstPrefix=label.length>0?`${indent}${label}${LAMP_SEPARATOR}`:indent,continuationPrefix=`${indent}${LAMP_SEPARATOR}`,rows=[],current="",prefix=firstPrefix;for(let lamp of lamps){let candidate=current.length===0?`${prefix}${lamp}`:`${current}${LAMP_SEPARATOR}${lamp}`;if(current.length>0&&visibleWidth(candidate)>width){rows.push(current),prefix=continuationPrefix,current=`${prefix}${lamp}`;continue}current=candidate}return current.length>0&&rows.push(current),rows}function truncatePlain(text,width){if(visibleWidth(text)<=width)return text;let out="";for(let character of text){if(visibleWidth(out+character)>width-1)break;out+=character}return`${out}\u2026`}function clamp3(line,width){return truncatePlain(line,width)}var STAGE_CELL_PATTERN=/\d{2} \S+ (?:DONE|CURRENT|PENDING)/gu,STAGE_CELL_SEPARATOR=" ";function isStageRow(line){return line.match(STAGE_CELL_PATTERN)!==null}function foldStages(line,width){let cells=(line.match(STAGE_CELL_PATTERN)??[]).filter(cell=>!cell.endsWith("CURRENT")),label=line.trimStart().startsWith("STAGES")?"STAGES":"",rows=[],current="",prefix=label.length>0?`${label} `:" ";for(let cell of cells){let candidate=current.length===0?`${prefix}${cell}`:`${current}${STAGE_CELL_SEPARATOR}${cell}`;if(current.length>0&&visibleWidth(candidate)>width){rows.push(current),prefix=" ",current=`${prefix}${cell}`;continue}current=candidate}return current.length>0&&rows.push(current),rows}function fitHeader(line,width){if(visibleWidth(line)<=width)return line;let segments=line.split(" "),job=segments.findIndex(segment2=>segment2.startsWith("JOB "));if(job!==-1){let excess=visibleWidth(line)-width,keep=Math.max(10,visibleWidth(segments[job]??"")-excess);segments[job]=truncatePlain(segments[job]??"",keep)}return clamp3(segments.join(" "),width)}function isEssentialRow(line){return line.includes("CURRENT")||line.startsWith("STOP ")||line.startsWith("K-\u03C0")||line.startsWith("WAITING ON OPERATOR")||line.startsWith("HUMAN OVERSIGHT")}function fitBoard(lines,width){if(width===void 0||width<=0||width>=100)return[...lines];let essential=[];for(let line of lines){if(line.includes("CURRENT")){let match2=/(\d{2}\s+\S+)\s+CURRENT/u.exec(line),marker=match2!==null?`${match2[1]} CURRENT`:"CURRENT";essential.push(clamp3(marker,width));continue}isEssentialRow(line)&&essential.push(line.startsWith("K-\u03C0")?fitHeader(line,width):clamp3(line,width))}let rest=[];for(let line of lines)if(!(isEssentialRow(line)&&!line.includes("CURRENT"))){if(isFileLampRow(line)){rest.push(...foldLamps(line,width));continue}if(isStageRow(line)){rest.push(...foldStages(line,width));continue}rest.push(clamp3(line,width))}return[...essential,...rest]}function researchCellFromDocument(document){let network=document.network;if(network!==void 0){if(network.state==="online"){let external=(document.sources??[]).filter(source2=>source2.kind==="external");return{cell:`RESEARCH ${external.find(source2=>typeof source2.service=="string"&&source2.service.length>0)?.service??document.mode??"exa"} ${external.length} src`}}if(network.state==="no-network"){if((network.origin==="engine"?"engine":"operator")==="operator")return{cell:"RESEARCH local \xB7 no-network operator"};let reason=typeof network.reason=="string"&&network.reason.length>0?network.reason:"exhausted",failed=new Set((network.failures??[]).map(failure=>failure.service?.toLowerCase()).filter(service=>typeof service=="string")),struck=["exa","perplexity"].filter(service=>failed.has(service)||failed.has(service==="perplexity"?"pplx":service)).map(service=>service==="perplexity"?"PPLX \u2715":"EXA \u2715").join(" "),marks=struck.length>0?struck:((network.failures??[]).length>0,"EXA \u2715 PPLX \u2715");return{cell:`RESEARCH local \xB7 no-network engine \xB7 ${reason}`,struck:marks}}}}var PLAIN_PALETTE={paint:(_tone,text)=>text};function paletteFromTheme(theme2){return{paint:(tone,text)=>text.length===0?text:theme2.fg(tone,text)}}var DEFAULT_FRAME_MIN_WIDTH=70,DEFAULT_COLUMNS_MIN_WIDTH=100,STRIP_SEPARATOR=" \u2502 ";function pad(text,width){let missing=width-visibleWidth(text);return missing>0?text+" ".repeat(missing):text}function fitWidth(text,width){return pad(truncatePlain(text,width),width)}function center(text,width){let missing=width-visibleWidth(text);if(missing<=0)return fitWidth(text,width);let left=Math.floor(missing/2);return" ".repeat(left)+text+" ".repeat(missing-left)}function paintRow(row,width,palette,fallback="text"){let plain=rowText(row);return visibleWidth(plain)>width?palette.paint(fallback,fitWidth(plain,width)):row.map(span=>palette.paint(span.tone??fallback,span.text)).join("")+" ".repeat(width-visibleWidth(plain))}function wrapWords(text,width){let lines=[],current="";for(let word of text.split(/\s+/u).filter(part=>part.length>0)){let candidate=current.length===0?word:`${current} ${word}`;if(current.length>0&&visibleWidth(candidate)>width){lines.push(current),current=word;continue}current=candidate}return current.length>0&&lines.push(current),lines.length===0?[""]:lines}function framePanel(region,width,palette){let borderTone=region.frame==="accent"?"borderAccent":"border",inner=Math.max(1,width-4),bar=palette.paint(borderTone,"\u2502"),line=content=>`${bar} ${content} ${bar}`,lines=[palette.paint(borderTone,`\u250C${"\u2500".repeat(width-2)}\u2510`)];region.title!==void 0&&lines.push(line(palette.paint("accent",fitWidth(region.title,inner))));for(let row of region.rows){let plain=rowText(row);if(visibleWidth(plain)>inner&&row.length===1){let tone=row[0]?.tone??"text";for(let part of wrapWords(plain,inner))lines.push(line(palette.paint(tone,pad(part,inner))));continue}lines.push(line(paintRow(row,inner,palette)))}return lines.push(palette.paint(borderTone,`\u2514${"\u2500".repeat(width-2)}\u2518`)),lines}function cellLayout(cells,width,lines){let widest=Math.max(...cells.map(cell=>Math.max(...lines(cell).map(text=>visibleWidth(text))))),fitting=natural2=>Math.min(cells.length,Math.max(1,Math.floor((width-1)/(natural2+1)))),natural=widest+2;fitting(natural)<cells.length&&fitting(widest)===cells.length&&(natural=widest);let rows=Math.ceil(cells.length/fitting(natural)),perRow=Math.ceil(cells.length/rows),cellInner=Math.max(natural,Math.floor((width-(perRow+1))/perRow));return{perRow,cellInner}}function junctionTone(left,right){return right?.lit?right.borderTone:left?.lit?left.borderTone:left?.borderTone??right?.borderTone??"border"}function borderLine(cells,cellInner,glyphs,palette){let[open10,join70,close]=glyphs,out=palette.paint(junctionTone(void 0,cells[0]),open10);return cells.forEach((cell,index3)=>{out+=palette.paint(cell.borderTone,"\u2500".repeat(cellInner));let next=cells[index3+1];out+=palette.paint(junctionTone(cell,next),next===void 0?close:join70)}),out}function textLine(cells,cellInner,texts,palette){let out=palette.paint(junctionTone(void 0,cells[0]),"\u2502");return cells.forEach((cell,index3)=>{out+=palette.paint(cell.tone,center(texts[index3]??"",cellInner)),out+=palette.paint(junctionTone(cell,cells[index3+1]),"\u2502")}),out}function frameCells(region,width,layout,palette){let twoLine=cell=>cell.lines.length>2?[cell.lines.slice(0,-1).join(" "),cell.lines.at(-1)??""]:cell.lines,oneLine=cell=>[cell.compact],bodyOf=layout==="full"?cell=>cell.lines:twoLine,{perRow,cellInner}=cellLayout(region.cells,width,bodyOf);if(layout==="compact"&&perRow<region.cells.length){let single=cellLayout(region.cells,width,oneLine),rowsOf2=per=>Math.ceil(region.cells.length/per);rowsOf2(single.perRow)*3<rowsOf2(perRow)*4&&(bodyOf=oneLine,{perRow,cellInner}=single)}let out=[];layout==="full"&&out.push(palette.paint("accent",fitWidth(region.title,width)));for(let start=0;start<region.cells.length;start+=perRow){let row=region.cells.slice(start,start+perRow),height=Math.max(...row.map(cell=>bodyOf(cell).length));out.push(pad(borderLine(row,cellInner,["\u250C","\u252C","\u2510"],palette),width));for(let line=0;line<height;line+=1)out.push(pad(textLine(row,cellInner,row.map(cell=>bodyOf(cell)[line]??""),palette),width));out.push(pad(borderLine(row,cellInner,["\u2514","\u2534","\u2518"],palette),width))}return out}function frameStrip(strip,width,palette,boxed){let inner=boxed?width-4:width,separator=palette.paint("dim",STRIP_SEPARATOR),segments=strip.segments.map(segment2=>({...segment2})),plainWidth=()=>segments.reduce((sum,segment2)=>sum+visibleWidth(segment2.text),0)+STRIP_SEPARATOR.length*Math.max(0,segments.length-1),job=segments.find(segment2=>segment2.text.startsWith("JOB "));if(job!==void 0&&plainWidth()>inner){let spare=Math.max(6,visibleWidth(job.text)-(plainWidth()-inner));job.text=truncatePlain(job.text,spare)}let painted=segments.map(segment2=>palette.paint(segment2.tone??"text",segment2.text)).join(separator),line=pad(plainWidth()<=inner?painted:palette.paint("text",fitWidth(rowText(segments),inner)),inner);if(!boxed)return[line];let bar=palette.paint("border","\u2502");return[palette.paint("border",`\u250C${"\u2500".repeat(width-2)}\u2510`),`${bar} ${line} ${bar}`,palette.paint("border",`\u2514${"\u2500".repeat(width-2)}\u2518`)]}function sideBySide(left,right,leftWidth,gap){let height=Math.max(left.length,right.length),rightWidth=Math.max(...right.map(line=>visibleWidth(line)),0),out=[];for(let index3=0;index3<height;index3+=1)out.push(`${pad(left[index3]??"",leftWidth)}${" ".repeat(gap)}${pad(right[index3]??"",rightWidth)}`);return out}function stopBox(text,tone,palette){let inner=visibleWidth(text)+2;return[palette.paint(tone,`\u250C${"\u2500".repeat(inner)}\u2510`),`${palette.paint(tone,"\u2502")} ${palette.paint(tone,text)} ${palette.paint(tone,"\u2502")}`,palette.paint(tone,`\u2514${"\u2500".repeat(inner)}\u2518`)]}function rightAlign(block,width){return block.map(line=>" ".repeat(Math.max(0,width-visibleWidth(line)))+line)}function paintFlat(regions,width,palette){let toneFor=line=>line.startsWith("K-\u03C0")?"accent":line.startsWith("STOP ")&&!line.startsWith("STOP STATES")?regions.byId.stop?.kind==="stop"?regions.byId.stop.tone:"warning":line.includes("CURRENT")||line.startsWith("WAITING ON OPERATOR")||line.startsWith("HUMAN OVERSIGHT")?"accent":"text";return fitBoard(flattenRegions(regions),width).map(line=>palette.paint(toneFor(line),line))}function rowsOf(region){return region?.kind==="rows"?region:void 0}function cellsOf(region){return region?.kind==="cells"?region:void 0}function telemetryBlock(regions,width,palette,layout){let lines=[],telemetry=rowsOf(regions.byId.telemetry);if(telemetry!==void 0)for(let row of telemetry.rows)lines.push(paintRow(row,width,palette));if(layout==="compact"){let iteration=rowsOf(regions.byId.iteration);if(iteration!==void 0){let spans=[];iteration.rows.forEach((row,index3)=>{index3>0&&spans.push({text:" "}),spans.push(...row)}),lines.push(paintRow(spans,width,palette))}let waiting=rowsOf(regions.byId.waiting);if(waiting!==void 0){let label="WAITING ON OPERATOR ",question=waiting.rows[0]===void 0?"":rowText(waiting.rows[0]);wrapWords(question,Math.max(8,width-label.length)).forEach((part,index3)=>{lines.push(paintRow(index3===0?[{text:"WAITING ON OPERATOR",tone:"accent"},{text:` ${part}`,tone:"text"}]:[{text:" ".repeat(label.length)},{text:part,tone:"text"}],width,palette))})}else{let context=rowsOf(regions.byId.contextLayer),summary=context?.rows.at(-1),lamps=context?.rows[0];lamps!==void 0&&summary!==void 0&&lines.push(paintRow([{text:"CONTEXT ",tone:"muted"},...lamps,{text:" "},...summary],width,palette))}let stopStates=cellsOf(regions.byId.stopStates);stopStates!==void 0&&lines.push(paintRow([{text:"STOP STATES ",tone:"text"},...stopStates.compactRow],width,palette))}return lines}function telemetryWithStop(regions,width,palette){let stop=regions.byId.stop;if(stop?.kind!=="stop")return telemetryBlock(regions,width,palette,"compact");let box2=stopBox(stop.text,stop.tone,palette),boxWidth=visibleWidth(stop.text)+4,leftWidth=width-boxWidth-2,cut=telemetryBlock(regions,leftWidth,PLAIN_PALETTE,"compact").some(line=>line.trimEnd().endsWith("\u2026"));return leftWidth<24||cut?[...telemetryBlock(regions,width,palette,"compact"),...rightAlign(box2,width)]:sideBySide(telemetryBlock(regions,leftWidth,palette,"compact"),box2,leftWidth,2)}function foldRow(prefix,items,width,palette){let indent=" ".repeat(visibleWidth(prefix.text)),rows=[],current=[prefix],used=visibleWidth(prefix.text);for(let item of items){let text=item.text.trimStart(),spacer=current.length===1?"":" ";if(current.length>1&&used+visibleWidth(spacer+text)>width){rows.push(current),current=[{text:indent}],used=indent.length,current.push({text,tone:item.tone}),used+=visibleWidth(text);continue}current.push({text:`${spacer}${text}`,tone:item.tone}),used+=visibleWidth(spacer+text)}return rows.push(current),rows.map(row=>paintRow(row,width,palette))}function paintCompact(regions,width,palette){let out=[],header2=regions.byId.header;header2?.kind==="strip"&&out.push(...frameStrip(header2,width,palette,!1));let stages=cellsOf(regions.byId.stages);stages!==void 0&&out.push(...frameCells(stages,width,"compact",palette));let lamps=cellsOf(regions.byId.lamps);return lamps!==void 0&&out.push(...foldRow({text:"FILES ",tone:"text"},lamps.compactRow,width,palette)),out.push(...telemetryWithStop(regions,width,palette)),out}function paintColumns(left,right,width,columnsMinWidth){if(right===void 0)return left;if(width<columnsMinWidth)return[...left,...right];let leftWidth=Math.floor((width-2)*.4);return sideBySide(left,right,leftWidth,2)}function paintFull(regions,width,palette,columnsMinWidth){let columnWidths=width<columnsMinWidth?[width,width]:[Math.floor((width-2)*.4),width-2-Math.floor((width-2)*.4)],out=[],header2=regions.byId.header;header2?.kind==="strip"&&out.push(...frameStrip(header2,width,palette,!0)),out.push(...telemetryBlock(regions,width,palette,"full"));let context=rowsOf(regions.byId.contextLayer);context!==void 0&&out.push(...framePanel(context,width,palette));let stages=cellsOf(regions.byId.stages);stages!==void 0&&out.push(...frameCells(stages,width,"full",palette));let iteration=rowsOf(regions.byId.iteration),oversight=rowsOf(regions.byId.oversight);if(iteration!==void 0){let left=framePanel(iteration,oversight===void 0?width:columnWidths[0],palette),right=oversight===void 0?void 0:framePanel(oversight,columnWidths[1],palette);out.push(...paintColumns(left,right,width,columnsMinWidth))}let lamps=cellsOf(regions.byId.lamps);lamps!==void 0&&out.push(...frameCells(lamps,width,"full",palette));let stopStates=cellsOf(regions.byId.stopStates),laws=rowsOf(regions.byId.threeLaws);if(stopStates!==void 0&&laws!==void 0){let left=frameCells(stopStates,width<columnsMinWidth?width:columnWidths[0],"full",palette),right=framePanel(laws,columnWidths[1],palette);out.push(...paintColumns(left,right,width,columnsMinWidth))}let waiting=rowsOf(regions.byId.waiting);waiting!==void 0&&out.push(...framePanel(waiting,width,palette));let stop=regions.byId.stop;return stop?.kind==="stop"&&out.push(...rightAlign(stopBox(stop.text,stop.tone,palette),width)),out.map(line=>pad(line,width))}function paintRegions(regions,options){let palette=options.palette??PLAIN_PALETTE,width=Math.max(1,Math.floor(options.width));if(width<(options.frameMinWidth??DEFAULT_FRAME_MIN_WIDTH))return paintFlat(regions,width,palette);let columnsMinWidth=options.columnsMinWidth??DEFAULT_COLUMNS_MIN_WIDTH;return options.layout==="compact"?paintCompact(regions,width,palette):paintFull(regions,width,palette,columnsMinWidth)}function paintBoard(model2,options){return paintRegions(buildBoardRegions(model2),options)}function createBoardComponent(model2,options){let current=model2,cache;return{render(width){if(cache!==void 0&&cache.width===width&&cache.model===current)return cache.lines;let lines=paintBoard(current,{width,layout:options.layout,palette:options.palette});return cache={width,model:current,lines},lines},invalidate(){cache=void 0},refresh(next){current=next,cache=void 0},dispose(){cache=void 0,options.onDispose?.()}}}import{execFile as execFileCallback2}from"node:child_process";import{createHash as createHash7,randomUUID as randomUUID14}from"node:crypto";import{readdir as readdir6,readFile as readFile22,realpath as realpath4,stat as stat9}from"node:fs/promises";import{basename as basename17,join as join55,relative as relative9,resolve as resolve20,sep as sep12}from"node:path";import{promisify as promisify2}from"node:util";function trimWrappingQuotes(value){let trimmed=value.trim(),first=trimmed[0],last=trimmed.at(-1);return trimmed.length>=2&&(first==="`"&&last==="`"||first==='"'&&last==='"'||first==="'"&&last==="'")?trimmed.slice(1,-1).trim():trimmed}function parseCommandCheck(input){let match2=/\bcmd\s+(.+?)\s+exits?\s+(-?\d+)\b/i.exec(input);if(match2===null)return;let cmd=trimWrappingQuotes(match2[1]);if(cmd.length!==0)return{kind:"command",cmd,expect:{exit:Number.parseInt(match2[2],10)}}}function parseWriteBounds(input){let match2=/\bwrites?\s+only\s+(.+?)(?=\s*;|\n|$)/i.exec(input);if(match2===null)return;let writeAllow=match2[1].trim().replace(/[.!?]+$/,"").split(/\s*(?:,|\band\b)\s*/i).map(trimWrappingQuotes).filter(path14=>path14.length>0);return writeAllow.length>0?{write_allow:writeAllow}:void 0}function scoreCompiledCriteria(criteria){let requiredCriteria=criteria.filter(criterion=>criterion.required),missingChecks=requiredCriteria.flatMap(criterion=>{let missing=[];return criterion.check===void 0&&missing.push("check"),criterion.bounds===void 0&&missing.push("bounds"),missing.length===0?[]:[{id:criterion.id,statement:criterion.statement,missing}]});return requiredCriteria.length===0?{quality:"narrative",missingChecks}:missingChecks.length===0?{quality:"executable",missingChecks}:{quality:requiredCriteria.some(criterion=>criterion.check!==void 0||criterion.bounds!==void 0)?"partial":"narrative",missingChecks}}function acceptanceStatements(input){let labeled=input.split(/\r?\n/u).map(line=>line.trim()).filter(line=>line.length>0).map(line=>/^(AC-\d+(?:\.\d+)?):\s*(.+)$/iu.exec(line));return labeled.length>0&&labeled.every(match2=>match2!==null)?labeled.map(match2=>({id:match2[1].toUpperCase(),statement:match2[2].trim().replace(/\s+/g," ")})):[{id:"AC-01",statement:input.trim().replace(/\s+/g," ")}]}function compileAcceptanceCriteria(input){let acceptance=acceptanceStatements(input).map(({id,statement})=>({id,statement,required:!0,check:parseCommandCheck(statement),bounds:parseWriteBounds(statement)}));return{acceptance,...scoreCompiledCriteria(acceptance)}}import{mkdir as mkdir11,readdir as readdir5,readFile as readFile20}from"node:fs/promises";import{basename as basename16,isAbsolute as isAbsolute9,join as join53,relative as relative8,resolve as resolve19}from"node:path";import{isDeepStrictEqual as isDeepStrictEqual2}from"node:util";import{execFile as execFileCallback}from"node:child_process";import{constants as constants7}from"node:fs";import{copyFile,mkdir as mkdir10,readFile as readFile19,stat as stat8}from"node:fs/promises";import{isAbsolute as isAbsolute8,join as join52,relative as relative7,resolve as resolve18,sep as sep11}from"node:path";import{promisify}from"node:util";import{createHash as createHash6,randomUUID as randomUUID13}from"node:crypto";import{appendFile,mkdir as mkdir9,readFile as readFile18,rename as rename5,rm as rm6,writeFile as writeFile2}from"node:fs/promises";import{basename as basename15,join as join51,relative as relative6,resolve as resolve17,sep as sep10}from"node:path";var CLAIM_STATUSES=["proposed","verified","rejected","superseded"],RECORD_FILES={source:"sources.jsonl",node:"nodes.jsonl",edge:"edges.jsonl"},PATCH_KINDS=["source","node","edge"],OBSERVED_AT_PATTERN=/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})$/u;function assertEnvelope(value,label){if(!isJsonObject(value))throw new Error(`${label} must be an object`);for(let field2 of["id","kind"]){let text=value[field2];if(typeof text!="string"||text.length===0)throw new Error(`${label}.${field2} is required`)}if(!Array.isArray(value.source_ids)||value.source_ids.some(id=>typeof id!="string"||id.length===0))throw new Error(`${label}.source_ids must be an array of source ids`);if(typeof value.status!="string"||!CLAIM_STATUSES.includes(value.status))throw new Error(`${label}.status must be one of ${CLAIM_STATUSES.join(", ")}`);if(typeof value.observed_at!="string"||!OBSERVED_AT_PATTERN.test(value.observed_at)||Number.isNaN(Date.parse(value.observed_at)))throw new Error(`${label}.observed_at must be an RFC 3339 date-time`);for(let field2 of["valid_from","valid_to"]){let instant=value[field2];if(instant!==void 0&&(typeof instant!="string"||Number.isNaN(Date.parse(instant))))throw new Error(`${label}.${field2} must be an RFC 3339 date-time`)}let rev=value.rev;if(rev!==void 0&&(typeof rev!="number"||!Number.isInteger(rev)||rev<1))throw new Error(`${label}.rev must be a positive integer`)}function validatePatch(value){if(!isJsonObject(value))throw new Error("knowledge graph patch must be an object");for(let key of Object.keys(value))if(!PATCH_KINDS.includes(key))throw new Error(`knowledge graph patch has an unsupported member ${key}`);let kinds=PATCH_KINDS.filter(kind=>value[kind]!==void 0);if(kinds.length===0)throw new Error("knowledge graph patch must carry a source, a node, or an edge");for(let kind of kinds)assertEnvelope(value[kind],`patch ${kind}`);let source2=value.source;if(isJsonObject(source2)){let uri=source2.uri;if(typeof uri!="string"||uri.length===0)throw new Error("patch source.uri is required")}let node=value.node;if(isJsonObject(node)&&node.source_ids.length===0)throw new Error("patch node.source_ids must cite at least one source");let edge=value.edge;if(isJsonObject(edge)){for(let field2 of["from","to"]){let endpoint=edge[field2];if(typeof endpoint!="string"||endpoint.length===0)throw new Error(`patch edge.${field2} is required`)}if(edge.source_ids.length===0)throw new Error("patch edge.source_ids must cite at least one source");let confidence=edge.confidence;if(confidence!==void 0&&(typeof confidence!="number"||confidence<0||confidence>1))throw new Error("patch edge.confidence must be between 0 and 1")}}function nextRevision(existing,id,requested,label){let next=existing.filter(record=>record.id===id).reduce((rev,record)=>Math.max(rev,record.rev),0)+1;if(requested!==void 0&&requested!==next)throw new Error(`${label} revision must be monotonic: expected ${next}, received ${requested}`);return next}function resolveAcceptance(patch,state2){let accepted={};patch.source!==void 0&&(accepted.source={...patch.source,rev:nextRevision(state2.sources,patch.source.id,patch.source.rev,`source ${patch.source.id}`)});let sourceIds=new Set(state2.sources.map(source2=>source2.id));accepted.source!==void 0&&sourceIds.add(accepted.source.id);let nodeIds=new Set(state2.nodes.map(node=>node.id));if(patch.node!==void 0){for(let id of patch.node.source_ids)if(!sourceIds.has(id))throw new Error(`node ${patch.node.id} cites unknown source ${id}`);let node={...patch.node,rev:nextRevision(state2.nodes,patch.node.id,patch.node.rev,`node ${patch.node.id}`)};accepted.node=node,nodeIds.add(node.id)}if(patch.edge!==void 0){for(let id of patch.edge.source_ids)if(!sourceIds.has(id))throw new Error(`edge ${patch.edge.id} cites unknown source ${id}`);for(let endpoint of[patch.edge.from,patch.edge.to])if(!nodeIds.has(endpoint))throw new Error(`edge ${patch.edge.id} references unknown node ${endpoint}`);accepted.edge={...patch.edge,rev:nextRevision(state2.edges,patch.edge.id,patch.edge.rev,`edge ${patch.edge.id}`)}}return accepted}var SNAPSHOT_COMPLETE_MARKER=".complete";function knowledgeGraphPaths(cwd){let root=join51(cwd,CONFIG_DIR_NAME,"kg");return{root,inbox:join51(root,"inbox"),snapshots:join51(root,"snapshots"),sources:join51(root,RECORD_FILES.source),nodes:join51(root,RECORD_FILES.node),edges:join51(root,RECORD_FILES.edge)}}function isAuthoritativeKnowledgeGraphPath(cwd,path14){let relativePath=relative6(resolve17(cwd),resolve17(cwd,path14)).split(sep10).join("/");if(relativePath.length===0||relativePath.startsWith("../"))return!1;let segments=relativePath.split("/");return segments.length<3||segments[0]!==CONFIG_DIR_NAME||segments[1]!=="kg"?!1:segments[2]!=="inbox"}var writeQueues=new Map;function serialize(root,operation){let result=(writeQueues.get(root)??Promise.resolve()).then(operation,operation);return writeQueues.set(root,result.catch(()=>{})),result}async function readRecords(path14){try{return(await readFile18(path14,"utf8")).split(`
1343
+ `),await file.sync()}finally{await file.close()}}async reapUnlocked(){for(let[agentId,worker]of[...this.workers])worker.launch.isAlive()&&this.isProcessAlive(worker.pid)||(this.workers.delete(agentId),worker.releaseAdmission(),worker.launch.protocol.close());await releaseDeadLeases(this.runDirectory,this.leaseDependencies)}async reap(){await this.serialize(()=>this.reapUnlocked())}get live(){return this.workers.size}countLiveProcesses(){let count=0;for(let worker of this.workers.values())worker.launch.isAlive()&&this.isProcessAlive(worker.pid)&&(count+=1);return count}hasLiveWriter(){for(let worker of this.workers.values())if(worker.isWriter&&worker.launch.isAlive()&&this.isProcessAlive(worker.pid))return!0;return!1}async spawn(options){return this.serialize(async()=>{if(this.closing)throw new Error("this bus is shutting down and starts no new workers");await this.reapUnlocked();let tools=resolveRoleTools(options.role,options.tools),isWriter=isWriterToolSet(tools),agentId=`${options.role}-${(this.dependencies.newAgentSuffix??randomUUID12)()}`,releaseAdmission;try{releaseAdmission=await this.admission.acquire({key:`${this.jobId}:${agentId}`,isWriter})}catch(error){throw await this.logDenied({reason:admissionDenialReason(error),role:options.role,agent_id:agentId,limit:this.admission.counts().workers}).catch(()=>{}),error}let admissionHeld=!0,returnAdmission=()=>{admissionHeld&&(admissionHeld=!1,releaseAdmission())};try{let capabilityId=(this.dependencies.newCapabilityId??mintCapabilityId)(),sessionDirectory=this.agentsDirectory,sessionPath=join50(sessionDirectory,`${agentId}.jsonl`),task=await readTaskForJob(this.cwd,this.jobId).catch(()=>{}),descriptor=mintWorkerDescriptor({agentId,jobId:this.jobId,role:options.role,runDirectory:this.runDirectory,tools,capabilityId,qualityGates:task?.quality_gates}),contractPin=mintContractPin({agentId,jobId:this.jobId,role:options.role,runDirectory:this.runDirectory,capabilityId});await mkdir8(sessionDirectory,{recursive:!0}),await(await open9(sessionPath,"a",384)).close();let launch=await this.launcher({cwd:this.cwd,sessionPath,sessionDirectory,tools,model:options.model,descriptor,cliPath:this.dependencies.cliPath,execPath:this.dependencies.execPath,startupTimeoutMs:this.dependencies.startupTimeoutMs}),settleTimeout=this.dependencies.contractWaitTimeoutMs??WORKER_RESULT_TIMEOUT_MS,initialSettlement=launch.protocol.waitForSettled(settleTimeout,launch.protocol.settles);initialSettlement.catch(()=>{});let record={agentId,role:options.role,pid:launch.pid,sessionPath,sessionDirectory,tools,isWriter,contractPin,descriptor,launch,spawnedAt:this.now().toISOString(),lastEvent:"agent.spawned",initialSettlement,releaseAdmission:returnAdmission};this.workers.set(agentId,record);try{await this.logSpawned({agent_id:agentId,role:options.role,pid:launch.pid,tools:[...tools],session_path:sessionPath}),await launch.protocol.prompt(options.prompt)}catch(error){throw this.workers.delete(agentId),returnAdmission(),await launch.stop().catch(()=>{}),error}return record}catch(error){throw returnAdmission(),error}})}get(agentId){return this.workers.get(agentId)}list(){return[...this.workers.values()]}async status(){return this.serialize(async()=>(await this.reapUnlocked(),[...this.workers.values()].map(worker=>({agent_id:worker.agentId,role:worker.role,pid:worker.pid,alive:worker.launch.isAlive()&&this.isProcessAlive(worker.pid),is_writer:worker.isWriter,tools:[...worker.tools],session_path:worker.sessionPath,last_event:worker.lastEvent,contract_path:worker.contractPin?.declaredPath,diagnostics:worker.launch.protocol.snapshot}))))}async communicate(options){let deliverAs=options.deliverAs??"followUp",expect=options.expect??"none",worker=await this.serialize(async()=>{await this.reapUnlocked();let found=this.workers.get(options.agentId);if(found===void 0)throw new Error(`Unknown or stopped worker: ${options.agentId}`);return found.lastEvent="agent.message",await this.logMessage({agent_id:options.agentId,role:found.role,deliver_as:deliverAs,expect}),found});if(expect==="none")return await worker.launch.protocol.send(deliverAs==="steer"?{type:"steer",message:options.message}:{type:"follow_up",message:options.message}),{accepted:!1};if(expect==="ack")return await worker.launch.protocol.deliver(options.message,deliverAs),{accepted:!0};let resultFile=ROLE_RESULT_FILE[worker.role];if(resultFile===void 0)throw new Error(`role ${worker.role} produces no result file, so there is nothing to wait for`);let pin=worker.contractPin,limit=options.timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,baselineReceipt=pin===void 0?void 0:await readPublicationReceipt(pin.receiptPath),baselineBytes=pin===void 0?await this.readResultBytes(resultFile):void 0,settled=worker.launch.protocol.waitForSettled(limit);try{await worker.launch.protocol.deliver(options.message,deliverAs)}catch(error){throw settled.catch(()=>{}),error}if(await settled,pin!==void 0){let outcome=await this.waitForPublication(pin,baselineReceipt?.publication_id,limit);return{accepted:!0,contractPath:outcome.receipt.declared_path,publicationId:outcome.receipt.publication_id}}let written=await this.waitForWriterResult(resultFile,baselineBytes,limit);return{accepted:!0,contractPath:resultFile,contentSha256:written.contentSha256}}async awaitInitialContract(agentId,timeoutMs){let worker=this.workers.get(agentId);if(worker===void 0)throw new Error(`Unknown or stopped worker: ${agentId}`);let pin=worker.contractPin;if(pin===void 0)throw new Error(`worker ${agentId} (${worker.role}) has no contract pin to collect`);await worker.initialSettlement,worker.lastEvent="agent.settled";let published=await this.waitForPublication(pin,void 0,timeoutMs);return{receipt:published.receipt,document:published.document,agentId:worker.agentId,sessionPath:worker.sessionPath}}async readResultBytes(file){return readFile17(join50(this.runDirectory,file),"utf8").catch(error=>{if(error.code!=="ENOENT")throw error})}async waitForWriterResult(file,baselineBytes,timeoutMs){let limit=timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,interval=this.dependencies.contractPollIntervalMs??CONTRACT_POLL_INTERVAL_MS,deadline=this.now().getTime()+limit,last=`${file} was never written`;for(;;){let bytes=await this.readResultBytes(file);if(bytes===void 0)last=`${file} does not exist`;else if(bytes===baselineBytes)last=`${file} is unchanged from before this delivery`;else{let document;try{document=JSON.parse(bytes)}catch{document=void 0,last=`${file} is not parseable JSON`}if(document!==void 0)try{return parseLadderDecision(document),{contentSha256:hashContractBytes(bytes),document}}catch(error){last=error instanceof Error?error.message:String(error)}}if(this.now().getTime()>=deadline)throw new Error(`worker did not write ${file} within ${limit}ms: ${last}`);await this.sleep(interval)}}async waitForPublication(pin,baselinePublicationId,timeoutMs){let limit=timeoutMs??this.dependencies.contractWaitTimeoutMs??CONTRACT_WAIT_TIMEOUT_MS,interval=this.dependencies.contractPollIntervalMs??CONTRACT_POLL_INTERVAL_MS,deadline=this.now().getTime()+limit,last="no attempt was made";for(;;){let outcome=await evaluatePublication({pin,baselinePublicationId});if(outcome.kind==="accepted")return{receipt:outcome.receipt,document:outcome.document};if(last=describeRejection(outcome.rejection),this.now().getTime()>=deadline)throw new Error(`worker did not publish ${pin.declaredPath} within ${limit}ms: ${last}`);await this.sleep(interval)}}async publishAndStop(agentId,graceMs){let worker=this.workers.get(agentId);if(worker===void 0)return{stopped:!1,graced:!1};let grace=graceMs??this.dependencies.stopGraceMs??STOP_GRACE_TIMEOUT_MS,published,reason;if(grace>0)try{if(ROLE_RESULT_FILE[worker.role]!==void 0)published=(await this.communicate({agentId,message:STOP_MESSAGE,deliverAs:"followUp",expect:"result",timeoutMs:grace})).contractPath;else{let settled=worker.launch.protocol.waitForSettled(grace);await this.communicate({agentId,message:STOP_MESSAGE,deliverAs:"followUp",expect:"ack"}),await settled}}catch(error){reason=error instanceof Error?error.message:String(error)}return{stopped:await this.stop(agentId),published,graced:published!==void 0||reason===void 0,reason}}async publishAndStopAll(graceMs){let agentIds=await this.serialize(async()=>(await this.reapUnlocked(),[...this.workers.keys()])),outcomes=[];for(let agentId of agentIds){let outcome=await this.publishAndStop(agentId,graceMs);outcomes.push({agentId,...outcome})}return outcomes}async stop(agentId){return this.serialize(()=>this.stopUnlocked(agentId))}async stopUnlocked(agentId){let worker=this.workers.get(agentId);return worker===void 0?!1:(this.workers.delete(agentId),worker.releaseAdmission(),await worker.launch.stop().catch(()=>{}),worker.launch.protocol.close(),await releaseAllLeasesFor(this.runDirectory,agentId,this.leaseDependencies),!0)}async stopAll(){await this.serialize(async()=>{this.closing=!0;for(let agentId of[...this.workers.keys()])await this.stopUnlocked(agentId)})}get isClosing(){return this.closing}async readLeases(){return readLeasesFile(this.runDirectory,this.leaseDependencies)}async releaseDeadLeases(){await releaseDeadLeases(this.runDirectory,this.leaseDependencies)}async claim(agentId,pid,key){return claimLease(this.runDirectory,{agentId,pid,key},this.leaseDependencies)}async release(agentId,key){return releaseLease(this.runDirectory,{agentId,key},this.leaseDependencies)}};var PARENT_WRITER_TOOLS=new Set(["write","edit","apply_patch","multi_edit","bash","powershell"]);function registerBackgroundBus(pi,options={}){if(hasWorkerDescriptor(options.env)){registerWorkerTools(pi,options);return}registerParentTools(pi,options)}function leaseDependenciesFrom(options){return{now:options.now,isProcessAlive:options.isProcessAlive,sleep:options.sleep,lockTimeoutMs:options.lockTimeoutMs,lockStaleMs:options.lockStaleMs,lockRetryMs:options.lockRetryMs}}async function canonicalClaimKey(cwd,jobId,runDirectory,path14){let task=await readTaskForJob(cwd,jobId);if(stackRequiredFor(task)){let{module}=await freezeCurrentSlice(cwd,runDirectory,task);return assertClaimInModule(cwd,path14,module)}return canonicalProjectPath(cwd,path14)}function registerWorkerTools(pi,options){let leaseDependencies=leaseDependenciesFrom(options),identityFor=cwd=>requireWorkerIdentity(cwd,options.env);typeof pi.registerTool=="function"&&(pi.registerTool({name:"write_contract",label:"Write Contract",description:"Publish this worker's one declared run-contract file after schema validation",parameters:typebox_exports.Object({path:typebox_exports.String(),content:typebox_exports.Object({},{additionalProperties:!0})}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);authorizeWorkerTool(identity,"write_contract");let pin=mintContractPin({agentId:identity.agentId,jobId:identity.jobId,role:identity.role,runDirectory:identity.runDirectory,capabilityId:identity.capabilityId??""}),result=await writeContract({pin,agentId:identity.agentId,jobId:identity.jobId,role:identity.role,requestedPath:params.path,payload:params.content,now:options.now}),details={path:result.path,agent_id:identity.agentId,publication_id:result.receipt.publication_id,content_sha256:result.receipt.content_sha256};return{content:[{type:"text",text:`published ${result.path}`}],details}}}),pi.registerTool({name:"claim_path",label:"Claim Path",description:"Acquire an exclusive same-tree path lease inside this job's frozen slice",parameters:typebox_exports.Object({path:typebox_exports.String()}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);if(authorizeWorkerTool(identity,"claim_path"),!identity.tools.some(tool=>MUTATION_TOOLS.has(tool)))throw new Error(`worker ${identity.agentId} (${identity.role}) holds no mutation tool to claim for`);let key=await canonicalClaimKey(context.cwd,identity.jobId,identity.runDirectory,params.path),lease;try{lease=await claimLease(identity.runDirectory,{agentId:identity.agentId,pid:process.pid,key},leaseDependencies)}catch(error){let held=/^Path already claimed by (\S+):/u.exec(error instanceof Error?error.message:"");throw held!==null&&await appendBusDenial(identity.runDirectory,identity.jobId,{reason:"claim-held",role:identity.role,agent_id:identity.agentId,key,holder:held[1]}).catch(()=>{}),error}let details={path:params.path,key,agent_id:identity.agentId,at:lease.at};return{content:[{type:"text",text:`claimed ${key}`}],details}}}),pi.registerTool({name:"release_path",label:"Release Path",description:"Release a same-tree path lease held by this worker",parameters:typebox_exports.Object({path:typebox_exports.String()}),async execute(_id,params,_signal,_update,context){let identity=await identityFor(context.cwd);authorizeWorkerTool(identity,"release_path");let key=await canonicalClaimKey(context.cwd,identity.jobId,identity.runDirectory,params.path),released=await releaseLease(identity.runDirectory,{agentId:identity.agentId,key},leaseDependencies);return{content:[{type:"text",text:released?`released ${key}`:`no lease on ${key}`}],details:{path:params.path,key,released}}}})),typeof pi.on=="function"&&pi.on("tool_call",async(event,ctx)=>{let identity=await resolveWorkerIdentity(ctx.cwd,options.env).catch(()=>{});if(identity!==void 0)return evaluateWorkerToolCall(event,identity)})}function evaluateWorkerToolCall(event,identity){if(MUTATION_TOOLS.has(event.toolName)&&!identity.tools.some(tool=>MUTATION_TOOLS.has(tool)))return{block:!0,reason:`${identity.role} workers publish through write_contract and never write files directly`};if(isToolCallEventType("bash",event)&&hasReadOnlyShell(identity.role)){let command=typeof event.input.command=="string"?event.input.command.trim():"",classification=classifyShellCommand(command);if(!classification.readOnly)return{block:!0,reason:`${identity.role} workers may only run read-only shell commands: ${classification.reason}`}}if(isToolCallEventType("bash",event)&&hasTestShellOnly(identity.role)){let command=typeof event.input.command=="string"?event.input.command.trim():"",gates=identity.qualityGates??[];if(gates.length===0)return{block:!0,reason:`${identity.role} workers may only run this job's declared quality gates, and none are declared`};if(!gates.includes(command))return{block:!0,reason:`${identity.role} workers may only run a declared quality gate exactly; allowed: ${gates.join(" | ")}`}}}function registerParentTools(pi,options){let buses=new Map;setLiveWorkerCountProvider(()=>{let count=0;for(let bus of buses.values())count+=bus.countLiveProcesses();return count});let parentGate=Promise.resolve(),serializeParent=operation=>{let result=parentGate.then(operation,operation);return parentGate=result.then(()=>{},()=>{}),result},activeBus=async cwd=>{let job=await readActiveJob(cwd);if(job===void 0)throw new Error("No active K-\u03C0 job");let bus=buses.get(job.jobId);return bus===void 0&&(bus=new BackgroundBus(cwd,job.directory,job.jobId,options),buses.set(job.jobId,bus)),bus},busOwning=async(cwd,agentId)=>{for(let bus of buses.values())if(bus.get(agentId)!==void 0)return bus;return activeBus(cwd)},countLiveAcrossJobs=async()=>{let workers=0,writers=0;for(let bus of buses.values()){await bus.reap();for(let worker of bus.list())workers+=1,worker.isWriter&&(writers+=1)}return{workers,writers}},liveWriter=async()=>{for(let bus of buses.values()){await bus.reap();let writer=bus.list().find(worker=>worker.isWriter);if(writer!==void 0&&bus.hasLiveWriter())return{agentId:writer.agentId,jobId:bus.jobId}}};typeof pi.registerTool=="function"&&(pi.registerTool({name:"spawn_background",label:"Spawn Background",description:"Start one local background K-\u03C0 worker; at most two workers and one writer",parameters:typebox_exports.Object({role:typebox_exports.Union(WORKER_ROLES.map(role=>typebox_exports.Literal(role))),prompt:typebox_exports.String(),model:typebox_exports.Optional(typebox_exports.String()),tools:typebox_exports.Optional(typebox_exports.Array(typebox_exports.String()))}),async execute(_id,params,_signal,_update,context){if(!isWorkerRole(params.role))throw new Error(`Unknown worker role: ${String(params.role)}`);let worker=await serializeParent(async()=>{let tools=resolveRoleTools(params.role,params.tools),wantsWriter=isWriterToolSet(tools),live=await countLiveAcrossJobs(),bus=await activeBus(context.cwd);if(live.workers>=MAX_LIVE_WORKERS)throw await bus.logDenied({reason:"worker-limit",role:params.role,limit:MAX_LIVE_WORKERS}).catch(()=>{}),new Error(`Background worker limit is ${MAX_LIVE_WORKERS}`);if(wantsWriter&&live.writers>=MAX_LIVE_WRITERS)throw await bus.logDenied({reason:"writer-live",role:params.role,limit:MAX_LIVE_WRITERS}).catch(()=>{}),new Error("A writer worker is already live");return bus.spawn({role:params.role,prompt:params.prompt,model:params.model,tools:params.tools})}),details={agent_id:worker.agentId,session_path:worker.sessionPath,pid:worker.pid,role:worker.role,tools:worker.tools,is_writer:worker.isWriter,contract_path:worker.contractPin?.declaredPath};return{content:[{type:"text",text:JSON.stringify(details)}],details}}}),pi.registerTool({name:"communicate",label:"Communicate",description:"Deliver steering or follow-up input to a background K-\u03C0 worker",parameters:typebox_exports.Object({to:typebox_exports.String(),message:typebox_exports.String(),deliverAs:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("steer"),typebox_exports.Literal("followUp")])),expect:typebox_exports.Optional(typebox_exports.Union([typebox_exports.Literal("none"),typebox_exports.Literal("ack"),typebox_exports.Literal("result")])),timeoutMs:typebox_exports.Optional(typebox_exports.Number())}),async execute(_id,params,_signal,_update,context){let outcome=await(await busOwning(context.cwd,params.to)).communicate({agentId:params.to,message:params.message,deliverAs:params.deliverAs,expect:params.expect,timeoutMs:params.timeoutMs}),details={to:params.to,expect:params.expect??"none",accepted:outcome.accepted,contract_path:outcome.contractPath,publication_id:outcome.publicationId};return{content:[{type:"text",text:JSON.stringify(details)}],details}}}),pi.registerTool({name:"agents_status",label:"Agents Status",description:"List live background workers, their pids, and their last bus event",parameters:typebox_exports.Object({}),async execute(_id,_params,_signal,_update,context){await activeBus(context.cwd).catch(()=>{});let status=(await Promise.all([...buses.values()].map(bus=>bus.status()))).flat();return{content:[{type:"text",text:JSON.stringify({agents:status.length,workers:status})}],details:{workers:status}}}}),pi.registerTool({name:"agents_stop",label:"Agents Stop",description:"Ask a worker to publish its contract and exit, then stop it",parameters:typebox_exports.Object({agent_id:typebox_exports.Optional(typebox_exports.String()),graceMs:typebox_exports.Optional(typebox_exports.Number())}),async execute(_id,params,_signal,_update,context){if(params.agent_id===void 0){let outcomes=await serializeParent(async()=>{await activeBus(context.cwd).catch(()=>{});let collected=[];for(let bus2 of buses.values()){let stopped=await bus2.publishAndStopAll(params.graceMs);for(let outcome2 of stopped)collected.push({agent_id:outcome2.agentId,job_id:bus2.jobId,stopped:outcome2.stopped,published:outcome2.published,graced:outcome2.graced,reason:outcome2.reason})}return collected});return{content:[{type:"text",text:`stopped ${outcomes.filter(entry=>entry.stopped).length} worker(s)`}],details:{stopped:outcomes}}}let outcome=await(await busOwning(context.cwd,params.agent_id)).publishAndStop(params.agent_id,params.graceMs);return{content:[{type:"text",text:outcome.stopped?`stopped ${params.agent_id}${outcome.published===void 0?"":` after publishing ${outcome.published}`}`:`no live worker ${params.agent_id}`}],details:outcome}}})),typeof pi.on=="function"&&(pi.on("tool_call",async event=>{if(!PARENT_WRITER_TOOLS.has(event.toolName))return;let writer=await liveWriter();if(writer===void 0)return;let holder=`${writer.agentId} (job ${writer.jobId})`;return{block:!0,reason:event.toolName==="bash"||event.toolName==="powershell"?`worker ${holder} holds the single-writer slot; a shell can write anything, so it is closed until that worker stops`:`worker ${holder} holds the single-writer slot; stop it before writing from this session`}}),pi.on("session_shutdown",async()=>{for(let bus of buses.values())await bus.stopAll().catch(()=>{});buses.clear()}))}import{readFile as readFile23,stat as stat10}from"node:fs/promises";import{join as join56}from"node:path";var BOARD_STAGES=[{id:"01",key:"ac-compile",label:"ac-compile"},{id:"02",key:"specify",label:"specify"},{id:"03",key:"plan",label:"plan"},{id:"04",key:"implement",label:"implement"},{id:"05",key:"test",label:"test"},{id:"06",key:"bounds",label:"bounds"},{id:"07",key:"review",label:"review"},{id:"08",key:"ship",label:"ship"}],RUN_FILE_NAMES=["task.json","context.md","candidate.json","evidence.json","verdict.json","events.jsonl"],STOP_VOCABULARY=new Set(["RUNNING","DONE","BLOCKED","EXHAUSTED","NO_PROGRESS","UNSAFE","NEEDS_HUMAN"]);function normalizeStop(raw){let upper=(raw??"RUNNING").toUpperCase();return upper==="APPROVAL"?"RUNNING":STOP_VOCABULARY.has(upper)?upper:upper==="COMPLETED"?"DONE":"RUNNING"}function stageIndex(stage){let normalized=stage.toLowerCase().replace(/^0?\d+\s+/,"").trim();if(normalized.length===0)return-1;let exact=BOARD_STAGES.findIndex(entry=>entry.key===normalized||entry.label===normalized);if(exact>=0)return exact;if(normalized==="ac_compile"||normalized==="accompile")return 0;if(normalized==="plan-check")return 2;if(normalized==="quality-green")return 4;if(normalized.endsWith("er")){let stem=normalized.slice(0,-2),byStem=BOARD_STAGES.findIndex(entry=>entry.key===stem);if(byStem>=0)return byStem}return normalized==="human-confirm"||normalized==="human_confirm"||normalized==="confirm"?7:-1}function resolveCurrentStageIndex(stage,node){let fromStage=stageIndex(stage);if(fromStage>=0)return fromStage;if(node!==void 0){let fromNode=stageIndex(node);if(fromNode>=0)return fromNode}return 0}function rowText(row){return row.map(span=>span.text).join("")}function verifierFor(model2){return model2.verifier!==void 0?model2.verifier:model2.passed===!0?"pass":model2.passed===!1?"fail":"pending"}function verifierLabel(verifier){return verifier==="pass"?"PASS":verifier==="fail"?"FAIL":"PASS/FAIL PENDING"}function shortFingerprint(value){if(value===void 0||value.length===0)return"\u2014";let hex=value.replace(/^sha256:/,"");return hex.length<=12?hex:hex.slice(0,12)}function stopTone(stop){return stop==="RUNNING"?"warning":stop==="DONE"?"success":stop==="NEEDS_HUMAN"?"accent":"error"}var LIT="\u25CF",DARK="\u25CB";function stageCells(current){return BOARD_STAGES.map((entry,index3)=>{let status=index3===current?"CURRENT":current>=0&&index3<current?"DONE":"PENDING",tone=status==="CURRENT"?"accent":status==="DONE"?"success":"dim";return{lines:[entry.id,entry.label,status],compact:`${entry.id} ${entry.label} ${status}`,tone,borderTone:status==="CURRENT"?"borderAccent":"border",lit:status==="CURRENT"}})}function stagesRegion(current,title){let cells=stageCells(current),labels=cells.map(cell=>cell.compact);return{kind:"cells",id:"stages",title,cells,compactRow:cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone})),flat:[`STAGES ${labels.slice(0,4).join(" ")}`,` ${labels.slice(4).join(" ")}`]}}function lampCells(fileLit){return RUN_FILE_NAMES.map(name=>{let lit=fileLit[name]===!0;return{lines:[name,lit?LIT:DARK,lit?"ON":"DIM"],compact:`${lit?LIT:DARK} ${name}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit}})}function lampRow(cells){return cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone}))}function lampsRegion(model2,paused){let cells=paused?RUN_FILE_NAMES.map(name=>{let lit=model2.fileLit[name]===!0;return{lines:[name,lit?LIT:DARK,name==="events.jsonl"?"APPEND":lit?"READY":"MISSING"],compact:`${lit?LIT:DARK} ${name}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit}}):lampCells(model2.fileLit),compactRow=lampRow(cells),flatLamps=rowText(compactRow);return{kind:"cells",id:"lamps",title:paused?"SHARED RUN STATE":"FILE LAMPS",cells,compactRow,flat:paused?["SHARED RUN STATE",` ${flatLamps}`]:[`FILES ${flatLamps}`]}}function contextRows(model2){let pack=model2.contextPack,rows=[[{text:`product ${pack.product?LIT:DARK}`,tone:pack.product?"text":"dim"},{text:" "},{text:`structure ${pack.structure?LIT:DARK}`,tone:pack.structure?"text":"dim"},{text:" "},{text:`tech ${pack.tech?LIT:DARK}`,tone:pack.tech?"text":"dim"}]];if(model2.research!==void 0&&(rows.push([{text:model2.research.cell,tone:"muted"}]),model2.research.struck!==void 0&&rows.push([{text:model2.research.struck,tone:"error"}])),model2.kstack!==void 0){let done=model2.kstack.todos.length;rows.push([{text:`K-STACK ${model2.kstack.playbook} ${done} steps`,tone:"text"}]),model2.kstack.todos.length>0&&rows.push([{text:`PROGRESS ${model2.kstack.todos[0]}${done>1?` \xB7 +${done-1}`:""}`,tone:"muted"}])}let cells=[{text:`AGENTS ${model2.agents}`,tone:"text"},{text:" "},{text:model2.busLit?`BUS ${LIT}`:`BUS ${DARK}`,tone:model2.busLit?"text":"dim"}];return model2.route!==void 0&&cells.push({text:" "},{text:`ROUTE ${model2.route}`,tone:"text"}),model2.usage!==void 0&&cells.push({text:" "},{text:`USAGE ${model2.usage}`,tone:"text"}),rows.push(cells),rows}function contextRegion(model2){let rows=contextRows(model2),[lamps,...rest]=rows;return{kind:"rows",id:"contextLayer",title:"CONTEXT LAYER",rows,frame:"panel",flat:[`CONTEXT LAYER ${rowText(lamps??[])}`,...rest.map(row=>` ${rowText(row)}`)]}}function iterationRegion(model2){let verifier=verifierFor(model2),fingerprint=shortFingerprint(model2.fingerprint),round=`ROUND ${model2.round}/${model2.maxRounds}`,rows=[[{text:round,tone:"text"}]];return verifier==="pending"?rows.push([{text:"PASS/FAIL PENDING",tone:"dim"}]):rows.push([{text:verifier==="pass"?`PASS ${LIT} last verifier`:`PASS ${DARK} none`,tone:verifier==="pass"?"success":"dim"}],[{text:verifier==="fail"?`FAIL ${LIT} last verifier`:`FAIL ${DARK} none`,tone:verifier==="fail"?"error":"dim"}]),rows.push([{text:`FINGERPRINT ${fingerprint}`,tone:"muted"}]),{kind:"rows",id:"iteration",title:"ITERATION LOOP",rows,frame:"panel",flat:[`${round} FINGERPRINT ${fingerprint} ${verifierLabel(verifier)}`]}}function oversightRegion(question){return{kind:"rows",id:"oversight",title:"HUMAN OVERSIGHT REQUIRED",rows:[[{text:"GATE human \u2014 ",tone:"accent"},{text:question===void 0?"confirm to continue":question,tone:"text"}]],frame:"accent",flat:["HUMAN OVERSIGHT REQUIRED"]}}function waitingRegion(question){return{kind:"rows",id:"waiting",title:"WAITING ON OPERATOR",rows:question===void 0?[]:[[{text:question,tone:"text"}]],frame:"accent",flat:[question===void 0?"WAITING ON OPERATOR":`WAITING ON OPERATOR ${question}`]}}function stopStatesRegion(stop){let cells=[["DONE",stop==="DONE"],["BLOCKED",stop==="BLOCKED"],["APPROVAL",!0]].map(([label,lit])=>({lines:[label,lit?LIT:DARK],compact:`${label} ${lit?LIT:DARK}`,tone:lit?"accent":"dim",borderTone:lit?"borderAccent":"border",lit})),compactRow=cells.map((cell,index3)=>({text:`${index3===0?"":" "}${cell.compact}`,tone:cell.tone}));return{kind:"cells",id:"stopStates",title:"STOP STATES",cells,compactRow,flat:[`STOP STATES ${rowText(compactRow)}`]}}var THREE_LAWS=["1. Outer loop owns the return path","2. Shared files are the contract","3. Irreversible effects stay outside the worker"];function threeLawsRegion(){return{kind:"rows",id:"threeLaws",title:"THREE LAWS",rows:THREE_LAWS.map(law=>[{text:law,tone:"muted"}]),frame:"panel",flat:["THREE LAWS",...THREE_LAWS.map(law=>` ${law}`)]}}function telemetryRegion(model2,current,gate){let stage=BOARD_STAGES[current]??BOARD_STAGES[0],row=[{text:`LOOP ${model2.jobId}`,tone:"text"},{text:" "},{text:`STAGE ${stage.id} ${stage.label}`,tone:"accent"},{text:" "},{text:`NODE ${model2.node}`,tone:"text"},{text:" "},{text:`GATE ${gate}`,tone:gate==="human"?"accent":"text"}];return{kind:"rows",id:"telemetry",rows:[row],frame:"none",flat:[rowText(row)]}}function headerRegion(model2,paused){let segments=[{text:paused?"K-\u03C0 PROTOCOL":"K-\u03C0 GRAPH CONTROL",tone:"accent"},{text:`MODE ${model2.mode}`,tone:"text"},{text:`JOB ${model2.jobId}`,tone:"text"},{text:`ROUND ${model2.round}/${model2.maxRounds}`,tone:"text"}];return paused&&segments.push({text:"GATE approval",tone:"accent"}),model2.kstack!==void 0&&segments.push({text:"K-STACK on",tone:"success"}),{kind:"strip",id:"header",segments,flat:[segments.map(segment2=>segment2.text).join(" ")]}}function buildBoardRegions(model2){let current=resolveCurrentStageIndex(model2.stage,model2.node),paused=model2.paused,gate=model2.gate??(paused?"human":"machine"),question=model2.pendingQuestion?.trim(),pending=question!==void 0&&question.length>0?question:void 0,regions=[headerRegion(model2,paused),telemetryRegion(model2,current,gate),contextRegion(model2),stagesRegion(current,paused?"STAGE RAIL":"STAGES 01\u201308"),iterationRegion(model2)];paused&&regions.push(oversightRegion(pending),waitingRegion(pending)),regions.push(lampsRegion(model2,paused)),paused&&regions.push(stopStatesRegion(model2.stop),threeLawsRegion()),regions.push({kind:"stop",id:"stop",text:`STOP ${model2.stop}`,tone:stopTone(model2.stop),flat:[`STOP ${model2.stop}`]});let byId={};for(let region of regions)byId[region.id]=region;return{variant:paused?"blue":"amber",regions,byId}}function flattenRegions(regions){return regions.regions.flatMap(region=>region.flat)}function renderBoard(model2){return fitBoard(flattenRegions(buildBoardRegions(model2)),model2.width)}var LAMP_SEPARATOR=" ";function isFileLampRow(line){return RUN_FILE_NAMES.every(name=>line.includes(name))}function foldLamps(line,width){let indent=line.slice(0,line.length-line.trimStart().length),body=line.slice(indent.length),label=body.startsWith("FILES")?"FILES":"",lamps=body.slice(label.length).trim().split(LAMP_SEPARATOR).filter(lamp=>lamp.length>0);if(lamps.length===0)return[line];let firstPrefix=label.length>0?`${indent}${label}${LAMP_SEPARATOR}`:indent,continuationPrefix=`${indent}${LAMP_SEPARATOR}`,rows=[],current="",prefix=firstPrefix;for(let lamp of lamps){let candidate=current.length===0?`${prefix}${lamp}`:`${current}${LAMP_SEPARATOR}${lamp}`;if(current.length>0&&visibleWidth(candidate)>width){rows.push(current),prefix=continuationPrefix,current=`${prefix}${lamp}`;continue}current=candidate}return current.length>0&&rows.push(current),rows}function truncatePlain(text,width){if(visibleWidth(text)<=width)return text;let out="";for(let character of text){if(visibleWidth(out+character)>width-1)break;out+=character}return`${out}\u2026`}function clamp3(line,width){return truncatePlain(line,width)}var STAGE_CELL_PATTERN=/\d{2} \S+ (?:DONE|CURRENT|PENDING)/gu,STAGE_CELL_SEPARATOR=" ";function isStageRow(line){return line.match(STAGE_CELL_PATTERN)!==null}function foldStages(line,width){let cells=(line.match(STAGE_CELL_PATTERN)??[]).filter(cell=>!cell.endsWith("CURRENT")),label=line.trimStart().startsWith("STAGES")?"STAGES":"",rows=[],current="",prefix=label.length>0?`${label} `:" ";for(let cell of cells){let candidate=current.length===0?`${prefix}${cell}`:`${current}${STAGE_CELL_SEPARATOR}${cell}`;if(current.length>0&&visibleWidth(candidate)>width){rows.push(current),prefix=" ",current=`${prefix}${cell}`;continue}current=candidate}return current.length>0&&rows.push(current),rows}function fitHeader(line,width){if(visibleWidth(line)<=width)return line;let segments=line.split(" "),job=segments.findIndex(segment2=>segment2.startsWith("JOB "));if(job!==-1){let excess=visibleWidth(line)-width,keep=Math.max(10,visibleWidth(segments[job]??"")-excess);segments[job]=truncatePlain(segments[job]??"",keep)}return clamp3(segments.join(" "),width)}function isEssentialRow(line){return line.includes("CURRENT")||line.startsWith("STOP ")||line.startsWith("K-\u03C0")||line.startsWith("WAITING ON OPERATOR")||line.startsWith("HUMAN OVERSIGHT")}function fitBoard(lines,width){if(width===void 0||width<=0||width>=100)return[...lines];let essential=[];for(let line of lines){if(line.includes("CURRENT")){let match2=/(\d{2}\s+\S+)\s+CURRENT/u.exec(line),marker=match2!==null?`${match2[1]} CURRENT`:"CURRENT";essential.push(clamp3(marker,width));continue}isEssentialRow(line)&&essential.push(line.startsWith("K-\u03C0")?fitHeader(line,width):clamp3(line,width))}let rest=[];for(let line of lines)if(!(isEssentialRow(line)&&!line.includes("CURRENT"))){if(isFileLampRow(line)){rest.push(...foldLamps(line,width));continue}if(isStageRow(line)){rest.push(...foldStages(line,width));continue}rest.push(clamp3(line,width))}return[...essential,...rest]}function researchCellFromDocument(document){let network=document.network;if(network!==void 0){if(network.state==="online"){let external=(document.sources??[]).filter(source2=>source2.kind==="external");return{cell:`RESEARCH ${external.find(source2=>typeof source2.service=="string"&&source2.service.length>0)?.service??document.mode??"exa"} ${external.length} src`}}if(network.state==="no-network"){if((network.origin==="engine"?"engine":"operator")==="operator")return{cell:"RESEARCH local \xB7 no-network operator"};let reason=typeof network.reason=="string"&&network.reason.length>0?network.reason:"exhausted",failed=new Set((network.failures??[]).map(failure=>failure.service?.toLowerCase()).filter(service=>typeof service=="string")),struck=["exa","perplexity"].filter(service=>failed.has(service)||failed.has(service==="perplexity"?"pplx":service)).map(service=>service==="perplexity"?"PPLX \u2715":"EXA \u2715").join(" "),marks=struck.length>0?struck:((network.failures??[]).length>0,"EXA \u2715 PPLX \u2715");return{cell:`RESEARCH local \xB7 no-network engine \xB7 ${reason}`,struck:marks}}}}var PLAIN_PALETTE={paint:(_tone,text)=>text};function paletteFromTheme(theme2){return{paint:(tone,text)=>text.length===0?text:theme2.fg(tone,text)}}var DEFAULT_FRAME_MIN_WIDTH=70,DEFAULT_COLUMNS_MIN_WIDTH=100,STRIP_SEPARATOR=" \u2502 ";function pad(text,width){let missing=width-visibleWidth(text);return missing>0?text+" ".repeat(missing):text}function fitWidth(text,width){return pad(truncatePlain(text,width),width)}function center(text,width){let missing=width-visibleWidth(text);if(missing<=0)return fitWidth(text,width);let left=Math.floor(missing/2);return" ".repeat(left)+text+" ".repeat(missing-left)}function paintRow(row,width,palette,fallback="text"){let plain=rowText(row);return visibleWidth(plain)>width?palette.paint(fallback,fitWidth(plain,width)):row.map(span=>palette.paint(span.tone??fallback,span.text)).join("")+" ".repeat(width-visibleWidth(plain))}function wrapWords(text,width){let lines=[],current="";for(let word of text.split(/\s+/u).filter(part=>part.length>0)){let candidate=current.length===0?word:`${current} ${word}`;if(current.length>0&&visibleWidth(candidate)>width){lines.push(current),current=word;continue}current=candidate}return current.length>0&&lines.push(current),lines.length===0?[""]:lines}function framePanel(region,width,palette){let borderTone=region.frame==="accent"?"borderAccent":"border",inner=Math.max(1,width-4),bar=palette.paint(borderTone,"\u2502"),line=content=>`${bar} ${content} ${bar}`,lines=[palette.paint(borderTone,`\u250C${"\u2500".repeat(width-2)}\u2510`)];region.title!==void 0&&lines.push(line(palette.paint("accent",fitWidth(region.title,inner))));for(let row of region.rows){let plain=rowText(row);if(visibleWidth(plain)>inner&&row.length===1){let tone=row[0]?.tone??"text";for(let part of wrapWords(plain,inner))lines.push(line(palette.paint(tone,pad(part,inner))));continue}lines.push(line(paintRow(row,inner,palette)))}return lines.push(palette.paint(borderTone,`\u2514${"\u2500".repeat(width-2)}\u2518`)),lines}function cellLayout(cells,width,lines){let widest=Math.max(...cells.map(cell=>Math.max(...lines(cell).map(text=>visibleWidth(text))))),fitting=natural2=>Math.min(cells.length,Math.max(1,Math.floor((width-1)/(natural2+1)))),natural=widest+2;fitting(natural)<cells.length&&fitting(widest)===cells.length&&(natural=widest);let rows=Math.ceil(cells.length/fitting(natural)),perRow=Math.ceil(cells.length/rows),cellInner=Math.max(natural,Math.floor((width-(perRow+1))/perRow));return{perRow,cellInner}}function junctionTone(left,right){return right?.lit?right.borderTone:left?.lit?left.borderTone:left?.borderTone??right?.borderTone??"border"}function borderLine(cells,cellInner,glyphs,palette){let[open10,join70,close]=glyphs,out=palette.paint(junctionTone(void 0,cells[0]),open10);return cells.forEach((cell,index3)=>{out+=palette.paint(cell.borderTone,"\u2500".repeat(cellInner));let next=cells[index3+1];out+=palette.paint(junctionTone(cell,next),next===void 0?close:join70)}),out}function textLine(cells,cellInner,texts,palette){let out=palette.paint(junctionTone(void 0,cells[0]),"\u2502");return cells.forEach((cell,index3)=>{out+=palette.paint(cell.tone,center(texts[index3]??"",cellInner)),out+=palette.paint(junctionTone(cell,cells[index3+1]),"\u2502")}),out}function frameCells(region,width,layout,palette){let twoLine=cell=>cell.lines.length>2?[cell.lines.slice(0,-1).join(" "),cell.lines.at(-1)??""]:cell.lines,oneLine=cell=>[cell.compact],bodyOf=layout==="full"?cell=>cell.lines:twoLine,{perRow,cellInner}=cellLayout(region.cells,width,bodyOf);if(layout==="compact"&&perRow<region.cells.length){let single=cellLayout(region.cells,width,oneLine),rowsOf2=per=>Math.ceil(region.cells.length/per);rowsOf2(single.perRow)*3<rowsOf2(perRow)*4&&(bodyOf=oneLine,{perRow,cellInner}=single)}let out=[];layout==="full"&&out.push(palette.paint("accent",fitWidth(region.title,width)));for(let start=0;start<region.cells.length;start+=perRow){let row=region.cells.slice(start,start+perRow),height=Math.max(...row.map(cell=>bodyOf(cell).length));out.push(pad(borderLine(row,cellInner,["\u250C","\u252C","\u2510"],palette),width));for(let line=0;line<height;line+=1)out.push(pad(textLine(row,cellInner,row.map(cell=>bodyOf(cell)[line]??""),palette),width));out.push(pad(borderLine(row,cellInner,["\u2514","\u2534","\u2518"],palette),width))}return out}function frameStrip(strip,width,palette,boxed){let inner=boxed?width-4:width,separator=palette.paint("dim",STRIP_SEPARATOR),segments=strip.segments.map(segment2=>({...segment2})),plainWidth=()=>segments.reduce((sum,segment2)=>sum+visibleWidth(segment2.text),0)+STRIP_SEPARATOR.length*Math.max(0,segments.length-1),job=segments.find(segment2=>segment2.text.startsWith("JOB "));if(job!==void 0&&plainWidth()>inner){let spare=Math.max(6,visibleWidth(job.text)-(plainWidth()-inner));job.text=truncatePlain(job.text,spare)}let painted=segments.map(segment2=>palette.paint(segment2.tone??"text",segment2.text)).join(separator),line=pad(plainWidth()<=inner?painted:palette.paint("text",fitWidth(rowText(segments),inner)),inner);if(!boxed)return[line];let bar=palette.paint("border","\u2502");return[palette.paint("border",`\u250C${"\u2500".repeat(width-2)}\u2510`),`${bar} ${line} ${bar}`,palette.paint("border",`\u2514${"\u2500".repeat(width-2)}\u2518`)]}function sideBySide(left,right,leftWidth,gap){let height=Math.max(left.length,right.length),rightWidth=Math.max(...right.map(line=>visibleWidth(line)),0),out=[];for(let index3=0;index3<height;index3+=1)out.push(`${pad(left[index3]??"",leftWidth)}${" ".repeat(gap)}${pad(right[index3]??"",rightWidth)}`);return out}function stopBox(text,tone,palette){let inner=visibleWidth(text)+2;return[palette.paint(tone,`\u250C${"\u2500".repeat(inner)}\u2510`),`${palette.paint(tone,"\u2502")} ${palette.paint(tone,text)} ${palette.paint(tone,"\u2502")}`,palette.paint(tone,`\u2514${"\u2500".repeat(inner)}\u2518`)]}function rightAlign(block,width){return block.map(line=>" ".repeat(Math.max(0,width-visibleWidth(line)))+line)}function paintFlat(regions,width,palette){let toneFor=line=>line.startsWith("K-\u03C0")?"accent":line.startsWith("STOP ")&&!line.startsWith("STOP STATES")?regions.byId.stop?.kind==="stop"?regions.byId.stop.tone:"warning":line.includes("CURRENT")||line.startsWith("WAITING ON OPERATOR")||line.startsWith("HUMAN OVERSIGHT")?"accent":"text";return fitBoard(flattenRegions(regions),width).map(line=>palette.paint(toneFor(line),line))}function rowsOf(region){return region?.kind==="rows"?region:void 0}function cellsOf(region){return region?.kind==="cells"?region:void 0}function telemetryBlock(regions,width,palette,layout){let lines=[],telemetry=rowsOf(regions.byId.telemetry);if(telemetry!==void 0)for(let row of telemetry.rows)lines.push(paintRow(row,width,palette));if(layout==="compact"){let iteration=rowsOf(regions.byId.iteration);if(iteration!==void 0){let spans=[];iteration.rows.forEach((row,index3)=>{index3>0&&spans.push({text:" "}),spans.push(...row)}),lines.push(paintRow(spans,width,palette))}let waiting=rowsOf(regions.byId.waiting);if(waiting!==void 0){let label="WAITING ON OPERATOR ",question=waiting.rows[0]===void 0?"":rowText(waiting.rows[0]);wrapWords(question,Math.max(8,width-label.length)).forEach((part,index3)=>{lines.push(paintRow(index3===0?[{text:"WAITING ON OPERATOR",tone:"accent"},{text:` ${part}`,tone:"text"}]:[{text:" ".repeat(label.length)},{text:part,tone:"text"}],width,palette))})}else{let context=rowsOf(regions.byId.contextLayer),summary=context?.rows.at(-1),lamps=context?.rows[0];lamps!==void 0&&summary!==void 0&&lines.push(paintRow([{text:"CONTEXT ",tone:"muted"},...lamps,{text:" "},...summary],width,palette))}let stopStates=cellsOf(regions.byId.stopStates);stopStates!==void 0&&lines.push(paintRow([{text:"STOP STATES ",tone:"text"},...stopStates.compactRow],width,palette))}return lines}function telemetryWithStop(regions,width,palette){let stop=regions.byId.stop;if(stop?.kind!=="stop")return telemetryBlock(regions,width,palette,"compact");let box2=stopBox(stop.text,stop.tone,palette),boxWidth=visibleWidth(stop.text)+4,leftWidth=width-boxWidth-2,cut=telemetryBlock(regions,leftWidth,PLAIN_PALETTE,"compact").some(line=>line.trimEnd().endsWith("\u2026"));return leftWidth<24||cut?[...telemetryBlock(regions,width,palette,"compact"),...rightAlign(box2,width)]:sideBySide(telemetryBlock(regions,leftWidth,palette,"compact"),box2,leftWidth,2)}function foldRow(prefix,items,width,palette){let indent=" ".repeat(visibleWidth(prefix.text)),rows=[],current=[prefix],used=visibleWidth(prefix.text);for(let item of items){let text=item.text.trimStart(),spacer=current.length===1?"":" ";if(current.length>1&&used+visibleWidth(spacer+text)>width){rows.push(current),current=[{text:indent}],used=indent.length,current.push({text,tone:item.tone}),used+=visibleWidth(text);continue}current.push({text:`${spacer}${text}`,tone:item.tone}),used+=visibleWidth(spacer+text)}return rows.push(current),rows.map(row=>paintRow(row,width,palette))}function paintCompact(regions,width,palette){let out=[],header2=regions.byId.header;header2?.kind==="strip"&&out.push(...frameStrip(header2,width,palette,!1));let stages=cellsOf(regions.byId.stages);stages!==void 0&&out.push(...frameCells(stages,width,"compact",palette));let lamps=cellsOf(regions.byId.lamps);return lamps!==void 0&&out.push(...foldRow({text:"FILES ",tone:"text"},lamps.compactRow,width,palette)),out.push(...telemetryWithStop(regions,width,palette)),out}function paintColumns(left,right,width,columnsMinWidth){if(right===void 0)return left;if(width<columnsMinWidth)return[...left,...right];let leftWidth=Math.floor((width-2)*.4);return sideBySide(left,right,leftWidth,2)}function paintFull(regions,width,palette,columnsMinWidth){let columnWidths=width<columnsMinWidth?[width,width]:[Math.floor((width-2)*.4),width-2-Math.floor((width-2)*.4)],out=[],header2=regions.byId.header;header2?.kind==="strip"&&out.push(...frameStrip(header2,width,palette,!0)),out.push(...telemetryBlock(regions,width,palette,"full"));let context=rowsOf(regions.byId.contextLayer);context!==void 0&&out.push(...framePanel(context,width,palette));let stages=cellsOf(regions.byId.stages);stages!==void 0&&out.push(...frameCells(stages,width,"full",palette));let iteration=rowsOf(regions.byId.iteration),oversight=rowsOf(regions.byId.oversight);if(iteration!==void 0){let left=framePanel(iteration,oversight===void 0?width:columnWidths[0],palette),right=oversight===void 0?void 0:framePanel(oversight,columnWidths[1],palette);out.push(...paintColumns(left,right,width,columnsMinWidth))}let lamps=cellsOf(regions.byId.lamps);lamps!==void 0&&out.push(...frameCells(lamps,width,"full",palette));let stopStates=cellsOf(regions.byId.stopStates),laws=rowsOf(regions.byId.threeLaws);if(stopStates!==void 0&&laws!==void 0){let left=frameCells(stopStates,width<columnsMinWidth?width:columnWidths[0],"full",palette),right=framePanel(laws,columnWidths[1],palette);out.push(...paintColumns(left,right,width,columnsMinWidth))}let waiting=rowsOf(regions.byId.waiting);waiting!==void 0&&out.push(...framePanel(waiting,width,palette));let stop=regions.byId.stop;return stop?.kind==="stop"&&out.push(...rightAlign(stopBox(stop.text,stop.tone,palette),width)),out.map(line=>pad(line,width))}function paintRegions(regions,options){let palette=options.palette??PLAIN_PALETTE,width=Math.max(1,Math.floor(options.width));if(width<(options.frameMinWidth??DEFAULT_FRAME_MIN_WIDTH))return paintFlat(regions,width,palette);let columnsMinWidth=options.columnsMinWidth??DEFAULT_COLUMNS_MIN_WIDTH;return options.layout==="compact"?paintCompact(regions,width,palette):paintFull(regions,width,palette,columnsMinWidth)}function paintBoard(model2,options){return paintRegions(buildBoardRegions(model2),options)}function createBoardComponent(model2,options){let current=model2,cache;return{render(width){if(cache!==void 0&&cache.width===width&&cache.model===current)return cache.lines;let lines=paintBoard(current,{width,layout:options.layout,palette:options.palette});return cache={width,model:current,lines},lines},invalidate(){cache=void 0},refresh(next){current=next,cache=void 0},dispose(){cache=void 0,options.onDispose?.()}}}import{execFile as execFileCallback2}from"node:child_process";import{createHash as createHash7,randomUUID as randomUUID14}from"node:crypto";import{readdir as readdir6,readFile as readFile22,realpath as realpath4,stat as stat9}from"node:fs/promises";import{basename as basename17,join as join55,relative as relative9,resolve as resolve20,sep as sep12}from"node:path";import{promisify as promisify2}from"node:util";function trimWrappingQuotes(value){let trimmed=value.trim(),first=trimmed[0],last=trimmed.at(-1);return trimmed.length>=2&&(first==="`"&&last==="`"||first==='"'&&last==='"'||first==="'"&&last==="'")?trimmed.slice(1,-1).trim():trimmed}function parseCommandCheck(input){let match2=/\bcmd\s+(.+?)\s+exits?\s+(-?\d+)\b/i.exec(input);if(match2===null)return;let cmd=trimWrappingQuotes(match2[1]);if(cmd.length!==0)return{kind:"command",cmd,expect:{exit:Number.parseInt(match2[2],10)}}}function parseWriteBounds(input){let match2=/\bwrites?\s+only\s+(.+?)(?=\s*;|\n|$)/i.exec(input);if(match2===null)return;let writeAllow=match2[1].trim().replace(/[.!?]+$/,"").split(/\s*(?:,|\band\b)\s*/i).map(trimWrappingQuotes).filter(path14=>path14.length>0);return writeAllow.length>0?{write_allow:writeAllow}:void 0}function scoreCompiledCriteria(criteria){let requiredCriteria=criteria.filter(criterion=>criterion.required),missingChecks=requiredCriteria.flatMap(criterion=>{let missing=[];return criterion.check===void 0&&missing.push("check"),criterion.bounds===void 0&&missing.push("bounds"),missing.length===0?[]:[{id:criterion.id,statement:criterion.statement,missing}]});return requiredCriteria.length===0?{quality:"narrative",missingChecks}:missingChecks.length===0?{quality:"executable",missingChecks}:{quality:requiredCriteria.some(criterion=>criterion.check!==void 0||criterion.bounds!==void 0)?"partial":"narrative",missingChecks}}function acceptanceStatements(input){let labeled=input.split(/\r?\n/u).map(line=>line.trim()).filter(line=>line.length>0).map(line=>/^(AC-\d+(?:\.\d+)?):\s*(.+)$/iu.exec(line));return labeled.length>0&&labeled.every(match2=>match2!==null)?labeled.map(match2=>({id:match2[1].toUpperCase(),statement:match2[2].trim().replace(/\s+/g," ")})):[{id:"AC-01",statement:input.trim().replace(/\s+/g," ")}]}function compileAcceptanceCriteria(input){let acceptance=acceptanceStatements(input).map(({id,statement})=>({id,statement,required:!0,check:parseCommandCheck(statement),bounds:parseWriteBounds(statement)}));return{acceptance,...scoreCompiledCriteria(acceptance)}}import{mkdir as mkdir11,readdir as readdir5,readFile as readFile20}from"node:fs/promises";import{basename as basename16,isAbsolute as isAbsolute9,join as join53,relative as relative8,resolve as resolve19}from"node:path";import{isDeepStrictEqual as isDeepStrictEqual2}from"node:util";import{execFile as execFileCallback}from"node:child_process";import{constants as constants7}from"node:fs";import{copyFile,mkdir as mkdir10,readFile as readFile19,stat as stat8}from"node:fs/promises";import{isAbsolute as isAbsolute8,join as join52,relative as relative7,resolve as resolve18,sep as sep11}from"node:path";import{promisify}from"node:util";import{createHash as createHash6,randomUUID as randomUUID13}from"node:crypto";import{appendFile,mkdir as mkdir9,readFile as readFile18,rename as rename5,rm as rm6,writeFile as writeFile2}from"node:fs/promises";import{basename as basename15,join as join51,relative as relative6,resolve as resolve17,sep as sep10}from"node:path";var CLAIM_STATUSES=["proposed","verified","rejected","superseded"],RECORD_FILES={source:"sources.jsonl",node:"nodes.jsonl",edge:"edges.jsonl"},PATCH_KINDS=["source","node","edge"],OBSERVED_AT_PATTERN=/^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:[Zz]|[+-]\d{2}:\d{2})$/u;function assertEnvelope(value,label){if(!isJsonObject(value))throw new Error(`${label} must be an object`);for(let field2 of["id","kind"]){let text=value[field2];if(typeof text!="string"||text.length===0)throw new Error(`${label}.${field2} is required`)}if(!Array.isArray(value.source_ids)||value.source_ids.some(id=>typeof id!="string"||id.length===0))throw new Error(`${label}.source_ids must be an array of source ids`);if(typeof value.status!="string"||!CLAIM_STATUSES.includes(value.status))throw new Error(`${label}.status must be one of ${CLAIM_STATUSES.join(", ")}`);if(typeof value.observed_at!="string"||!OBSERVED_AT_PATTERN.test(value.observed_at)||Number.isNaN(Date.parse(value.observed_at)))throw new Error(`${label}.observed_at must be an RFC 3339 date-time`);for(let field2 of["valid_from","valid_to"]){let instant=value[field2];if(instant!==void 0&&(typeof instant!="string"||Number.isNaN(Date.parse(instant))))throw new Error(`${label}.${field2} must be an RFC 3339 date-time`)}let rev=value.rev;if(rev!==void 0&&(typeof rev!="number"||!Number.isInteger(rev)||rev<1))throw new Error(`${label}.rev must be a positive integer`)}function validatePatch(value){if(!isJsonObject(value))throw new Error("knowledge graph patch must be an object");for(let key of Object.keys(value))if(!PATCH_KINDS.includes(key))throw new Error(`knowledge graph patch has an unsupported member ${key}`);let kinds=PATCH_KINDS.filter(kind=>value[kind]!==void 0);if(kinds.length===0)throw new Error("knowledge graph patch must carry a source, a node, or an edge");for(let kind of kinds)assertEnvelope(value[kind],`patch ${kind}`);let source2=value.source;if(isJsonObject(source2)){let uri=source2.uri;if(typeof uri!="string"||uri.length===0)throw new Error("patch source.uri is required")}let node=value.node;if(isJsonObject(node)&&node.source_ids.length===0)throw new Error("patch node.source_ids must cite at least one source");let edge=value.edge;if(isJsonObject(edge)){for(let field2 of["from","to"]){let endpoint=edge[field2];if(typeof endpoint!="string"||endpoint.length===0)throw new Error(`patch edge.${field2} is required`)}if(edge.source_ids.length===0)throw new Error("patch edge.source_ids must cite at least one source");let confidence=edge.confidence;if(confidence!==void 0&&(typeof confidence!="number"||confidence<0||confidence>1))throw new Error("patch edge.confidence must be between 0 and 1")}}function nextRevision(existing,id,requested,label){let next=existing.filter(record=>record.id===id).reduce((rev,record)=>Math.max(rev,record.rev),0)+1;if(requested!==void 0&&requested!==next)throw new Error(`${label} revision must be monotonic: expected ${next}, received ${requested}`);return next}function resolveAcceptance(patch,state2){let accepted={};patch.source!==void 0&&(accepted.source={...patch.source,rev:nextRevision(state2.sources,patch.source.id,patch.source.rev,`source ${patch.source.id}`)});let sourceIds=new Set(state2.sources.map(source2=>source2.id));accepted.source!==void 0&&sourceIds.add(accepted.source.id);let nodeIds=new Set(state2.nodes.map(node=>node.id));if(patch.node!==void 0){for(let id of patch.node.source_ids)if(!sourceIds.has(id))throw new Error(`node ${patch.node.id} cites unknown source ${id}`);let node={...patch.node,rev:nextRevision(state2.nodes,patch.node.id,patch.node.rev,`node ${patch.node.id}`)};accepted.node=node,nodeIds.add(node.id)}if(patch.edge!==void 0){for(let id of patch.edge.source_ids)if(!sourceIds.has(id))throw new Error(`edge ${patch.edge.id} cites unknown source ${id}`);for(let endpoint of[patch.edge.from,patch.edge.to])if(!nodeIds.has(endpoint))throw new Error(`edge ${patch.edge.id} references unknown node ${endpoint}`);accepted.edge={...patch.edge,rev:nextRevision(state2.edges,patch.edge.id,patch.edge.rev,`edge ${patch.edge.id}`)}}return accepted}var SNAPSHOT_COMPLETE_MARKER=".complete";function knowledgeGraphPaths(cwd){let root=join51(cwd,CONFIG_DIR_NAME,"kg");return{root,inbox:join51(root,"inbox"),snapshots:join51(root,"snapshots"),sources:join51(root,RECORD_FILES.source),nodes:join51(root,RECORD_FILES.node),edges:join51(root,RECORD_FILES.edge)}}function isAuthoritativeKnowledgeGraphPath(cwd,path14){let relativePath=relative6(resolve17(cwd),resolve17(cwd,path14)).split(sep10).join("/");if(relativePath.length===0||relativePath.startsWith("../"))return!1;let segments=relativePath.split("/");return segments.length<3||segments[0]!==CONFIG_DIR_NAME||segments[1]!=="kg"?!1:segments[2]!=="inbox"}var writeQueues=new Map;function serialize(root,operation){let result=(writeQueues.get(root)??Promise.resolve()).then(operation,operation);return writeQueues.set(root,result.catch(()=>{})),result}async function readRecords(path14){try{return(await readFile18(path14,"utf8")).split(`
1342
1344
  `).filter(line=>line.length>0).map(line=>JSON.parse(line))}catch(error){if(error.code==="ENOENT")return[];throw error}}var KnowledgeGraphProposals=class{constructor(cwd,options={}){this.paths=knowledgeGraphPaths(cwd),this.now=options.now??Date.now}async propose(patch){return validatePatch(patch),serialize(this.paths.root,async()=>{await mkdir9(this.paths.inbox,{recursive:!0});let path14=join51(this.paths.inbox,`${this.now()}-${randomUUID13()}.json`);return await writeFile2(path14,`${JSON.stringify(patch)}
1343
1345
  `,{flag:"wx"}),path14})}async read(){let[sources,nodes,edges]=await Promise.all([readRecords(this.paths.sources),readRecords(this.paths.nodes),readRecords(this.paths.edges)]);return{sources,nodes,edges}}async query(text=""){let{nodes}=await this.read();if(text.length===0)return nodes;let needle=text.toLowerCase();return nodes.filter(node=>JSON.stringify(node).toLowerCase().includes(needle))}},KnowledgeGraphControlPlane=class extends KnowledgeGraphProposals{constructor(cwd,options={}){super(cwd,options),this.afterSnapshot=options.afterSnapshot}assertInboxPatch(patchPath){if(resolve17(this.paths.inbox,basename15(patchPath))!==resolve17(patchPath))throw new Error(`Knowledge graph accepts inbox patches only: ${patchPath}`)}accept(patchPath){return serialize(this.paths.root,async()=>{this.assertInboxPatch(patchPath);let patch=JSON.parse(await readFile18(patchPath,"utf8"));validatePatch(patch);let accepted=resolveAcceptance(patch,await this.read()),snapshotPath=await this.snapshot();await this.afterSnapshot?.(snapshotPath);for(let kind of PATCH_KINDS){let record=accepted[kind];record!==void 0&&await appendFile(join51(this.paths.root,RECORD_FILES[kind]),`${JSON.stringify(record)}
1344
1346
  `,"utf8")}return await rm6(patchPath),accepted})}async snapshot(){let stamp=new Date(this.now()).toISOString().replaceAll(":","-"),target=join51(this.paths.snapshots,`${stamp}-${randomUUID13()}`);await mkdir9(target,{recursive:!0});let files={};for(let kind of PATCH_KINDS){let name=RECORD_FILES[kind],content="";try{content=await readFile18(join51(this.paths.root,name),"utf8")}catch(error){if(error.code!=="ENOENT")throw error}await writeFile2(join51(target,name),content),files[name]={records:content.split(`
1345
1347
  `).filter(line=>line.length>0).length,sha256:createHash6("sha256").update(content).digest("hex")}}let manifest={capturedAt:stamp,files};await writeFile2(join51(target,"manifest.json"),`${JSON.stringify(manifest,null,2)}
1346
1348
  `);let marker=join51(target,`${SNAPSHOT_COMPLETE_MARKER}.tmp`);return await writeFile2(marker,`ok
1347
- `),await rename5(marker,join51(target,SNAPSHOT_COMPLETE_MARKER)),target}};var ParseError3=class extends Error{},READ_ONLY={readOnly:!0};function notReadOnly(reason,segment2){return segment2===void 0?{readOnly:!1,reason}:{readOnly:!1,reason,segment:segment2}}var Scanner=class{constructor(source2){this.index=0,this.word="",this.wordStarted=!1,this.current={words:[],redirects:[],substitutions:[]},this.commands=[],this.caseDepth=0,this.source=source2}scan(){for(;this.index<this.source.length;)this.step();return this.endWord(),this.endCommand(),this.commands}peek(offset=0){return this.source[this.index+offset]??""}take(){let character=this.source[this.index]??"";return this.index+=1,character}append(text){this.word+=text,this.wordStarted=!0}endWord(){this.wordStarted&&this.current.words.push(this.word),this.word="",this.wordStarted=!1}endCommand(){this.endWord();let{words:words2,redirects,substitutions}=this.current;(words2.length>0||redirects.length>0||substitutions.length>0)&&(this.commands.push(this.current),this.trackCase(words2)),this.current={words:[],redirects:[],substitutions:[]}}trackCase(words2){words2[0]==="case"&&(this.caseDepth+=1),words2.includes("esac")&&this.caseDepth>0&&(this.caseDepth-=1)}step(){let character=this.peek();if(character===" "||character===" "){this.take(),this.endWord();return}if(character==="#"&&!this.wordStarted){this.skipComment();return}this.stepOperator(character)||this.stepQuote(character)||this.stepExpansion(character)||this.stepRedirect(character)||this.stepGroup(character)||this.append(this.take())}skipComment(){for(;this.index<this.source.length&&this.peek()!==`
1348
- `;)this.take()}stepOperator(character){if(character===`
1349
- `||character===";"){for(this.take();this.peek()===";"||this.peek()==="&";)this.take();return this.endCommand(),!0}if(character==="|")return this.take(),(this.peek()==="|"||this.peek()==="&")&&this.take(),this.endCommand(),!0;if(character==="&"){if(this.peek(1)==="&")return this.take(),this.take(),this.endCommand(),!0;if(this.peek(1)===">")return!1;throw new ParseError3("a background job (&) cannot be classified")}return!1}stepQuote(character){return character==="\\"?(this.take(),this.append(this.take()),!0):character==="'"||character==="$"&&this.peek(1)==="'"?(character==="$"&&this.take(),this.take(),this.append(this.readUntil("'","an unterminated single quote")),this.take(),!0):character==='"'?(this.take(),this.readDoubleQuoted(),!0):!1}readUntil(terminator,failure){let end=this.source.indexOf(terminator,this.index);if(end<0)throw new ParseError3(failure);let text=this.source.slice(this.index,end);return this.index=end,text}readDoubleQuoted(){for(this.wordStarted=!0;;){if(this.index>=this.source.length)throw new ParseError3("an unterminated double quote");let character=this.peek();if(character==='"'){this.take();return}if(character==="\\"){this.take(),this.append(this.take());continue}if(character==="`"||character==="$"&&this.peek(1)==="("){this.captureSubstitution();continue}if(character==="$"&&this.peek(1)==="{"){this.take(),this.append(this.readParameterExpansion());continue}this.append(this.take())}}stepExpansion(character){return character==="`"?(this.captureSubstitution(),!0):character!=="$"?!1:this.peek(1)==="("&&this.peek(2)==="("?(this.take(),this.append(this.readBalanced("(",")")),!0):this.peek(1)==="("?(this.captureSubstitution(),!0):this.peek(1)==="{"?(this.take(),this.append(this.readParameterExpansion()),!0):(this.append(this.take()),!0)}captureSubstitution(){if(this.wordStarted=!0,this.peek()==="`"){this.take();let body2=this.readUntil("`","an unterminated backtick");this.take(),this.current.substitutions.push(body2),this.append("`\u2026`");return}this.take();let body=this.readBalanced("(",")");this.current.substitutions.push(body.slice(1,-1)),this.append("$(\u2026)")}readBalanced(open10,close){let depth=0,start=this.index;for(;this.index<this.source.length;){let character=this.take();if(character==="\\"){this.take();continue}if(character==="'"){this.readUntil("'","an unterminated single quote"),this.take();continue}if(character===open10&&(depth+=1),character===close&&(depth-=1,depth===0))return this.source.slice(start,this.index)}throw new ParseError3(`an unbalanced ${open10}`)}readParameterExpansion(){let body=this.readBalanced("{","}");if(body.includes("$(")||body.includes("`"))throw new ParseError3("a command substitution inside a parameter expansion");return`$${body}`}stepRedirect(character){if(character!=="<"&&character!==">"&&!(character==="&"&&this.peek(1)===">"))return!1;let descriptor="";this.wordStarted&&/^\d$/u.test(this.word)?(descriptor=this.word,this.word="",this.wordStarted=!1):this.endWord();let operator2=this.readRedirectOperator(),target=this.readRedirectTarget();return this.current.redirects.push(`${descriptor}${operator2}${target}`),!0}readRedirectOperator(){let operator2=this.take();for(operator2==="&"&&(operator2+=this.take());this.peek()===">"||this.peek()==="<"||this.peek()==="&"||this.peek()==="|";)operator2+=this.take();if(operator2.includes("<<"))throw new ParseError3("a heredoc or here-string");if(this.peek()==="(")throw new ParseError3("a process substitution");return operator2}readRedirectTarget(){for(;this.peek()===" "||this.peek()===" ";)this.take();let target="";for(;this.index<this.source.length&&!/[\s;&|<>()]/u.test(this.peek());){let character=this.take();if(character==="'"||character==='"'){target+=this.readUntil(character,"an unterminated quote in a redirect"),this.take();continue}target+=character}return target}stepGroup(character){if(character==="("){if(this.wordStarted)throw new ParseError3("a function definition or a stray paren");let body=this.readBalanced("(",")");return this.current.substitutions.push(body.slice(1,-1)),this.append("(\u2026)"),!0}if(character===")"){if(this.current.words[0]==="case"&&(this.caseDepth+=1),this.caseDepth===0)throw new ParseError3("an unbalanced )");return this.take(),this.word="",this.wordStarted=!1,this.current.words=[],!0}return!1}};function tokenizeShellCommand(command){return new Scanner(command).scan()}var PREFIX_CONTROL_WORDS=new Set(["if","then","else","elif","while","until","do","!","{","time"]),STANDALONE_CONTROL_WORDS=new Set(["fi","done","esac","}","]]",";;",":","true","false","exit"]),SHELL_STATE_BUILTINS=new Set(["read","local","export","unset","shift","break","continue","return","wait"]),HARMLESS_REDIRECT=/^(?:\d?>&[12-]|\d?>>?\/dev\/null|&>>?\/dev\/null|\d?>&-|<[^<]*)$/u,ASSIGNMENT=/^[A-Za-z_][A-Za-z0-9_]*=/u,HELP_OR_VERSION=new Set(["--help","--version","-h","-v","-V","-version"]),always=()=>!0,withoutFlags=(...forbidden)=>args=>!args.some(arg=>forbidden.some(flag=>arg===flag||arg.startsWith(`${flag}=`))),GIT_READ_VERBS=new Set(["status","log","diff","show","rev-parse","rev-list","ls-files","ls-remote","ls-tree","blame","describe","shortlog","name-rev","cat-file","help","--version","var","check-ignore","merge-base"]),GIT_BRANCH_LIST_FLAGS=/^(?:--show-current|--list|-a|-r|-v|-vv|--all|--remotes|--verbose|--contains=?.*|--merged=?.*|--no-merged=?.*|--format=.*|--sort=.*|--points-at=?.*|--column|--no-column)$/u;function gitRefinement(rawArgs){let args=[...rawArgs];for(;args[0]==="--no-pager"||args[0]==="-P"||args[0]==="-C";)args.shift()==="-C"&&args.shift();if(args.some(arg=>arg.startsWith("--output")))return!1;let[verb,...rest]=args;if(verb===void 0)return!1;if(GIT_READ_VERBS.has(verb))return!0;switch(verb){case"branch":return rest.every(arg=>GIT_BRANCH_LIST_FLAGS.test(arg));case"remote":return rest.length===0||rest[0]==="-v"||rest[0]==="show"||rest[0]==="get-url";case"config":return["--get","--get-all","--get-regexp","--list","-l"].includes(rest[0]??"");case"stash":return rest[0]==="list"||rest[0]==="show";case"reflog":return rest.length===0||rest[0]==="show";case"tag":return rest.length===0||rest.every(arg=>arg==="-l"||arg==="--list"||arg==="-n"||!arg.startsWith("-"));case"worktree":return rest[0]==="list";default:return!1}}function npmRefinement(args){let[verb,...rest]=args;return verb===void 0?!1:["ls","list","ll","la","view","info","show","outdated","why","explain","--version","-v"].includes(verb)?!0:verb==="audit"?!rest.includes("fix"):verb==="config"?["get","list","ls"].includes(rest[0]??""):verb==="pkg"?rest[0]==="get":!1}function sedRefinement(args){return!args.some(arg=>arg==="-n"||arg==="--quiet"||arg==="--silent"||/^-[a-zA-Z]*n[a-zA-Z]*$/u.test(arg))||args.some(arg=>arg==="-i"||arg.startsWith("--in-place")||/^-[a-zA-Z]*i/u.test(arg))?!1:!args.some(arg=>/(?:^|[;{\s])[wW]\s/u.test(arg))}function awkRefinement(args){return args.some(arg=>arg==="-i"||arg.startsWith("--in-place"))?!1:!args.some(arg=>/system\s*\(|>|\|/u.test(arg))}var findRefinement=withoutFlags("-exec","-execdir","-ok","-okdir","-delete","-fprint","-fprint0","-fprintf","-fls"),READ_ONLY_HEADS={cat:always,head:always,tail:always,less:always,more:always,grep:always,egrep:always,fgrep:always,rg:withoutFlags("--pre"),ls:always,pwd:always,echo:always,printf:always,wc:always,sort:withoutFlags("-o","--output"),uniq:always,cut:always,tr:always,diff:always,cmp:always,comm:always,file:always,stat:always,du:always,df:always,tree:withoutFlags("-o"),which:always,whereis:always,type:always,env:always,printenv:always,uname:always,whoami:always,id:always,hostname:always,arch:always,nproc:always,uptime:always,ps:always,lsof:always,date:withoutFlags("-s","--set"),basename:always,dirname:always,realpath:always,readlink:always,jq:always,column:always,nl:always,tac:always,fold:always,paste:always,seq:always,expr:always,sleep:always,md5sum:always,sha1sum:always,sha256sum:always,shasum:always,strings:always,od:always,hexdump:always,test:always,"[":always,"[[":always,sed:sedRefinement,awk:awkRefinement,gawk:awkRefinement,mawk:awkRefinement,find:findRefinement,fd:withoutFlags("-x","--exec","-X","--exec-batch"),git:gitRefinement,npm:npmRefinement,pnpm:args=>["ls","list","why","outdated","--version","-v"].includes(args[0]??""),yarn:args=>["--version","-v","list","why","info"].includes(args[0]??""),bun:args=>args[0]==="--version"||args[0]==="-v",node:args=>args.length===1&&(args[0]==="--version"||args[0]==="-v"),java:args=>args.length===1&&(args[0]==="-version"||args[0]==="--version"),go:args=>args[0]==="version"};function dropFlags(args,valued,bare){let rest=[...args];for(;rest.length>0;){let head=rest[0]??"";if(valued.test(head))rest.splice(0,head.includes("=")||/^-[a-zA-Z]\S+$/u.test(head)?1:2);else if(bare.test(head)||ASSIGNMENT.test(head))rest.shift();else break}return rest}var WRAPPERS={env:{unwrap:args=>dropFlags(args,/^(?:-u|--unset)/u,/^(?:-i|-0|--ignore-environment|--null)$/u)},command:{unwrap:args=>{if(!(args[0]==="-v"||args[0]==="-V"))return args[0]==="-p"?args.slice(1):args}},xargs:{unwrap:args=>{let rest=dropFlags(args,/^(?:-n|-I|-d|-P|-L|-s|-E|--max-args|--replace|--delimiter|--max-procs|--max-lines)/u,/^(?:-0|-r|-t|-p|--null|--no-run-if-empty|--verbose)$/u);return rest.length===0?void 0:rest}},timeout:{unwrap:args=>dropFlags(args,/^(?:-s|-k|--signal|--kill-after)/u,/^(?:--foreground|--preserve-status|-v|--verbose)$/u).slice(1)},nice:{unwrap:args=>dropFlags(args,/^(?:-n|--adjustment)/u,/^-\d+$/u)},time:{unwrap:args=>dropFlags(args,/^(?:-f|-o|--format|--output)/u,/^(?:-p|-v|--verbose|--portability)$/u)}};function headName(word){return word.startsWith("/")?word.split("/").pop()??word:word}function classifyWords(rawWords,depth){let words2=[...rawWords];for(;words2.length>0&&PREFIX_CONTROL_WORDS.has(words2[0]??"");)words2.shift();for(;words2.length>0&&ASSIGNMENT.test(words2[0]??"");)words2.shift();if(words2.length===0)return READ_ONLY;let head=headName(words2[0]??""),args=words2.slice(1),segment2=words2.join(" ");if(STANDALONE_CONTROL_WORDS.has(head)||SHELL_STATE_BUILTINS.has(head))return READ_ONLY;if(head==="(\u2026)")return args.length===0?READ_ONLY:notReadOnly("a subshell with trailing words",segment2);if(head==="$(\u2026)"||head==="`\u2026`")return notReadOnly("a command taken from substitution output",segment2);if(head==="for"||head==="case"||head==="select"||head==="in")return READ_ONLY;if(head==="set")return args.every(arg=>/^[-+][a-zA-Z]+$/u.test(arg)||arg==="-o"||arg==="+o"||/^[a-z]+$/u.test(arg))?READ_ONLY:notReadOnly("set with positional parameters",segment2);if(head==="cd")return args.length<=1?READ_ONLY:notReadOnly("cd with extra arguments",segment2);let wrapper=WRAPPERS[head];if(wrapper!==void 0){let inner=wrapper.unwrap(args);return inner===void 0?READ_ONLY:depth>8?notReadOnly("wrappers nested too deeply",segment2):classifyWords(inner,depth+1)}let refinement=READ_ONLY_HEADS[head];return refinement!==void 0?refinement(args)?READ_ONLY:notReadOnly(`${head} with an argument that writes or executes`,segment2):args.length===1&&HELP_OR_VERSION.has(args[0]??"")?READ_ONLY:notReadOnly(`unknown head "${head}"`,segment2)}function classifySimple(command,depth){for(let body of command.substitutions){let nested=classifyCommand(body,depth+1);if(!nested.readOnly)return nested}let redirect=command.redirects.find(entry=>!HARMLESS_REDIRECT.test(entry));return redirect!==void 0?notReadOnly(`a redirect that writes a file (${redirect})`,command.words.join(" ")):classifyWords(command.words,depth)}function classifyCommand(command,depth){if(depth>8)return notReadOnly("substitutions nested too deeply");let commands;try{commands=tokenizeShellCommand(command)}catch(error){if(error instanceof ParseError3)return notReadOnly(error.message);throw error}for(let simple of commands){let verdict=classifySimple(simple,depth);if(!verdict.readOnly)return verdict}return READ_ONLY}function classifyShellCommand(command){return command.trim().length===0?READ_ONLY:classifyCommand(command,0)}var execFile2=promisify(execFileCallback),DEFAULT_POLICY_CONFIG={deny:["git push","git push --force","git reset --hard","rm -rf","chmod 777"],allow:[],commit:{chat:"allow",gated:"confirm",autopilot:"after-release"},unknown:{chat:"allow",gated:"confirm",autopilot:"deny"}},DEFAULT_ACTIVE_POLICY_STATE={mode:"chat",releaseApproved:!1,writeAllow:[],qualityGates:[]},UNREADABLE_JOB_POLICY_STATE={mode:"gated",releaseApproved:!1,writeAllow:[],qualityGates:[]},APPROVAL_OPTIONS=["Allow for this session","Always allow in this project","Deny"],ALLOW={kind:"allow"},SENSITIVE_FILE_PATTERN=/^(?:\.env(?:\..*)?|id_rsa|auth\.json|accounts\.secrets\.json)$/i,PRODUCTION_COMMAND_PATTERNS=[/\b(?:npm|pnpm|yarn)\s+publish\b/i,/\b(?:kubectl|helm|terraform)\b[^;&|\n]*\b(?:apply|deploy|upgrade)\b/i,/\b(?:vercel|netlify)\b[^;&|\n]*--(?:prod|production)\b/i,/\bdeploy\b[^;&|\n]*\bprod(?:uction)?\b/i,/\bnpm\s+(?:install|i)\b/i,/\b(?:pnpm|yarn|bun)\s+add\b/i],SHELL_COMPOSITION_PATTERN=/[;&|`\n\r<>]|\$[({]/u,SHELL_WORD_SEPARATOR=/[\s;&|`()<>="',]+/u,DIFF_STAT_FILES_PATTERN=/(\d+)\s+files?\s+changed/u,DIFF_STAT_INSERTIONS_PATTERN=/(\d+)\s+insertions?\(\+\)/u,DIFF_STAT_DELETIONS_PATTERN=/(\d+)\s+deletions?\(-\)/u;function normalizeCommand(command){return command.trim().replace(/\s+/g," ").toLowerCase()}function collapseWhitespace(command){return command.trim().replace(/\s+/gu," ")}function includesGitPush(command){return command.split(/[;&|\n]+/).some(segment2=>/(?:^|\s)(?:sudo\s+)?git\b.*\bpush(?:\s|$)/i.test(segment2))}function includesRecursiveForceRemove(command){for(let segment2 of command.split(/[;&|\n]+/)){let tokens=segment2.trim().split(/\s+/),rmIndex=tokens.findIndex(token=>/(?:^|\/)rm$/.test(token));if(rmIndex<0)continue;let recursive=!1,force=!1;for(let token of tokens.slice(rmIndex+1))token==="--recursive"?recursive=!0:token==="--force"?force=!0:/^-[^-]/.test(token)&&(recursive||=token.includes("r")||token.includes("R"),force||=token.includes("f"));if(recursive&&force)return!0}return!1}function commandDenied(command,deny){if(includesGitPush(command)||includesRecursiveForceRemove(command)||PRODUCTION_COMMAND_PATTERNS.some(pattern=>pattern.test(command)))return!0;let normalized=normalizeCommand(command);return deny.some(entry=>normalized.includes(normalizeCommand(entry)))}function isStandaloneGitCommit(command){if(SHELL_COMPOSITION_PATTERN.test(command))return!1;let tokens=collapseWhitespace(command).split(" ");return tokens[0]==="git"&&tokens[1]==="commit"}function isDeclaredQualityGate(command,qualityGates){if(SHELL_COMPOSITION_PATTERN.test(command))return!1;let exact=collapseWhitespace(command);return qualityGates.some(gate=>collapseWhitespace(gate)===exact)}function isAllowlisted(command,allow){let exact=collapseWhitespace(command);return allow.some(entry=>collapseWhitespace(entry)===exact)}function normalizePath2(path14){return path14.split(sep11).join("/").replace(/^\.\//,"")}function globPattern(pattern){let source2="";for(let index3=0;index3<pattern.length;index3+=1){let character=pattern[index3];character==="*"&&pattern[index3+1]==="*"?pattern[index3+2]==="/"?(source2+="(?:.*/)?",index3+=2):(source2+=".*",index3+=1):character==="*"?source2+="[^/]*":character==="?"?source2+="[^/]":source2+=character.replace(/[\\^$+?.()|{}[\]]/g,"\\$&")}return new RegExp(`^${source2}$`)}function relativeWritePath(cwd,path14){let absolutePath=resolve18(cwd,path14),relativePath=relative7(resolve18(cwd),absolutePath);if(!(relativePath===""||relativePath===".."||relativePath.startsWith(`..${sep11}`)||isAbsolute8(relativePath)))return normalizePath2(relativePath)}var PROTECTED_RUN_ARTIFACT_OWNERS={"verdict.json":"the reviewer","release.approved":"the release.set node","ship.json":"the control plane"};function protectedRunArtifact(cwd,path14){let relativePath=relativeWritePath(cwd,path14);if(relativePath===void 0)return;let segments=relativePath.split("/");if(segments.length<4||segments[0]!==CONFIG_DIR_NAME||segments[1]!=="runs")return;let artifact=segments[segments.length-1];return Object.hasOwn(PROTECTED_RUN_ARTIFACT_OWNERS,artifact)?artifact:void 0}function protectedCommandTarget(cwd,command){for(let word of command.split(SHELL_WORD_SEPARATOR)){if(word.length===0)continue;let artifact=protectedRunArtifact(cwd,word);if(artifact!==void 0)return{path:word,owner:PROTECTED_RUN_ARTIFACT_OWNERS[artifact]};if(isAuthoritativeKnowledgeGraphPath(cwd,word))return{path:word,owner:"the knowledge graph control plane"}}}var DISCARD_TARGETS=new Set(["/dev/null","/dev/stdout","/dev/stderr","/dev/tty"]);function unquote2(word){return word.replace(/^['"]|['"]$/gu,"")}function sensitiveCommandTarget(command){for(let word of command.split(SHELL_WORD_SEPARATOR)){let candidate=unquote2(word);if(candidate.length!==0&&candidate.split(/[\\/]/u).some(segment2=>SENSITIVE_FILE_PATTERN.test(segment2)))return candidate}}var REDIRECT_TARGET_PATTERN=/(?:^|[\s;&|(])\d?>{1,2}\|?\s*(?!&)(['"]?)([^\s;&|)'"]+)\1/gu,TEE_TARGET_PATTERN=/\btee\b((?:\s+-[^\s]+)*)\s+([^\s;&|)]+(?:\s+[^-\s;&|)][^\s;&|)]*)*)/gu,DD_TARGET_PATTERN=/\bdd\b[^;&|\n]*?\bof=(['"]?)([^\s;&|)'"]+)\1/gu,COPY_COMMAND_PATTERN=/\b(?:cp|mv|install|rsync)\b([^;&|\n]*)/gu,NESTED_SHELL_PATTERN=/\b(?:ba|z|da)?sh\b[^;&|\n]*?-c\s+(['"])([\s\S]*?)\1/gu;function shellWriteTargets(command){let targets=[],add=value=>{let candidate=unquote2(value??"").trim();candidate.length===0||DISCARD_TARGETS.has(candidate)||/^\d$/u.test(candidate)||targets.push(candidate)};for(let match2 of command.matchAll(REDIRECT_TARGET_PATTERN))add(match2[2]);for(let match2 of command.matchAll(TEE_TARGET_PATTERN))for(let word of match2[2].split(/\s+/u))add(word);for(let match2 of command.matchAll(DD_TARGET_PATTERN))add(match2[2]);for(let match2 of command.matchAll(COPY_COMMAND_PATTERN)){let operands=match2[1].split(/\s+/u).map(unquote2).filter(word=>word.length>0&&!word.startsWith("-"));operands.length>=2&&add(operands.at(-1))}for(let match2 of command.matchAll(NESTED_SHELL_PATTERN))targets.push(...shellWriteTargets(match2[2]));return targets}function isWriteAllowed(cwd,path14,writeAllow){let relativePath=relativeWritePath(cwd,path14);return relativePath===void 0||relativePath.split("/").some(part=>SENSITIVE_FILE_PATTERN.test(part))?!1:writeAllow.some(allowedPath=>{let normalizedAllowedPath=normalizePath2(isAbsolute8(allowedPath)?relative7(resolve18(cwd),resolve18(allowedPath)):allowedPath);return globPattern(normalizedAllowedPath).test(relativePath)})}function matchCount(summary,pattern){let match2=pattern.exec(summary);return match2===null?0:Number(match2[1])}function parseDiffStat(summary){return{filesChanged:matchCount(summary,DIFF_STAT_FILES_PATTERN),insertions:matchCount(summary,DIFF_STAT_INSERTIONS_PATTERN),deletions:matchCount(summary,DIFF_STAT_DELETIONS_PATTERN)}}async function readGitDiffStat(cwd){try{let{stdout}=await execFile2("git",["diff","--shortstat","HEAD"],{cwd});return parseDiffStat(stdout)}catch{return{filesChanged:0,insertions:0,deletions:0}}}function isReleaseApproved(state2){let values=isJsonObject(state2.values)?state2.values:state2;return isJsonObject(values.release)&&values.release.approved===!0}async function resolveActivePolicyState(cwd){let job=await readLiveJob(cwd);if(job===void 0)return DEFAULT_ACTIVE_POLICY_STATE;let task;try{task=JSON.parse(await readFile19(join52(job.directory,"task.json"),"utf8"))}catch{return UNREADABLE_JOB_POLICY_STATE}let writeAllow=Array.isArray(task.acceptance)?[...writeAllowForTask(task)]:[],runRelative=relative7(resolve18(cwd),resolve18(job.directory)).replaceAll("\\","/");return runRelative.length>0&&!runRelative.startsWith("..")&&writeAllow.push(`${runRelative}/candidate.json`),{mode:task.mode==="autopilot"?"autopilot":"gated",releaseApproved:isReleaseApproved(job.state),writeAllow,qualityGates:Array.isArray(task.quality_gates)?task.quality_gates:[]}}function confirmCommit(command,summary){return{kind:"confirm",title:"Approve git commit",question:`${command}
1349
+ `),await rename5(marker,join51(target,SNAPSHOT_COMPLETE_MARKER)),target}};var execFile2=promisify(execFileCallback),DEFAULT_POLICY_CONFIG={deny:["git push --force","git reset --hard","rm -rf","chmod 777"],allow:[],commit:{chat:"allow",gated:"confirm",autopilot:"after-release"},unknown:{chat:"allow",gated:"confirm",autopilot:"deny"}},LEGACY_PUSH_DENY_ENTRY="git push",DEFAULT_ACTIVE_POLICY_STATE={mode:"chat",releaseApproved:!1,writeAllow:[],qualityGates:[]},UNREADABLE_JOB_POLICY_STATE={mode:"gated",releaseApproved:!1,writeAllow:[],qualityGates:[]},APPROVAL_OPTIONS=["Allow for this session","Always allow in this project","Deny"],ALLOW={kind:"allow"},SENSITIVE_FILE_PATTERN=/^(?:\.env(?:\..*)?|id_rsa|auth\.json|accounts\.secrets\.json)$/i,PRODUCTION_COMMAND_PATTERNS=[/\b(?:npm|pnpm|yarn)\s+publish\b/i,/\b(?:kubectl|helm|terraform)\b[^;&|\n]*\b(?:apply|deploy|upgrade)\b/i,/\b(?:vercel|netlify)\b[^;&|\n]*--(?:prod|production)\b/i,/\bdeploy\b[^;&|\n]*\bprod(?:uction)?\b/i,/\bnpm\s+(?:install|i)\b/i,/\b(?:pnpm|yarn|bun)\s+add\b/i,/\bgh\s+pr\s+merge\b/i],JOB_BRANCH_PATTERN=/^kpi\/[A-Za-z0-9][A-Za-z0-9._-]*$/u,JOB_PUSH_REMOTE="origin",JOB_PUSH_FLAGS=new Set(["-u","--set-upstream","-q","--quiet","-v","--verbose"]),PR_HEAD_FLAGS=new Set(["--head","-H"]),SHELL_COMPOSITION_PATTERN=/[;&|`\n\r<>]|\$[({]/u,SHELL_WORD_SEPARATOR=/[\s;&|`()<>="',]+/u,DIFF_STAT_FILES_PATTERN=/(\d+)\s+files?\s+changed/u,DIFF_STAT_INSERTIONS_PATTERN=/(\d+)\s+insertions?\(\+\)/u,DIFF_STAT_DELETIONS_PATTERN=/(\d+)\s+deletions?\(-\)/u;function normalizeCommand(command){return command.trim().replace(/\s+/g," ").toLowerCase()}function collapseWhitespace(command){return command.trim().replace(/\s+/gu," ")}function includesGitPush(command){return command.split(/[;&|\n]+/).some(segment2=>/(?:^|\s)(?:sudo\s+)?git\b.*\bpush(?:\s|$)/i.test(segment2))}function includesRecursiveForceRemove(command){for(let segment2 of command.split(/[;&|\n]+/)){let tokens=segment2.trim().split(/\s+/),rmIndex=tokens.findIndex(token=>/(?:^|\/)rm$/.test(token));if(rmIndex<0)continue;let recursive=!1,force=!1;for(let token of tokens.slice(rmIndex+1))token==="--recursive"?recursive=!0:token==="--force"?force=!0:/^-[^-]/.test(token)&&(recursive||=token.includes("r")||token.includes("R"),force||=token.includes("f"));if(recursive&&force)return!0}return!1}function commandDenied(command,deny){if(includesRecursiveForceRemove(command)||PRODUCTION_COMMAND_PATTERNS.some(pattern=>pattern.test(command)))return!0;let normalized=normalizeCommand(command);return deny.some(entry=>normalized.includes(normalizeCommand(entry)))}function standaloneWords(command){if(!SHELL_COMPOSITION_PATTERN.test(command))return collapseWhitespace(command).split(" ")}function isStandaloneGit(command,verb){let tokens=standaloneWords(command);return tokens!==void 0&&tokens[0]==="git"&&tokens[1]===verb}function isStandaloneGitCommit(command){return isStandaloneGit(command,"commit")}function parseJobBranchPush(command){let tokens=standaloneWords(command);if(tokens===void 0)return{reason:"a push may not be chained with another command"};if(tokens[0]!=="git"||tokens[1]!=="push")return{reason:"only a standalone `git push` is allowed"};let positionals=[];for(let token of tokens.slice(2)){if(token.startsWith("-")){if(!JOB_PUSH_FLAGS.has(token))return{reason:`push option ${token} is not allowed`};continue}positionals.push(token)}if(positionals.length!==2)return{reason:`a push must name the remote and exactly one kpi/* branch, as git push -u ${JOB_PUSH_REMOTE} kpi/<job>`};let[remote,refspec]=positionals;return remote!==JOB_PUSH_REMOTE?{reason:`only ${JOB_PUSH_REMOTE} may be pushed to, not ${remote}`}:refspec.startsWith("+")?{reason:"a leading + is a force push"}:refspec.includes(":")?{reason:"a refspec with a destination can delete or rename a remote branch"}:JOB_BRANCH_PATTERN.test(refspec)?{branch:refspec}:{reason:`only a kpi/* branch may be pushed, not ${refspec}`}}function isJobPullRequestCreate(command){let tokens=standaloneWords(command);if(tokens===void 0||tokens[0]!=="gh"||tokens[1]!=="pr"||tokens[2]!=="create")return!1;for(let[index3,token]of tokens.entries())if(PR_HEAD_FLAGS.has(token)){let head=tokens[index3+1];if(head===void 0||!JOB_BRANCH_PATTERN.test(unquote2(head)))return!1}else{let[flag,value]=token.split("=",2);if(PR_HEAD_FLAGS.has(flag)&&(value===void 0||!JOB_BRANCH_PATTERN.test(unquote2(value))))return!1}return!0}function isDeclaredQualityGate(command,qualityGates){if(SHELL_COMPOSITION_PATTERN.test(command))return!1;let exact=collapseWhitespace(command);return qualityGates.some(gate=>collapseWhitespace(gate)===exact)}function isAllowlisted(command,allow){let exact=collapseWhitespace(command);return allow.some(entry=>collapseWhitespace(entry)===exact)}function normalizePath2(path14){return path14.split(sep11).join("/").replace(/^\.\//,"")}function globPattern(pattern){let source2="";for(let index3=0;index3<pattern.length;index3+=1){let character=pattern[index3];character==="*"&&pattern[index3+1]==="*"?pattern[index3+2]==="/"?(source2+="(?:.*/)?",index3+=2):(source2+=".*",index3+=1):character==="*"?source2+="[^/]*":character==="?"?source2+="[^/]":source2+=character.replace(/[\\^$+?.()|{}[\]]/g,"\\$&")}return new RegExp(`^${source2}$`)}function relativeWritePath(cwd,path14){let absolutePath=resolve18(cwd,path14),relativePath=relative7(resolve18(cwd),absolutePath);if(!(relativePath===""||relativePath===".."||relativePath.startsWith(`..${sep11}`)||isAbsolute8(relativePath)))return normalizePath2(relativePath)}var PROTECTED_RUN_ARTIFACT_OWNERS={"verdict.json":"the reviewer","release.approved":"the release.set node","ship.json":"the control plane"};function protectedRunArtifact(cwd,path14){let relativePath=relativeWritePath(cwd,path14);if(relativePath===void 0)return;let segments=relativePath.split("/");if(segments.length<4||segments[0]!==CONFIG_DIR_NAME||segments[1]!=="runs")return;let artifact=segments[segments.length-1];return Object.hasOwn(PROTECTED_RUN_ARTIFACT_OWNERS,artifact)?artifact:void 0}function protectedCommandTarget(cwd,command){for(let word of command.split(SHELL_WORD_SEPARATOR)){if(word.length===0)continue;let artifact=protectedRunArtifact(cwd,word);if(artifact!==void 0)return{path:word,owner:PROTECTED_RUN_ARTIFACT_OWNERS[artifact]};if(isAuthoritativeKnowledgeGraphPath(cwd,word))return{path:word,owner:"the knowledge graph control plane"}}}var DISCARD_TARGETS=new Set(["/dev/null","/dev/stdout","/dev/stderr","/dev/tty"]);function unquote2(word){return word.replace(/^['"]|['"]$/gu,"")}function sensitiveCommandTarget(command){for(let word of command.split(SHELL_WORD_SEPARATOR)){let candidate=unquote2(word);if(candidate.length!==0&&candidate.split(/[\\/]/u).some(segment2=>SENSITIVE_FILE_PATTERN.test(segment2)))return candidate}}var REDIRECT_TARGET_PATTERN=/(?:^|[\s;&|(])\d?>{1,2}\|?\s*(?!&)(['"]?)([^\s;&|)'"]+)\1/gu,TEE_TARGET_PATTERN=/\btee\b((?:\s+-[^\s]+)*)\s+([^\s;&|)]+(?:\s+[^-\s;&|)][^\s;&|)]*)*)/gu,DD_TARGET_PATTERN=/\bdd\b[^;&|\n]*?\bof=(['"]?)([^\s;&|)'"]+)\1/gu,COPY_COMMAND_PATTERN=/\b(?:cp|mv|install|rsync)\b([^;&|\n]*)/gu,NESTED_SHELL_PATTERN=/\b(?:ba|z|da)?sh\b[^;&|\n]*?-c\s+(['"])([\s\S]*?)\1/gu;function shellWriteTargets(command){let targets=[],add=value=>{let candidate=unquote2(value??"").trim();candidate.length===0||DISCARD_TARGETS.has(candidate)||/^\d$/u.test(candidate)||targets.push(candidate)};for(let match2 of command.matchAll(REDIRECT_TARGET_PATTERN))add(match2[2]);for(let match2 of command.matchAll(TEE_TARGET_PATTERN))for(let word of match2[2].split(/\s+/u))add(word);for(let match2 of command.matchAll(DD_TARGET_PATTERN))add(match2[2]);for(let match2 of command.matchAll(COPY_COMMAND_PATTERN)){let operands=match2[1].split(/\s+/u).map(unquote2).filter(word=>word.length>0&&!word.startsWith("-"));operands.length>=2&&add(operands.at(-1))}for(let match2 of command.matchAll(NESTED_SHELL_PATTERN))targets.push(...shellWriteTargets(match2[2]));return targets}function isWriteAllowed(cwd,path14,writeAllow){let relativePath=relativeWritePath(cwd,path14);return relativePath===void 0||relativePath.split("/").some(part=>SENSITIVE_FILE_PATTERN.test(part))?!1:writeAllow.some(allowedPath=>{let normalizedAllowedPath=normalizePath2(isAbsolute8(allowedPath)?relative7(resolve18(cwd),resolve18(allowedPath)):allowedPath);return globPattern(normalizedAllowedPath).test(relativePath)})}function matchCount(summary,pattern){let match2=pattern.exec(summary);return match2===null?0:Number(match2[1])}function parseDiffStat(summary){return{filesChanged:matchCount(summary,DIFF_STAT_FILES_PATTERN),insertions:matchCount(summary,DIFF_STAT_INSERTIONS_PATTERN),deletions:matchCount(summary,DIFF_STAT_DELETIONS_PATTERN)}}async function readGitDiffStat(cwd){try{let{stdout}=await execFile2("git",["diff","--shortstat","HEAD"],{cwd});return parseDiffStat(stdout)}catch{return{filesChanged:0,insertions:0,deletions:0}}}function isReleaseApproved(state2){let values=isJsonObject(state2.values)?state2.values:state2;return isJsonObject(values.release)&&values.release.approved===!0}async function resolveActivePolicyState(cwd){let job=await readLiveJob(cwd);if(job===void 0)return DEFAULT_ACTIVE_POLICY_STATE;let task;try{task=JSON.parse(await readFile19(join52(job.directory,"task.json"),"utf8"))}catch{return UNREADABLE_JOB_POLICY_STATE}let writeAllow=Array.isArray(task.acceptance)?[...writeAllowForTask(task)]:[],runRelative=relative7(resolve18(cwd),resolve18(job.directory)).replaceAll("\\","/");return runRelative.length>0&&!runRelative.startsWith("..")&&writeAllow.push(`${runRelative}/candidate.json`),{mode:task.mode==="autopilot"?"autopilot":"gated",releaseApproved:isReleaseApproved(job.state),writeAllow,qualityGates:Array.isArray(task.quality_gates)?task.quality_gates:[]}}function confirmCommit(command,summary){return{kind:"confirm",title:"Approve git commit",question:`${command}
1350
1350
 
1351
1351
  ${summary} against HEAD.
1352
1352
 
1353
- Commit on the job branch?`,declineReason:`Policy requires confirmation for git commit; not approved: ${command}`}}async function evaluateGitCommit(command,options){let{active,policy}=options,rule=active.mode==="chat"?policy.commit.chat:policy.commit[active.mode];if(rule==="allow")return ALLOW;if(rule==="confirm"){let stat11=await(options.readDiffStat??readGitDiffStat)(options.cwd),summary=`${stat11.filesChanged} files changed, ${stat11.insertions} insertions(+), ${stat11.deletions} deletions(-)`;return confirmCommit(command,summary)}return active.releaseApproved?ALLOW:{kind:"deny",reason:`Policy denied git commit before release.approved: ${command}`}}function unknownCommand(command,options,why){let{active,policy}=options,rule=active.mode==="chat"?policy.unknown.chat:policy.unknown[active.mode];return rule==="allow"?ALLOW:rule==="confirm"?{kind:"confirm",title:"Approve unrecognized command",question:`${command}
1353
+ Commit on the job branch?`,declineReason:`Policy requires confirmation for git commit; not approved: ${command}`}}async function evaluateGitCommit(command,options){let{active,policy}=options,rule=active.mode==="chat"?policy.commit.chat:policy.commit[active.mode];if(rule==="allow")return ALLOW;if(rule==="confirm"){let stat11=await(options.readDiffStat??readGitDiffStat)(options.cwd),summary=`${stat11.filesChanged} files changed, ${stat11.insertions} insertions(+), ${stat11.deletions} deletions(-)`;return confirmCommit(command,summary)}return active.releaseApproved?ALLOW:{kind:"deny",reason:`Policy denied git commit before release.approved: ${command}`}}function evaluateGitPush(command,options){let parsed=parseJobBranchPush(command);return"reason"in parsed?{kind:"deny",reason:`Policy denied git push (${parsed.reason}): ${command}`}:options.active.mode==="chat"?{kind:"deny",reason:`Policy denied git push outside a K-\u03C0 job: ${command}`}:options.active.releaseApproved?ALLOW:{kind:"deny",reason:`Policy denied git push before release.approved: ${command}`}}function releaseStep(command,options){let{active}=options;if(active.mode!=="chat"){if(isStandaloneGit(command,"add"))return active.releaseApproved?ALLOW:void 0;if(isJobPullRequestCreate(command))return active.releaseApproved?ALLOW:{kind:"deny",reason:`Policy denied gh pr create before release.approved: ${command}`}}}function unknownCommand(command,options,why){let{active,policy}=options,rule=active.mode==="chat"?policy.unknown.chat:policy.unknown[active.mode];return rule==="allow"?ALLOW:rule==="confirm"?{kind:"confirm",title:"Approve unrecognized command",question:`${command}
1354
1354
 
1355
1355
  ${why}
1356
1356
 
1357
- Run it?`,declineReason:`Policy requires confirmation for an unrecognized command; not approved: ${command}`,command:collapseWhitespace(command)}:{kind:"deny",reason:`Policy denied unrecognized command: ${command}`}}async function evaluateCommand(command,options){let{active,policy}=options;if(commandDenied(command,policy.deny))return{kind:"deny",reason:`Policy denied command: ${command}`};let reserved=protectedCommandTarget(options.cwd,command);if(reserved!==void 0)return{kind:"deny",reason:`Policy reserved ${reserved.path} for ${reserved.owner}: ${command}`};let sensitive=sensitiveCommandTarget(command);if(sensitive!==void 0)return{kind:"deny",reason:`Policy denied a secret-shaped path: ${sensitive}`};if(active.mode!=="chat"){let outsideBounds=shellWriteTargets(command).find(target=>!isWriteAllowed(options.cwd,target,active.writeAllow));if(outsideBounds!==void 0)return{kind:"deny",reason:`Policy denied write outside write_allow: ${outsideBounds}`}}if(isStandaloneGitCommit(command))return await evaluateGitCommit(command,options);if(isDeclaredQualityGate(command,active.qualityGates))return ALLOW;let classification=classifyShellCommand(command);if(classification.readOnly||isAllowlisted(command,policy.allow))return ALLOW;let why=classification.segment===void 0?`Not read-only: ${classification.reason}.`:`Not read-only: ${classification.reason} in \`${classification.segment}\`.`;return unknownCommand(command,options,why)}function evaluateWrite(path14,options){let artifact=protectedRunArtifact(options.cwd,path14);return artifact!==void 0?{kind:"deny",reason:`Policy reserved ${artifact} for ${PROTECTED_RUN_ARTIFACT_OWNERS[artifact]}: ${path14}`}:isAuthoritativeKnowledgeGraphPath(options.cwd,path14)?{kind:"deny",reason:`Policy reserved the authoritative knowledge graph for the control plane: ${path14}`}:options.active.mode==="chat"?(relativeWritePath(options.cwd,path14)??normalizePath2(path14)).split("/").some(part=>SENSITIVE_FILE_PATTERN.test(part))?{kind:"deny",reason:`Policy denied a secret-shaped path: ${path14}`}:ALLOW:isWriteAllowed(options.cwd,path14,options.active.writeAllow)?ALLOW:{kind:"deny",reason:`Policy denied write outside write_allow: ${path14}`}}async function evaluateToolCall(event,options){return isToolCallEventType("bash",event)?await evaluateCommand(event.input.command,options):isToolCallEventType("write",event)||isToolCallEventType("edit",event)?evaluateWrite(event.input.path,options):ALLOW}function policyPath(cwd){return resolve18(cwd,CONFIG_DIR_NAME,"policy.json")}async function ensurePolicyFile(cwd){let target=policyPath(cwd);await mkdir10(resolve18(cwd,CONFIG_DIR_NAME),{recursive:!0});try{await copyFile(join52(getKpiResourceDir(),"templates","policy.json"),target,constants7.COPYFILE_EXCL)}catch(error){if(error.code!=="EEXIST")throw error}return target}async function exists(path14){try{return await stat8(path14),!0}catch(error){if(error.code==="ENOENT")return!1;throw error}}async function shouldSeedPolicyFile(cwd){return await exists(resolve18(cwd,CONFIG_DIR_NAME))||await exists(resolve18(cwd,".git"))}function chatRule(value,source2,field2){if(value===void 0)return"allow";if(value==="allow"||value==="confirm")return value;throw new Error(`${source2} ${field2} must be "allow" or "confirm"`)}function normalizePolicy(raw,source2){if(!isJsonObject(raw)||!Array.isArray(raw.deny))throw new Error(`${source2} must define a deny array`);let allow=raw.allow??[];if(!Array.isArray(allow)||!allow.every(entry=>typeof entry=="string"))throw new Error(`${source2} allow must be an array of strings`);let commit=isJsonObject(raw.commit)?raw.commit:{},unknown=isJsonObject(raw.unknown)?raw.unknown:{};return{deny:raw.deny.filter(entry=>typeof entry=="string"),allow,commit:{chat:chatRule(commit.chat,source2,"commit.chat"),gated:"confirm",autopilot:"after-release"},unknown:{chat:chatRule(unknown.chat,source2,"unknown.chat"),gated:"confirm",autopilot:"deny"}}}async function readPolicy(cwd){let target=policyPath(cwd),source2;try{source2=await readFile19(target,"utf8")}catch(error){if(error.code==="ENOENT")return DEFAULT_POLICY_CONFIG;throw error}return normalizePolicy(JSON.parse(source2),target)}async function rememberAllowedCommand(cwd,command){let target=await ensurePolicyFile(cwd),policy=normalizePolicy(JSON.parse(await readFile19(target,"utf8")),target),exact=collapseWhitespace(command);return policy.allow.includes(exact)||policy.allow.push(exact),await atomicWrite(target,`${JSON.stringify(policy,null,2)}
1357
+ Run it?`,declineReason:`Policy requires confirmation for an unrecognized command; not approved: ${command}`,command:collapseWhitespace(command)}:{kind:"deny",reason:`Policy denied unrecognized command: ${command}`}}async function evaluateCommand(command,options){let{active,policy}=options;if(includesGitPush(command))return evaluateGitPush(command,options);if(commandDenied(command,policy.deny))return{kind:"deny",reason:`Policy denied command: ${command}`};let reserved=protectedCommandTarget(options.cwd,command);if(reserved!==void 0)return{kind:"deny",reason:`Policy reserved ${reserved.path} for ${reserved.owner}: ${command}`};let sensitive=sensitiveCommandTarget(command);if(sensitive!==void 0)return{kind:"deny",reason:`Policy denied a secret-shaped path: ${sensitive}`};if(active.mode!=="chat"){let outsideBounds=shellWriteTargets(command).find(target=>!isWriteAllowed(options.cwd,target,active.writeAllow));if(outsideBounds!==void 0)return{kind:"deny",reason:`Policy denied write outside write_allow: ${outsideBounds}`}}if(isStandaloneGitCommit(command))return await evaluateGitCommit(command,options);let release=releaseStep(command,options);if(release!==void 0)return release;if(isDeclaredQualityGate(command,active.qualityGates))return ALLOW;let classification=classifyShellCommand(command);if(classification.readOnly||isAllowlisted(command,policy.allow))return ALLOW;let why=classification.segment===void 0?`Not read-only: ${classification.reason}.`:`Not read-only: ${classification.reason} in \`${classification.segment}\`.`;return unknownCommand(command,options,why)}function evaluateWrite(path14,options){let artifact=protectedRunArtifact(options.cwd,path14);return artifact!==void 0?{kind:"deny",reason:`Policy reserved ${artifact} for ${PROTECTED_RUN_ARTIFACT_OWNERS[artifact]}: ${path14}`}:isAuthoritativeKnowledgeGraphPath(options.cwd,path14)?{kind:"deny",reason:`Policy reserved the authoritative knowledge graph for the control plane: ${path14}`}:options.active.mode==="chat"?(relativeWritePath(options.cwd,path14)??normalizePath2(path14)).split("/").some(part=>SENSITIVE_FILE_PATTERN.test(part))?{kind:"deny",reason:`Policy denied a secret-shaped path: ${path14}`}:ALLOW:isWriteAllowed(options.cwd,path14,options.active.writeAllow)?ALLOW:{kind:"deny",reason:`Policy denied write outside write_allow: ${path14}`}}async function evaluateToolCall(event,options){return isToolCallEventType("bash",event)?await evaluateCommand(event.input.command,options):isToolCallEventType("write",event)||isToolCallEventType("edit",event)?evaluateWrite(event.input.path,options):ALLOW}function policyPath(cwd){return resolve18(cwd,CONFIG_DIR_NAME,"policy.json")}async function ensurePolicyFile(cwd){let target=policyPath(cwd);await mkdir10(resolve18(cwd,CONFIG_DIR_NAME),{recursive:!0});try{await copyFile(join52(getKpiResourceDir(),"templates","policy.json"),target,constants7.COPYFILE_EXCL)}catch(error){if(error.code!=="EEXIST")throw error}return target}async function exists(path14){try{return await stat8(path14),!0}catch(error){if(error.code==="ENOENT")return!1;throw error}}async function shouldSeedPolicyFile(cwd){return await exists(resolve18(cwd,CONFIG_DIR_NAME))||await exists(resolve18(cwd,".git"))}function chatRule(value,source2,field2){if(value===void 0)return"allow";if(value==="allow"||value==="confirm")return value;throw new Error(`${source2} ${field2} must be "allow" or "confirm"`)}function normalizePolicy(raw,source2){if(!isJsonObject(raw)||!Array.isArray(raw.deny))throw new Error(`${source2} must define a deny array`);let allow=raw.allow??[];if(!Array.isArray(allow)||!allow.every(entry=>typeof entry=="string"))throw new Error(`${source2} allow must be an array of strings`);let commit=isJsonObject(raw.commit)?raw.commit:{},unknown=isJsonObject(raw.unknown)?raw.unknown:{};return{deny:raw.deny.filter(entry=>typeof entry=="string"&&normalizeCommand(entry)!==LEGACY_PUSH_DENY_ENTRY),allow,commit:{chat:chatRule(commit.chat,source2,"commit.chat"),gated:"confirm",autopilot:"after-release"},unknown:{chat:chatRule(unknown.chat,source2,"unknown.chat"),gated:"confirm",autopilot:"deny"}}}async function readPolicy(cwd){let target=policyPath(cwd),source2;try{source2=await readFile19(target,"utf8")}catch(error){if(error.code==="ENOENT")return DEFAULT_POLICY_CONFIG;throw error}return normalizePolicy(JSON.parse(source2),target)}async function rememberAllowedCommand(cwd,command){let target=await ensurePolicyFile(cwd),policy=normalizePolicy(JSON.parse(await readFile19(target,"utf8")),target),exact=collapseWhitespace(command);return policy.allow.includes(exact)||policy.allow.push(exact),await atomicWrite(target,`${JSON.stringify(policy,null,2)}
1358
1358
  `),target}async function askApproval(ui,decision){if(decision.command===void 0||typeof ui.select!="function")return await ui.confirm(decision.title,decision.question)?"once":"deny";let choice=await ui.select(`${decision.title}
1359
- ${decision.question}`,[...APPROVAL_OPTIONS]);return choice===APPROVAL_OPTIONS[0]?"once":choice===APPROVAL_OPTIONS[1]?"always":"deny"}function requestedPath(event){if(isToolCallEventType("write",event)||isToolCallEventType("edit",event))return event.input.path}async function recordToolRequest(cwd,event,decision,reason){try{let job=await readLiveJob(cwd);if(job===void 0)return;let path14=requestedPath(event);await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"tool.request",job_id:job.jobId,round:typeof job.state.round=="number"?job.state.round:0,node:typeof job.state.node=="string"?job.state.node:"tool",tool:event.toolName,decision,...path14===void 0?{}:{path:path14},...reason===void 0?{}:{reason}})}catch{}}function registerPolicy(pi,options={}){let sessionAllow=options.sessionAllow??new Set;pi.on("session_start",async(_event,ctx)=>{await shouldSeedPolicyFile(ctx.cwd)&&await ensurePolicyFile(ctx.cwd)}),pi.on("tool_call",async(event,ctx)=>{let[policy,resolved]=await Promise.all([readPolicy(ctx.cwd),(options.resolveActiveState??resolveActivePolicyState)(ctx.cwd)]),active=options.resolveWriteAllow===void 0||resolved.mode==="chat"?resolved:{...resolved,writeAllow:await options.resolveWriteAllow(ctx.cwd)},decision=await evaluateToolCall(event,{active,cwd:ctx.cwd,policy,readDiffStat:options.readDiffStat});if(decision.kind==="allow"){await recordToolRequest(ctx.cwd,event,"allow");return}if(decision.kind==="deny")return await recordToolRequest(ctx.cwd,event,"deny",decision.reason),{block:!0,reason:decision.reason};let key=decision.command===void 0?void 0:`${ctx.cwd}\0${decision.command}`;if(key!==void 0&&sessionAllow.has(key)){await recordToolRequest(ctx.cwd,event,"allow","approved earlier this session");return}await recordToolRequest(ctx.cwd,event,"confirm",decision.title);let choice=await askApproval(ctx.ui,decision);if(choice==="deny")return{block:!0,reason:decision.declineReason};if(key!==void 0&&sessionAllow.add(key),choice==="always"&&decision.command!==void 0)try{let target=await rememberAllowedCommand(ctx.cwd,decision.command);ctx.ui.notify(`Always allowed in ${relative7(ctx.cwd,target)}: ${decision.command}`,"info")}catch(error){let message=error instanceof Error?error.message:String(error);ctx.ui.notify(`Could not record the approval in ${CONFIG_DIR_NAME}/policy.json: ${message}`,"warning")}})}var READ_ONLY_TOOLS=new Set(["read","grep","find","ls"]),FORBIDDEN_PATH_PARTS=new Set(["__proto__","prototype","constructor"]),END_NODE_ID="__end__";function defaultSleep2(milliseconds){return new Promise(resolve26=>{setTimeout(resolve26,milliseconds)})}var GraphNodeContractError=class extends Error{constructor(nodeId,message){super(message),this.name="GraphNodeContractError",this.nodeId=nodeId}},TransientRetriesExhaustedError=class extends Error{constructor(nodeId,reason,spent,cause){super(`node ${nodeId} exhausted maxTransientRetries ${spent} after a ${reason} failure: ${cause instanceof Error?cause.message:String(cause)}`),this.name="TransientRetriesExhaustedError",this.nodeId=nodeId}};function assertString(value,label){if(typeof value!="string"||value.length===0)throw new Error(`${label} must be a non-empty string`)}function assertStringArray(value,label){if(!Array.isArray(value)||value.some(item=>typeof item!="string"))throw new Error(`${label} must be a string array`)}function assertBoolean(value,label){if(typeof value!="boolean")throw new Error(`${label} must be a boolean`)}function assertStatePath(path14,label){if(path14.split(".").some(part=>part.length===0||FORBIDDEN_PATH_PARTS.has(part)))throw new Error(`${label} contains an invalid state path: ${path14}`)}function validateNode(value,index3){if(!isJsonObject(value))throw new Error(`nodes[${index3}] must be an object`);if(assertString(value.id,`nodes[${index3}].id`),assertString(value.type,`nodes[${index3}].type`),value.type==="set"){if(!isJsonObject(value.assignments))throw new Error(`set node ${value.id} must define assignments`);for(let path14 of Object.keys(value.assignments))assertStatePath(path14,`set node ${value.id}`);return}if(value.type==="terminal"){if(!GRAPH_ROUTED_TERMINALS.includes(value.status))throw new Error(`terminal node ${value.id}.status must be one of ${GRAPH_ROUTED_TERMINALS.join(" | ")}`);assertString(value.reason,`terminal node ${value.id}.reason`);return}if(value.type==="human"){assertString(value.title,`human node ${value.id}.title`),assertString(value.question,`human node ${value.id}.question`),assertString(value.statePath,`human node ${value.id}.statePath`),assertStatePath(value.statePath,`human node ${value.id}`);return}if(value.type!=="agent")throw new Error(`node ${value.id} has unsupported type ${value.type}`);if(assertString(value.prompt,`agent node ${value.id}.prompt`),assertBoolean(value.readOnly,`agent node ${value.id}.readOnly`),assertStringArray(value.tools,`agent node ${value.id}.tools`),!isJsonObject(value.context))throw new Error(`agent node ${value.id} must define context`);if(value.context.mode!=="isolated"&&value.context.mode!=="thread")throw new Error(`agent node ${value.id} has invalid context mode`);if(value.context.threadKey!==void 0&&(typeof value.context.threadKey!="string"||value.context.threadKey.length===0))throw new Error(`agent node ${value.id}.context.threadKey must be non-empty`);if(value.readOnly){let mutatingTool=value.tools.find(tool=>!READ_ONLY_TOOLS.has(tool));if(mutatingTool!==void 0)throw new Error(`read-only agent node ${value.id} cannot enable tool ${mutatingTool}`)}if(value.workerRole!==void 0){if(value.workerRole!=="reviewer")throw new Error(`agent node ${value.id}.workerRole must be a known contract-publishing role (got ${String(value.workerRole)})`);let contract=ROLE_CONTRACT_FILE[value.workerRole];if(contract===void 0)throw new Error(`agent node ${value.id}.workerRole ${value.workerRole} has no contract file`);if(value.response===void 0)throw new Error(`agent node ${value.id} with workerRole requires a response contract`);if(!isJsonObject(value.response))throw new Error(`agent node ${value.id}.response must be an object`);if(value.response.path!==contract.file)throw new Error(`agent node ${value.id}.response.path must be ${contract.file} for workerRole ${value.workerRole}`);if(value.response.schema!==contract.schema)throw new Error(`agent node ${value.id}.response.schema must be ${contract.schema} for workerRole ${value.workerRole}`)}if(value.response!==void 0){if(!isJsonObject(value.response))throw new Error(`agent node ${value.id}.response must be an object`);if(assertString(value.response.path,`agent node ${value.id}.response.path`),isAbsolute9(value.response.path)||value.response.path.split(/[\\/]/u).some(part=>part===".."))throw new Error(`agent node ${value.id}.response.path must stay in the run directory`);if(assertString(value.response.schema,`agent node ${value.id}.response.schema`),basename16(value.response.schema)!==value.response.schema)throw new Error(`agent node ${value.id}.response.schema must be a file name`);if(typeof value.response.retries!="number"||!Number.isInteger(value.response.retries)||value.response.retries<0)throw new Error(`agent node ${value.id}.response.retries must be a non-negative integer`);if(!isJsonObject(value.response.state))throw new Error(`agent node ${value.id}.response.state must be an object`);for(let[statePath,responsePath]of Object.entries(value.response.state))assertStatePath(statePath,`agent node ${value.id}.response.state`),assertString(responsePath,`agent node ${value.id}.response.state.${statePath}`),assertStatePath(responsePath,`agent node ${value.id}.response.state`)}}function validateLimits(value){if(!isJsonObject(value))throw new Error("graph limits must be an object");for(let key of["maxSteps","maxNodeRuns","maxConcurrency","maxCostUsd","timeoutMs"]){let limit=value[key];if(typeof limit!="number"||!Number.isFinite(limit)||limit<=0)throw new Error(`graph limits.${key} must be a positive number`)}}function validatePolicy(value){if(!isJsonObject(value))throw new Error("graph policy must be an object");for(let key of["allowNonInteractive","allowNonInteractiveMutations","confirmProjectGraph","confirmMutatingNodes"])assertBoolean(value[key],`graph policy.${key}`);if(value.onHumanDeny!==void 0&&value.onHumanDeny!=="revise"&&value.onHumanDeny!=="end")throw new Error("graph policy.onHumanDeny must be revise | end")}function validateGraphDefinition(value){if(!isJsonObject(value))throw new Error("graph must be an object");if(value.schemaVersion!==2)throw new Error("graph schemaVersion must be 2");if(assertString(value.id,"graph id"),assertString(value.entry,"graph entry"),!Array.isArray(value.nodes)||value.nodes.length===0)throw new Error("graph nodes must be a non-empty array");let nodes=[];for(let[index3,node]of value.nodes.entries())validateNode(node,index3),nodes.push(node);let nodeIds=new Set;for(let node of nodes){if(nodeIds.has(node.id))throw new Error(`duplicate graph node id: ${node.id}`);nodeIds.add(node.id)}if(!nodeIds.has(value.entry))throw new Error(`graph entry does not exist: ${value.entry}`);if(!Array.isArray(value.edges))throw new Error("graph edges must be an array");for(let[index3,edge]of value.edges.entries()){if(!isJsonObject(edge))throw new Error(`edges[${index3}] must be an object`);if(assertString(edge.from,`edges[${index3}].from`),assertString(edge.to,`edges[${index3}].to`),!nodeIds.has(edge.from))throw new Error(`edge source does not exist: ${edge.from}`);if(edge.to!==END_NODE_ID&&!nodeIds.has(edge.to))throw new Error(`edge target does not exist: ${edge.to}`);if(edge.when!==void 0){let conditions=Array.isArray(edge.when)?edge.when:[edge.when];if(conditions.length===0)throw new Error(`edges[${index3}].when must not be empty`);for(let condition of conditions){if(!isJsonObject(condition))throw new Error(`edges[${index3}].when must be a condition or a list of conditions`);if(assertString(condition.path,`edges[${index3}].when.path`),assertStatePath(condition.path,`edges[${index3}].when`),!("equals"in condition))throw new Error(`edges[${index3}].when must define equals`)}}}for(let node of nodes)if(node.type==="terminal"&&value.edges.some(edge=>isJsonObject(edge)&&edge.from===node.id))throw new Error(`terminal node ${node.id} cannot have outgoing edges`);if(validateLimits(value.limits),validatePolicy(value.policy),isJsonObject(value.policy)&&value.policy.allowNonInteractive===!0){let humanNode=nodes.find(node=>node.type==="human");if(humanNode!==void 0)throw new Error(`non-interactive graph ${value.id} cannot contain human node ${humanNode.id}`)}}async function loadGraph(path14){let value=JSON.parse(await readFile20(path14,"utf8"));return validateGraphDefinition(value),value}async function loadNamedGraph(projectRoot,name){let fileName=basename16(name.endsWith(".json")?name:`${name}.json`);if(fileName!==name&&`${fileName.slice(0,-5)}`!==name)throw new Error(`Invalid graph name: ${name}`);let projectPath=join53(projectRoot,CONFIG_DIR_NAME,"graphs",fileName);try{return await loadGraph(projectPath)}catch(error){if(error.code!=="ENOENT")throw error}return loadGraph(join53(getKpiResourceDir(),"graphs",fileName))}function getStatePath(values,path14){let current=values;for(let part of path14.split(".")){if(!isJsonObject(current)||!(part in current))return;current=current[part]}return current}function setStatePath(values,path14,value){let parts=path14.split("."),current=values;for(let part of parts.slice(0,-1)){let next=current[part];isJsonObject(next)||(current[part]={}),current=current[part]}current[parts.at(-1)]=structuredClone(value)}function safeThreadKey(value){return value.replace(/[^a-zA-Z0-9._-]/g,"-")}async function loadResponseSchema(projectRoot,name){let projectPath=join53(projectRoot,CONFIG_DIR_NAME,"schemas",name);try{return JSON.parse(await readFile20(projectPath,"utf8"))}catch(error){if(error.code!=="ENOENT")throw error}return JSON.parse(await readFile20(join53(getKpiResourceDir(),"schemas",name),"utf8"))}async function resolveActiveWriteAllow(cwd){let job=await readLiveJob(cwd);if(job===void 0)return[];let task=JSON.parse(await readFile20(join53(job.directory,"task.json"),"utf8")),allow=[...writeAllowForTask(task)],runRelative=relative8(resolve19(cwd),resolve19(job.directory)).replaceAll("\\","/");return runRelative.length>0&&!runRelative.startsWith("..")&&allow.push(`${runRelative}/candidate.json`),allow}function graphAgentExtensionFactories(){return[{name:"k-pi-graph-agent",factory:pi=>{registerLocalProviders(pi,{resolveSlots:async poolId=>((await new AccountsStore().read()).pools[poolId]?.slots??[]).flatMap(slot=>slot.kind==="local"&&slot.baseUrl!==void 0?[{slotId:slot.id,baseUrl:slot.baseUrl,secretRef:slot.secretRef}]:[]),resolveToken:async(poolId,slotId)=>{let store=new AccountsStore,slot=(await store.read()).pools[poolId]?.slots.find(candidate=>candidate.id===slotId),reference=slot?.kind==="local"?slot.secretRef:void 0;if(reference===void 0)return;let credential=(await store.readSecrets())[reference];return credential?.type==="api_key"?credential.key:credential?.type==="oauth"?credential.access:void 0}}),registerPolicy(pi,{resolveWriteAllow:resolveActiveWriteAllow})}}]}var GraphEngine=class _GraphEngine{constructor(graph,options,initialState){this.threadSessions=new Map,this.sessionCostUsd=0,this.sessionCostBaseline=new WeakMap,this.checkpointWrites=Promise.resolve(),validateGraphDefinition(graph),this.graph=graph,this.options=options,this.uiContext=options.uiContext,this.nodes=new Map(graph.nodes.map(node=>[node.id,node])),this.sessionFactory=options.createAgentSession??createAgentSession,this.now=options.now??Date.now,this.sessionCostUsd=0;let checkpointCost=initialState!==void 0&&typeof initialState.budget?.costUsd=="number"&&Number.isFinite(initialState.budget.costUsd)?Math.max(0,initialState.budget.costUsd):0,externalMeter=options.accumulatedCostUsd;if(externalMeter!==void 0?(this.baselineCostUsd=0,this.accumulatedCostUsd=()=>Math.max(0,externalMeter())+this.sessionCostUsd):(this.baselineCostUsd=checkpointCost,this.accumulatedCostUsd=()=>this.baselineCostUsd+this.sessionCostUsd),this.sleep=options.sleep??defaultSleep2,this.retryBaseDelayMs=options.retryBaseDelayMs??DEFAULT_RETRY_BASE_MS,initialState===void 0){let limits=resolveGraphBudgetLimits(graph.limits,options.limits);this.runState={graphId:graph.id,jobId:options.jobId,status:"running",superstep:0,active:[graph.entry],values:{policy:{onHumanDeny:graph.policy.onHumanDeny??"revise"}},nodes:Object.fromEntries(graph.nodes.map(node=>[node.id,{status:"pending",runs:0}])),budget:{limits,startedAtMs:this.now(),elapsedMs:0,costUsd:0,round:0,batches:0}}}else{if(!isBudgetState(initialState.budget))throw new Error("checkpoint is missing budget counters");this.runState=initialState,isJsonObject(this.runState.values.policy)||(this.runState.values.policy={onHumanDeny:graph.policy.onHumanDeny??"revise"}),this.runState.budget.limits=resolveGraphBudgetLimits(graph.limits,options.limits??initialState.budget.limits),this.rearmIfAffordable()}if(this.runState.graphId!==graph.id||this.runState.jobId!==options.jobId)throw new Error("checkpoint does not match graph and job")}get state(){return this.runState}get limits(){return this.runState.budget.limits}rearmIfAffordable(){if(this.runState.status!=="exhausted"||this.runState.active.length===0)return;let limits=this.runState.budget.limits,terminal=this.runState.terminal;if(terminal?.limit==="maxTransientRetries"){if(terminal.nodes.some(nodeId=>(this.runState.nodes[nodeId]?.transientRetries??0)>=limits.maxTransientRetries))return;this.runState.status="running",delete this.runState.terminal;for(let nodeId of this.runState.active){let nodeState=this.runState.nodes[nodeId];nodeState.status==="exhausted"&&(nodeState.status=terminal.nodes.includes(nodeId)?"running":"pending")}return}if(findExhaustedRunLimit(limits,this.readBudget())===void 0){this.runState.status="running",delete this.runState.terminal;for(let nodeId of this.runState.active){let nodeState=this.runState.nodes[nodeId];nodeState.status==="exhausted"&&(nodeState.status="pending")}}}runDirectory(){return join53(this.options.projectRoot,CONFIG_DIR_NAME,"runs",this.options.jobId)}nodePrompt(node){let lines=[node.prompt.replaceAll("{{job_id}}",this.options.jobId),"",`Job: ${this.options.jobId}`,`Run directory: ${this.runDirectory()}`,"Read task.json and context.md from the run directory before acting."];return node.response!==void 0&&lines.push(`Return only JSON matching ${node.response.schema}; the graph engine writes ${node.response.path}.`),lines.join(`
1359
+ ${decision.question}`,[...APPROVAL_OPTIONS]);return choice===APPROVAL_OPTIONS[0]?"once":choice===APPROVAL_OPTIONS[1]?"always":"deny"}function requestedPath(event){if(isToolCallEventType("write",event)||isToolCallEventType("edit",event))return event.input.path}async function recordToolRequest(cwd,event,decision,reason){try{let job=await readLiveJob(cwd);if(job===void 0)return;let path14=requestedPath(event);await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"tool.request",job_id:job.jobId,round:typeof job.state.round=="number"?job.state.round:0,node:typeof job.state.node=="string"?job.state.node:"tool",tool:event.toolName,decision,...path14===void 0?{}:{path:path14},...reason===void 0?{}:{reason}})}catch{}}function registerPolicy(pi,options={}){let sessionAllow=options.sessionAllow??new Set;pi.on("session_start",async(_event,ctx)=>{await shouldSeedPolicyFile(ctx.cwd)&&await ensurePolicyFile(ctx.cwd)}),pi.on("tool_call",async(event,ctx)=>{let[policy,resolved]=await Promise.all([readPolicy(ctx.cwd),(options.resolveActiveState??resolveActivePolicyState)(ctx.cwd)]),active=options.resolveWriteAllow===void 0||resolved.mode==="chat"?resolved:{...resolved,writeAllow:await options.resolveWriteAllow(ctx.cwd)},decision=await evaluateToolCall(event,{active,cwd:ctx.cwd,policy,readDiffStat:options.readDiffStat});if(decision.kind==="allow"){await recordToolRequest(ctx.cwd,event,"allow");return}if(decision.kind==="deny")return await recordToolRequest(ctx.cwd,event,"deny",decision.reason),{block:!0,reason:decision.reason};let key=decision.command===void 0?void 0:`${ctx.cwd}\0${decision.command}`;if(key!==void 0&&sessionAllow.has(key)){await recordToolRequest(ctx.cwd,event,"allow","approved earlier this session");return}await recordToolRequest(ctx.cwd,event,"confirm",decision.title);let choice=await askApproval(ctx.ui,decision);if(choice==="deny")return{block:!0,reason:decision.declineReason};if(key!==void 0&&sessionAllow.add(key),choice==="always"&&decision.command!==void 0)try{let target=await rememberAllowedCommand(ctx.cwd,decision.command);ctx.ui.notify(`Always allowed in ${relative7(ctx.cwd,target)}: ${decision.command}`,"info")}catch(error){let message=error instanceof Error?error.message:String(error);ctx.ui.notify(`Could not record the approval in ${CONFIG_DIR_NAME}/policy.json: ${message}`,"warning")}})}var READ_ONLY_TOOLS=new Set(["read","grep","find","ls"]),FORBIDDEN_PATH_PARTS=new Set(["__proto__","prototype","constructor"]),END_NODE_ID="__end__";function defaultSleep2(milliseconds){return new Promise(resolve26=>{setTimeout(resolve26,milliseconds)})}var GraphNodeContractError=class extends Error{constructor(nodeId,message){super(message),this.name="GraphNodeContractError",this.nodeId=nodeId}},GraphNodeProviderError=class extends Error{constructor(nodeId,reason){super(`agent node ${nodeId} provider failed: ${reason}`),this.name="GraphNodeProviderError",this.nodeId=nodeId;let status=/^(\d{3})\b/u.exec(reason.trim());status!==null&&(this.status=Number(status[1]))}},TransientRetriesExhaustedError=class extends Error{constructor(nodeId,reason,spent,cause){super(`node ${nodeId} exhausted maxTransientRetries ${spent} after a ${reason} failure: ${cause instanceof Error?cause.message:String(cause)}`),this.name="TransientRetriesExhaustedError",this.nodeId=nodeId}};function assertString(value,label){if(typeof value!="string"||value.length===0)throw new Error(`${label} must be a non-empty string`)}function assertStringArray(value,label){if(!Array.isArray(value)||value.some(item=>typeof item!="string"))throw new Error(`${label} must be a string array`)}function assertBoolean(value,label){if(typeof value!="boolean")throw new Error(`${label} must be a boolean`)}function assertStatePath(path14,label){if(path14.split(".").some(part=>part.length===0||FORBIDDEN_PATH_PARTS.has(part)))throw new Error(`${label} contains an invalid state path: ${path14}`)}function validateNode(value,index3){if(!isJsonObject(value))throw new Error(`nodes[${index3}] must be an object`);if(assertString(value.id,`nodes[${index3}].id`),assertString(value.type,`nodes[${index3}].type`),value.type==="set"){if(!isJsonObject(value.assignments))throw new Error(`set node ${value.id} must define assignments`);for(let path14 of Object.keys(value.assignments))assertStatePath(path14,`set node ${value.id}`);return}if(value.type==="terminal"){if(!GRAPH_ROUTED_TERMINALS.includes(value.status))throw new Error(`terminal node ${value.id}.status must be one of ${GRAPH_ROUTED_TERMINALS.join(" | ")}`);assertString(value.reason,`terminal node ${value.id}.reason`);return}if(value.type==="human"){assertString(value.title,`human node ${value.id}.title`),assertString(value.question,`human node ${value.id}.question`),assertString(value.statePath,`human node ${value.id}.statePath`),assertStatePath(value.statePath,`human node ${value.id}`);return}if(value.type!=="agent")throw new Error(`node ${value.id} has unsupported type ${value.type}`);if(assertString(value.prompt,`agent node ${value.id}.prompt`),assertBoolean(value.readOnly,`agent node ${value.id}.readOnly`),assertStringArray(value.tools,`agent node ${value.id}.tools`),!isJsonObject(value.context))throw new Error(`agent node ${value.id} must define context`);if(value.context.mode!=="isolated"&&value.context.mode!=="thread")throw new Error(`agent node ${value.id} has invalid context mode`);if(value.context.threadKey!==void 0&&(typeof value.context.threadKey!="string"||value.context.threadKey.length===0))throw new Error(`agent node ${value.id}.context.threadKey must be non-empty`);if(value.readOnly){let mutatingTool=value.tools.find(tool=>!READ_ONLY_TOOLS.has(tool));if(mutatingTool!==void 0)throw new Error(`read-only agent node ${value.id} cannot enable tool ${mutatingTool}`)}if(value.workerRole!==void 0){if(value.workerRole!=="reviewer")throw new Error(`agent node ${value.id}.workerRole must be a known contract-publishing role (got ${String(value.workerRole)})`);let contract=ROLE_CONTRACT_FILE[value.workerRole];if(contract===void 0)throw new Error(`agent node ${value.id}.workerRole ${value.workerRole} has no contract file`);if(value.response===void 0)throw new Error(`agent node ${value.id} with workerRole requires a response contract`);if(!isJsonObject(value.response))throw new Error(`agent node ${value.id}.response must be an object`);if(value.response.path!==contract.file)throw new Error(`agent node ${value.id}.response.path must be ${contract.file} for workerRole ${value.workerRole}`);if(value.response.schema!==contract.schema)throw new Error(`agent node ${value.id}.response.schema must be ${contract.schema} for workerRole ${value.workerRole}`)}if(value.response!==void 0){if(!isJsonObject(value.response))throw new Error(`agent node ${value.id}.response must be an object`);if(assertString(value.response.path,`agent node ${value.id}.response.path`),isAbsolute9(value.response.path)||value.response.path.split(/[\\/]/u).some(part=>part===".."))throw new Error(`agent node ${value.id}.response.path must stay in the run directory`);if(assertString(value.response.schema,`agent node ${value.id}.response.schema`),basename16(value.response.schema)!==value.response.schema)throw new Error(`agent node ${value.id}.response.schema must be a file name`);if(typeof value.response.retries!="number"||!Number.isInteger(value.response.retries)||value.response.retries<0)throw new Error(`agent node ${value.id}.response.retries must be a non-negative integer`);if(!isJsonObject(value.response.state))throw new Error(`agent node ${value.id}.response.state must be an object`);for(let[statePath,responsePath]of Object.entries(value.response.state))assertStatePath(statePath,`agent node ${value.id}.response.state`),assertString(responsePath,`agent node ${value.id}.response.state.${statePath}`),assertStatePath(responsePath,`agent node ${value.id}.response.state`)}}function validateLimits(value){if(!isJsonObject(value))throw new Error("graph limits must be an object");for(let key of["maxSteps","maxNodeRuns","maxConcurrency","maxCostUsd","timeoutMs"]){let limit=value[key];if(typeof limit!="number"||!Number.isFinite(limit)||limit<=0)throw new Error(`graph limits.${key} must be a positive number`)}}function validatePolicy(value){if(!isJsonObject(value))throw new Error("graph policy must be an object");for(let key of["allowNonInteractive","allowNonInteractiveMutations","confirmProjectGraph","confirmMutatingNodes"])assertBoolean(value[key],`graph policy.${key}`);if(value.onHumanDeny!==void 0&&value.onHumanDeny!=="revise"&&value.onHumanDeny!=="end")throw new Error("graph policy.onHumanDeny must be revise | end")}function validateGraphDefinition(value){if(!isJsonObject(value))throw new Error("graph must be an object");if(value.schemaVersion!==2)throw new Error("graph schemaVersion must be 2");if(assertString(value.id,"graph id"),assertString(value.entry,"graph entry"),!Array.isArray(value.nodes)||value.nodes.length===0)throw new Error("graph nodes must be a non-empty array");let nodes=[];for(let[index3,node]of value.nodes.entries())validateNode(node,index3),nodes.push(node);let nodeIds=new Set;for(let node of nodes){if(nodeIds.has(node.id))throw new Error(`duplicate graph node id: ${node.id}`);nodeIds.add(node.id)}if(!nodeIds.has(value.entry))throw new Error(`graph entry does not exist: ${value.entry}`);if(!Array.isArray(value.edges))throw new Error("graph edges must be an array");for(let[index3,edge]of value.edges.entries()){if(!isJsonObject(edge))throw new Error(`edges[${index3}] must be an object`);if(assertString(edge.from,`edges[${index3}].from`),assertString(edge.to,`edges[${index3}].to`),!nodeIds.has(edge.from))throw new Error(`edge source does not exist: ${edge.from}`);if(edge.to!==END_NODE_ID&&!nodeIds.has(edge.to))throw new Error(`edge target does not exist: ${edge.to}`);if(edge.when!==void 0){let conditions=Array.isArray(edge.when)?edge.when:[edge.when];if(conditions.length===0)throw new Error(`edges[${index3}].when must not be empty`);for(let condition of conditions){if(!isJsonObject(condition))throw new Error(`edges[${index3}].when must be a condition or a list of conditions`);if(assertString(condition.path,`edges[${index3}].when.path`),assertStatePath(condition.path,`edges[${index3}].when`),!("equals"in condition))throw new Error(`edges[${index3}].when must define equals`)}}}for(let node of nodes)if(node.type==="terminal"&&value.edges.some(edge=>isJsonObject(edge)&&edge.from===node.id))throw new Error(`terminal node ${node.id} cannot have outgoing edges`);if(validateLimits(value.limits),validatePolicy(value.policy),isJsonObject(value.policy)&&value.policy.allowNonInteractive===!0){let humanNode=nodes.find(node=>node.type==="human");if(humanNode!==void 0)throw new Error(`non-interactive graph ${value.id} cannot contain human node ${humanNode.id}`)}}async function loadGraph(path14){let value=JSON.parse(await readFile20(path14,"utf8"));return validateGraphDefinition(value),value}async function loadNamedGraph(projectRoot,name){let fileName=basename16(name.endsWith(".json")?name:`${name}.json`);if(fileName!==name&&`${fileName.slice(0,-5)}`!==name)throw new Error(`Invalid graph name: ${name}`);let projectPath=join53(projectRoot,CONFIG_DIR_NAME,"graphs",fileName);try{return await loadGraph(projectPath)}catch(error){if(error.code!=="ENOENT")throw error}return loadGraph(join53(getKpiResourceDir(),"graphs",fileName))}function getStatePath(values,path14){let current=values;for(let part of path14.split(".")){if(!isJsonObject(current)||!(part in current))return;current=current[part]}return current}function setStatePath(values,path14,value){let parts=path14.split("."),current=values;for(let part of parts.slice(0,-1)){let next=current[part];isJsonObject(next)||(current[part]={}),current=current[part]}current[parts.at(-1)]=structuredClone(value)}function safeThreadKey(value){return value.replace(/[^a-zA-Z0-9._-]/g,"-")}async function loadResponseSchema(projectRoot,name){let projectPath=join53(projectRoot,CONFIG_DIR_NAME,"schemas",name);try{return JSON.parse(await readFile20(projectPath,"utf8"))}catch(error){if(error.code!=="ENOENT")throw error}return JSON.parse(await readFile20(join53(getKpiResourceDir(),"schemas",name),"utf8"))}async function resolveActiveWriteAllow(cwd){let job=await readLiveJob(cwd);if(job===void 0)return[];let task=JSON.parse(await readFile20(join53(job.directory,"task.json"),"utf8")),allow=[...writeAllowForTask(task)],runRelative=relative8(resolve19(cwd),resolve19(job.directory)).replaceAll("\\","/");return runRelative.length>0&&!runRelative.startsWith("..")&&allow.push(`${runRelative}/candidate.json`),allow}function graphAgentExtensionFactories(){return[{name:"k-pi-graph-agent",factory:pi=>{registerLocalProviders(pi,{resolveSlots:async poolId=>((await new AccountsStore().read()).pools[poolId]?.slots??[]).flatMap(slot=>slot.kind==="local"&&slot.baseUrl!==void 0?[{slotId:slot.id,baseUrl:slot.baseUrl,secretRef:slot.secretRef}]:[]),resolveToken:async(poolId,slotId)=>{let store=new AccountsStore,slot=(await store.read()).pools[poolId]?.slots.find(candidate=>candidate.id===slotId),reference=slot?.kind==="local"?slot.secretRef:void 0;if(reference===void 0)return;let credential=(await store.readSecrets())[reference];return credential?.type==="api_key"?credential.key:credential?.type==="oauth"?credential.access:void 0}}),registerPolicy(pi,{resolveWriteAllow:resolveActiveWriteAllow})}}]}var GraphEngine=class _GraphEngine{constructor(graph,options,initialState){this.threadSessions=new Map,this.sessionCostUsd=0,this.sessionCostBaseline=new WeakMap,this.checkpointWrites=Promise.resolve(),validateGraphDefinition(graph),this.graph=graph,this.options=options,this.uiContext=options.uiContext,this.nodes=new Map(graph.nodes.map(node=>[node.id,node])),this.sessionFactory=options.createAgentSession??createAgentSession,this.now=options.now??Date.now,this.sessionCostUsd=0;let checkpointCost=initialState!==void 0&&typeof initialState.budget?.costUsd=="number"&&Number.isFinite(initialState.budget.costUsd)?Math.max(0,initialState.budget.costUsd):0,externalMeter=options.accumulatedCostUsd;if(externalMeter!==void 0?(this.baselineCostUsd=0,this.accumulatedCostUsd=()=>Math.max(0,externalMeter())+this.sessionCostUsd):(this.baselineCostUsd=checkpointCost,this.accumulatedCostUsd=()=>this.baselineCostUsd+this.sessionCostUsd),this.sleep=options.sleep??defaultSleep2,this.retryBaseDelayMs=options.retryBaseDelayMs??DEFAULT_RETRY_BASE_MS,initialState===void 0){let limits=resolveGraphBudgetLimits(graph.limits,options.limits);this.runState={graphId:graph.id,jobId:options.jobId,status:"running",superstep:0,active:[graph.entry],values:{policy:{onHumanDeny:graph.policy.onHumanDeny??"revise"}},nodes:Object.fromEntries(graph.nodes.map(node=>[node.id,{status:"pending",runs:0}])),budget:{limits,startedAtMs:this.now(),elapsedMs:0,costUsd:0,round:0,batches:0}}}else{if(!isBudgetState(initialState.budget))throw new Error("checkpoint is missing budget counters");this.runState=initialState,isJsonObject(this.runState.values.policy)||(this.runState.values.policy={onHumanDeny:graph.policy.onHumanDeny??"revise"}),this.runState.budget.limits=resolveGraphBudgetLimits(graph.limits,options.limits??initialState.budget.limits),this.rearmIfAffordable()}if(this.runState.graphId!==graph.id||this.runState.jobId!==options.jobId)throw new Error("checkpoint does not match graph and job")}get state(){return this.runState}get limits(){return this.runState.budget.limits}rearmIfAffordable(){if(this.runState.status!=="exhausted"||this.runState.active.length===0)return;let limits=this.runState.budget.limits,terminal=this.runState.terminal;if(terminal?.limit==="maxTransientRetries"){if(terminal.nodes.some(nodeId=>(this.runState.nodes[nodeId]?.transientRetries??0)>=limits.maxTransientRetries))return;this.runState.status="running",delete this.runState.terminal;for(let nodeId of this.runState.active){let nodeState=this.runState.nodes[nodeId];nodeState.status==="exhausted"&&(nodeState.status=terminal.nodes.includes(nodeId)?"running":"pending")}return}if(findExhaustedRunLimit(limits,this.readBudget())===void 0){this.runState.status="running",delete this.runState.terminal;for(let nodeId of this.runState.active){let nodeState=this.runState.nodes[nodeId];nodeState.status==="exhausted"&&(nodeState.status="pending")}}}runDirectory(){return join53(this.options.projectRoot,CONFIG_DIR_NAME,"runs",this.options.jobId)}nodePrompt(node){let lines=[node.prompt.replaceAll("{{job_id}}",this.options.jobId),"",`Job: ${this.options.jobId}`,`Run directory: ${this.runDirectory()}`,"Read task.json and context.md from the run directory before acting."];return node.response!==void 0&&lines.push(`Return only JSON matching ${node.response.schema}; the graph engine writes ${node.response.path}.`),lines.join(`
1360
1360
  `)}workerNodePrompt(node){let lines=[node.prompt.replaceAll("{{job_id}}",this.options.jobId),"",`Job: ${this.options.jobId}`,`Run directory: ${this.runDirectory()}`,"Read task.json, context.md, candidate.json, and evidence from the run directory before acting.","Inspect the candidate and quality-gate results against every required acceptance criterion.","Do not change repository product files."];return node.response!==void 0&&lines.push(`Publish the verdict only by calling write_contract with path ${node.response.path} and a payload matching ${node.response.schema}.`,"write_contract is pinned to this worker, job, role, and path; it is the only authoritative publication.","Assistant transcript text is never the verdict and never authorizes release."),lines.join(`
1361
1361
  `)}checkpointDirectory(){return join53(this.runDirectory(),"graph")}writeCheckpoint(){let name=`checkpoint-${String(this.runState.superstep).padStart(6,"0")}.json`,snapshot2=`${JSON.stringify(this.runState,null,2)}
1362
- `,write=this.checkpointWrites.then(()=>atomicWrite(join53(this.checkpointDirectory(),name),snapshot2));return this.checkpointWrites=write.catch(()=>{}),write}outgoing(nodeId){return this.graph.edges.filter(edge=>edge.from===nodeId)}edgeFires(edge,values){return edge.when===void 0?!0:(Array.isArray(edge.when)?edge.when:[edge.when]).every(condition=>isDeepStrictEqual2(getStatePath(values,condition.path),condition.equals))}route(nodeIds,values){let targets=new Set,terminal,gap;for(let nodeId of nodeIds){let outgoing=this.outgoing(nodeId),fired=!1;for(let edge of outgoing){if(!this.edgeFires(edge,values))continue;fired=!0;let target=this.nodes.get(edge.to);if(target?.type==="terminal"){terminal??=target;continue}targets.add(edge.to)}!fired&&outgoing.length>0&&(gap??=nodeId)}return targets.delete(END_NODE_ID),{targets:[...targets],terminal,gap}}recordSessionCost(session){let stats=session.getSessionStats?.();if(stats===void 0||typeof stats.cost!="number"||!Number.isFinite(stats.cost))return;let previous=this.sessionCostBaseline.get(session)??0,delta=Math.max(0,stats.cost-previous);this.sessionCostBaseline.set(session,stats.cost),this.sessionCostUsd+=delta}async createSessionForNode(node){let threadKey=node.context.threadKey??node.id;if(node.context.mode==="thread"){let existing=this.threadSessions.get(threadKey);if(existing!==void 0)return{session:existing,disposeAfter:!1}}let sessionDirectory=join53(this.options.projectRoot,CONFIG_DIR_NAME,"runs",this.options.jobId,"agents",safeThreadKey(threadKey));await mkdir11(sessionDirectory,{recursive:!0});let sessionManager=SessionManager.continueRecent(this.options.projectRoot,sessionDirectory),agentDir=getAgentDir(),settingsManager=SettingsManager.create(this.options.projectRoot,agentDir),resourceLoader=new DefaultResourceLoader({cwd:this.options.projectRoot,agentDir,settingsManager,extensionFactories:graphAgentExtensionFactories()});await resourceLoader.reload();let result=await this.sessionFactory({cwd:this.options.projectRoot,agentDir,sessionManager,settingsManager,resourceLoader,tools:[...node.tools],excludeTools:node.readOnly?["bash","edit","write"]:void 0});if(this.uiContext!==void 0){let session=result.session;typeof session.bindExtensions=="function"&&await session.bindExtensions({uiContext:this.uiContext,mode:"rpc"})}let unexpectedTool=node.readOnly?result.session.getActiveToolNames().find(tool=>!node.tools.includes(tool)):void 0;if(unexpectedTool!==void 0)throw result.session.dispose(),new GraphNodeContractError(node.id,`read-only agent node ${node.id} registered forbidden tool ${unexpectedTool}`);return node.context.mode==="thread"&&this.threadSessions.set(threadKey,result.session),{session:result.session,disposeAfter:node.context.mode==="isolated"}}async executeNode(node){if(node.type==="set")return{nodeId:node.id,assignments:node.assignments};if(node.type==="human")throw new Error(`human node ${node.id} must interrupt before execution`);if(node.type==="terminal")throw new Error(`terminal node ${node.id} must stop the run before execution`);if(node.workerRole!==void 0)return this.executeWorkerAgentNode(node);let{session,disposeAfter}=await this.createSessionForNode(node);this.runState.nodes[node.id].sessionId=session.sessionId;try{if(node.response===void 0)return await session.prompt(this.nodePrompt(node)),{nodeId:node.id,assignments:{}};let schema=await loadResponseSchema(this.options.projectRoot,node.response.schema),validationErrors=[];for(let attempt2=0;attempt2<=node.response.retries;attempt2+=1){let prompt=attempt2===0?this.nodePrompt(node):`Your previous response failed ${node.response.schema}: ${validationErrors.join("; ")}. Return corrected JSON only.`;await session.prompt(prompt);let source2=session.getLastAssistantText?.();if(source2===void 0){validationErrors=["assistant response text is unavailable"];continue}let output;try{output=JSON.parse(source2)}catch{validationErrors=["response is not valid JSON"];continue}if(validationErrors=validateJsonSchema(output,schema),validationErrors.length>0)continue;if(!isJsonObject(output)){validationErrors=["response must be a JSON object"];continue}let assignments={};for(let[statePath,responsePath]of Object.entries(node.response.state)){let value=getStatePath(output,responsePath);if(value===void 0){validationErrors=[`response state path ${responsePath} does not exist`];break}assignments[statePath]=structuredClone(value)}if(!(validationErrors.length>0)){if(node.response.path==="stack.json")try{assertDuneStack(output)}catch(error){validationErrors=[error instanceof DuneStackError||error instanceof Error?error.message:String(error)];continue}return await atomicWrite(join53(this.runDirectory(),node.response.path),`${JSON.stringify(output,null,2)}
1363
- `),{nodeId:node.id,assignments}}}throw new GraphNodeContractError(node.id,`agent node ${node.id} failed response validation after ${node.response.retries+1} attempts: ${validationErrors.join("; ")}`)}finally{this.recordSessionCost(session),disposeAfter&&session.dispose()}}async executeWorkerAgentNode(node){if(node.workerRole===void 0||node.response===void 0)throw new GraphNodeContractError(node.id,`worker-role agent node ${node.id} requires workerRole and a response contract`);let bus=new BackgroundBus(this.options.projectRoot,this.runDirectory(),this.options.jobId,this.options.busDependencies??{}),agentId;try{let worker=await bus.spawn({role:node.workerRole,prompt:this.workerNodePrompt(node)});agentId=worker.agentId;let nodeState=this.runState.nodes[node.id];nodeState.sessionId=worker.sessionPath,nodeState.agentId=worker.agentId;let published;try{published=await bus.awaitInitialContract(worker.agentId)}catch(error){throw new GraphNodeContractError(node.id,`worker-role agent node ${node.id} failed closed without a receipt-backed ${node.response.path}: ${error instanceof Error?error.message:String(error)}`)}if(published.receipt.declared_path!==node.response.path)throw new GraphNodeContractError(node.id,`worker published ${published.receipt.declared_path}, expected ${node.response.path}`);let output=published.document;if(!isJsonObject(output))throw new GraphNodeContractError(node.id,`published ${node.response.path} is not a JSON object`);let assignments={};for(let[statePath,responsePath]of Object.entries(node.response.state)){let value=getStatePath(output,responsePath);if(value===void 0)throw new GraphNodeContractError(node.id,`published ${node.response.path} is missing state path ${responsePath}`);assignments[statePath]=structuredClone(value)}return await this.emitReviewVerdictIfNeeded(node,output),{nodeId:node.id,assignments}}finally{agentId!==void 0&&await bus.stop(agentId).catch(()=>{})}}async emitReviewVerdictIfNeeded(node,output){let path14=node.response?.path;if(!(node.workerRole==="reviewer"||path14==="verdict.json"||path14?.endsWith("/verdict.json")===!0))return;let fields=buildReviewVerdictEventFields(output);fields!==void 0&&await appendEvent(join53(this.runDirectory(),"events.jsonl"),{ts:new Date().toISOString(),type:"review.verdict",job_id:this.options.jobId,round:this.runState.budget.round,node:node.id,...fields})}async executeWithRetries(node){let nodeState=this.runState.nodes[node.id];for(nodeState.retryRun!==nodeState.runs&&(nodeState.retryRun=nodeState.runs,nodeState.transientRetries=0,nodeState.retryDelaysMs=[]);;)try{return await this.executeNode(node)}catch(error){if(error instanceof GraphNodeContractError)throw error;let reason=classifyTransientFailure(error);if(reason===void 0)throw error;let spent=nodeState.transientRetries??0;if(spent>=this.runState.budget.limits.maxTransientRetries)throw new TransientRetriesExhaustedError(node.id,reason,spent,error);let delayMs=this.retryBaseDelayMs*2**spent;nodeState.transientRetries=spent+1,nodeState.retryDelaysMs=[...nodeState.retryDelaysMs??[],delayMs],nodeState.error=`transient ${reason}: ${error instanceof Error?error.message:String(error)}`,await this.writeCheckpoint(),await this.sleep(delayMs)}}async fail(message,nodeIds){this.runState.status="failed";for(let nodeId of nodeIds)this.runState.nodes[nodeId].status="failed",this.runState.nodes[nodeId].error=message;throw this.runState.superstep+=1,await this.writeCheckpoint(),new Error(message)}readBudget(){let budget=this.runState.budget;return budget.elapsedMs=Math.max(0,this.now()-budget.startedAtMs),budget.costUsd=this.accumulatedCostUsd(),{superstep:this.runState.superstep,elapsedMs:budget.elapsedMs,costUsd:budget.costUsd}}async exhaust(exhaustion,nodeIds){this.runState.status="exhausted";for(let nodeId of nodeIds)this.runState.nodes[nodeId].status="exhausted";let terminal={status:"EXHAUSTED",limit:exhaustion.limit,reason:exhaustion.reason,round:this.runState.budget.round,superstep:this.runState.superstep,nodes:[...nodeIds]};return this.runState.terminal=terminal,this.runState.superstep+=1,await this.writeCheckpoint(),await this.emitTerminal(terminal),this.runState}async terminate(node,pending){this.runState.status="terminated",this.runState.active=[...pending];let terminal={status:node.status,reason:node.reason,round:this.runState.budget.round,superstep:this.runState.superstep,nodes:[node.id]};return this.runState.terminal=terminal,this.runState.nodes[node.id].status="completed",this.runState.superstep+=1,await this.writeCheckpoint(),await this.emitTerminal(terminal),this.runState}async emitTerminal(terminal){if(this.options.emitTerminal!==void 0){await this.options.emitTerminal(terminal);return}await appendEvent(join53(this.runDirectory(),"events.jsonl"),{ts:new Date(this.now()).toISOString(),type:"loop.terminal",job_id:this.options.jobId,round:terminal.round,node:terminal.nodes[0]??"graph",status:terminal.status,reason:terminal.reason})}async runSuperstep(){if(this.runState.status==="interrupted")throw new Error("graph is interrupted and must be resumed");if(this.runState.status!=="running")return this.runState;let limits=this.runState.budget.limits,runExhaustion=findExhaustedRunLimit(limits,this.readBudget());if(runExhaustion!==void 0)return this.exhaust(runExhaustion,this.runState.active);let activeNodes=this.runState.active.map(id=>{let node=this.nodes.get(id);if(node===void 0)throw new Error(`active graph node does not exist: ${id}`);return node});for(let node of activeNodes){let nodeExhaustion=findExhaustedNodeLimit(limits,node.id,this.runState.nodes[node.id].runs);if(nodeExhaustion!==void 0)return this.exhaust(nodeExhaustion,[node.id])}let humanNode=activeNodes.find(node=>node.type==="human");if(humanNode!==void 0){if(activeNodes.length!==1||humanNode.type!=="human")return this.fail("human nodes cannot share a superstep",this.runState.active);let nodeState=this.runState.nodes[humanNode.id];return nodeState.runs+=1,nodeState.status="interrupted",this.countRound(),this.runState.status="interrupted",this.runState.pendingHuman={nodeId:humanNode.id,title:humanNode.title,question:humanNode.question},this.runState.superstep+=1,await this.writeCheckpoint(),this.runState}let results=[],executed=[];for(let[index3,batch]of batchReadyNodes(activeNodes,limits.maxConcurrency).entries()){if(index3>0){let batchExhaustion=findExhaustedRunLimit(limits,this.readBudget());if(batchExhaustion!==void 0){let pending=activeNodes.filter(node=>!executed.includes(node)).map(node=>node.id),conflict2=this.commitResults(results,executed);return conflict2!==void 0?this.fail(conflict2,this.runState.active):(this.runState.active=pending,this.exhaust(batchExhaustion,pending))}}for(let node of batch){let nodeState=this.runState.nodes[node.id];nodeState.status!=="running"&&(nodeState.runs+=1),nodeState.status="running",delete nodeState.error}this.countRound();let settled=await Promise.allSettled(batch.map(node=>this.executeWithRetries(node))),rejected=[];for(let[index4,outcome]of settled.entries()){let node=batch[index4];if(outcome.status==="fulfilled"){results.push(outcome.value),executed.push(node);continue}rejected.push({node,error:outcome.reason}),this.runState.nodes[node.id].error=outcome.reason instanceof Error?outcome.reason.message:String(outcome.reason)}if(rejected.length>0){let conflict2=this.commitResults(results,executed);if(conflict2!==void 0)return this.fail(conflict2,this.runState.active);this.runState.active=activeNodes.filter(node=>!executed.includes(node)).map(node=>node.id);let first=rejected[0].error;return first instanceof TransientRetriesExhaustedError?this.exhaust({limit:"maxTransientRetries",reason:first.message},[first.nodeId]):this.fail(first instanceof Error?first.message:String(first),rejected.map(entry=>entry.node.id))}this.runState.budget.batches+=1}let conflict=this.commitResults(results,executed);if(conflict!==void 0)return this.fail(conflict,this.runState.active);this.readBudget(),await this.refreshFacts();let routed=this.route(executed.map(node=>node.id),this.runState.values);return routed.terminal!==void 0?this.terminate(routed.terminal,routed.targets):routed.gap!==void 0?this.fail(`no graph edge from ${routed.gap} matched the run state`,[routed.gap]):(this.runState.active=routed.targets,this.runState.status=this.runState.active.length===0?"completed":"running",this.runState.superstep+=1,await this.writeCheckpoint(),this.runState)}async refreshFacts(){let facts=await this.options.resolveFacts?.();if(facts===void 0)return;let values=structuredClone(this.runState.values);for(let[path14,value]of Object.entries(facts))setStatePath(values,path14,value);this.runState.values=values}commitResults(results,executed){let seenPaths=new Set,values=structuredClone(this.runState.values);for(let result of results)for(let[path14,value]of Object.entries(result.assignments)){if(seenPaths.has(path14))return`multiple nodes wrote state path ${path14} in one superstep`;seenPaths.add(path14),setStatePath(values,path14,value)}this.runState.values=values;for(let node of executed)this.runState.nodes[node.id].status="completed"}countRound(){this.runState.budget.round=Object.values(this.runState.nodes).reduce((round,node)=>Math.max(round,node.runs),0)}async runUntilPause(){for(;this.runState.status==="running";)await this.runSuperstep();return this.runState}async submitHuman(approved){let pending=this.runState.pendingHuman;if(this.runState.status!=="interrupted"||pending===void 0)throw new Error("graph has no pending human node");let node=this.nodes.get(pending.nodeId);if(node?.type!=="human")throw new Error(`pending human node does not exist: ${pending.nodeId}`);let values=structuredClone(this.runState.values);setStatePath(values,node.statePath,approved),this.runState.values=values,this.runState.nodes[node.id].status="completed",await this.refreshFacts();let routed=this.route([node.id],this.runState.values);return delete this.runState.pendingHuman,routed.terminal!==void 0?this.terminate(routed.terminal,routed.targets):routed.gap!==void 0?this.fail(`no graph edge from ${routed.gap} matched the run state`,[routed.gap]):(this.runState.active=routed.targets,this.runState.status=this.runState.active.length===0?"completed":"running",this.runState.superstep+=1,await this.writeCheckpoint(),this.runState)}async resume(approved){return await this.submitHuman(approved),this.runUntilPause()}async resumeWithUI(ui){let pending=this.runState.pendingHuman;if(pending===void 0)throw new Error("graph has no pending human node");return this.resume(await ui.confirm(pending.title,pending.question))}dispose(){for(let session of this.threadSessions.values())session.dispose();this.threadSessions.clear()}static async restore(graph,options){let directory=join53(options.projectRoot,CONFIG_DIR_NAME,"runs",options.jobId,"graph"),latest=(await readdir5(directory)).filter(name=>/^checkpoint-\d{6}\.json$/.test(name)).sort().at(-1);if(latest===void 0)throw new Error(`No graph checkpoint found for job ${options.jobId}`);let state2=JSON.parse(await readFile20(join53(directory,latest),"utf8"));return new _GraphEngine(graph,options,state2)}};var DEFAULT_EXA_BASE_URL="https://api.exa.ai",DEFAULT_PERPLEXITY_BASE_URL="https://api.perplexity.ai";var DEFAULT_RESEARCH_ENDPOINTS={exa:DEFAULT_EXA_BASE_URL,perplexity:DEFAULT_PERPLEXITY_BASE_URL},RESEARCH_BASE_URL_ENV={exa:"EXA_BASE_URL",perplexity:"PERPLEXITY_BASE_URL"},ResearchEndpointError=class extends Error{constructor(service,source2,reason){super(`${RESEARCH_BASE_URL_ENV[service]} from ${source2} is not a usable base URL: ${reason}`),this.name="ResearchEndpointError",this.service=service,this.source=source2}};function assertResearchBaseUrl(value,service,source2){let trimmed=value.trim();if(trimmed.length===0)throw new ResearchEndpointError(service,source2,"the value is empty");let url;try{url=new URL(trimmed)}catch{throw new ResearchEndpointError(service,source2,"it is not an absolute URL")}if(url.protocol!=="http:"&&url.protocol!=="https:")throw new ResearchEndpointError(service,source2,`the ${url.protocol.replace(":","")} scheme is not supported`);if(url.username.length>0||url.password.length>0)throw new ResearchEndpointError(service,source2,"it embeds credentials");if(url.search.length>0||url.hash.length>0)throw new ResearchEndpointError(service,source2,"a base URL carries no query or fragment");if(url.hostname.length===0)throw new ResearchEndpointError(service,source2,"it names no host");return`${url.origin}${url.pathname.replace(/\/+$/u,"")}`}function assertResearchTimeoutMs(value,source2){if(!Number.isFinite(value)||!Number.isInteger(value))throw new Error(`Research timeout from ${source2} must be an integer number of milliseconds`);if(value<1e3||value>12e4)throw new Error(`Research timeout from ${source2} must be between 1000 and 120000 ms, received ${value}`);return value}function resolveResearchEndpoints(overrides={},environment=process.env){let resolveOne=service=>{let configured=overrides[service];if(configured!==void 0&&configured.trim().length>0)return assertResearchBaseUrl(configured,service,"settings");let fromEnvironment=environment[RESEARCH_BASE_URL_ENV[service]];return fromEnvironment!==void 0&&fromEnvironment.trim().length>0?assertResearchBaseUrl(fromEnvironment,service,"the environment"):DEFAULT_RESEARCH_ENDPOINTS[service]},timeoutFromEnvironment=environment.RESEARCH_TIMEOUT_MS,timeoutMs=overrides.timeoutMs!==void 0?assertResearchTimeoutMs(overrides.timeoutMs,"settings"):timeoutFromEnvironment!==void 0&&timeoutFromEnvironment.trim().length>0?assertResearchTimeoutMs(Number(timeoutFromEnvironment),"the environment"):15e3;return{endpoints:{exa:resolveOne("exa"),perplexity:resolveOne("perplexity")},timeoutMs}}var ResearchTimeoutError=class extends Error{constructor(service,timeoutMs){super(`${service} request timed out after ${timeoutMs}ms`),this.name="TimeoutError",this.service=service,this.timeoutMs=timeoutMs}};async function fetchBounded(url,init,options){let timeoutMs=options.timeoutMs??15e3,deadline=new AbortController,timer=setTimeout(()=>deadline.abort(),timeoutMs),signals=options.signal===void 0?[deadline.signal]:[deadline.signal,options.signal];try{return await(options.fetch??fetch)(url,{...init,signal:AbortSignal.any(signals)})}catch(error){throw deadline.signal.aborted&&options.signal?.aborted!==!0?new ResearchTimeoutError(options.service,timeoutMs):error}finally{clearTimeout(timer)}}import{readFile as readFile21}from"node:fs/promises";import{join as join54}from"node:path";var ResearchHttpError=class extends Error{constructor(status,service){super(`${service} request failed: ${status}`),this.name="ResearchHttpError",this.status=status,this.service=service}};function boundedCount(value,fallback){return value===void 0||!Number.isFinite(value)?fallback:Math.max(1,Math.min(MAX_RESULTS_PER_REQUEST,Math.trunc(value)))}function usableUrl(value){if(typeof value!="string"||value.trim().length===0)return;let url;try{url=new URL(value.trim())}catch{return}return url.protocol==="http:"||url.protocol==="https:"?url.toString():void 0}function usableTitle(value,fallback){if(typeof value!="string")return fallback;let collapsed=value.replaceAll(/\s+/gu," ").trim();return collapsed.length===0?fallback:clampField(collapsed,300)}function usableDate(value){if(!(typeof value!="string"||value.trim().length===0))return clampField(value.trim(),64)}function boundedText(record){let parts=[],highlights=record.highlights;if(Array.isArray(highlights))for(let highlight2 of highlights)typeof highlight2=="string"&&highlight2.trim().length>0&&parts.push(highlight2.trim());if(parts.length===0&&typeof record.text=="string"&&record.text.trim().length>0&&parts.push(record.text.trim()),parts.length!==0)return clampField(parts.join(`
1362
+ `,write=this.checkpointWrites.then(()=>atomicWrite(join53(this.checkpointDirectory(),name),snapshot2));return this.checkpointWrites=write.catch(()=>{}),write}outgoing(nodeId){return this.graph.edges.filter(edge=>edge.from===nodeId)}edgeFires(edge,values){return edge.when===void 0?!0:(Array.isArray(edge.when)?edge.when:[edge.when]).every(condition=>isDeepStrictEqual2(getStatePath(values,condition.path),condition.equals))}route(nodeIds,values){let targets=new Set,terminal,gap;for(let nodeId of nodeIds){let outgoing=this.outgoing(nodeId),fired=!1;for(let edge of outgoing){if(!this.edgeFires(edge,values))continue;fired=!0;let target=this.nodes.get(edge.to);if(target?.type==="terminal"){terminal??=target;continue}targets.add(edge.to)}!fired&&outgoing.length>0&&(gap??=nodeId)}return targets.delete(END_NODE_ID),{targets:[...targets],terminal,gap}}recordSessionCost(session){let stats=session.getSessionStats?.();if(stats===void 0||typeof stats.cost!="number"||!Number.isFinite(stats.cost))return;let previous=this.sessionCostBaseline.get(session)??0,delta=Math.max(0,stats.cost-previous);this.sessionCostBaseline.set(session,stats.cost),this.sessionCostUsd+=delta}async createSessionForNode(node){let threadKey=node.context.threadKey??node.id;if(node.context.mode==="thread"){let existing=this.threadSessions.get(threadKey);if(existing!==void 0)return{session:existing,disposeAfter:!1}}let sessionDirectory=join53(this.options.projectRoot,CONFIG_DIR_NAME,"runs",this.options.jobId,"agents",safeThreadKey(threadKey));await mkdir11(sessionDirectory,{recursive:!0});let sessionManager=SessionManager.continueRecent(this.options.projectRoot,sessionDirectory),agentDir=getAgentDir(),settingsManager=SettingsManager.create(this.options.projectRoot,agentDir),resourceLoader=new DefaultResourceLoader({cwd:this.options.projectRoot,agentDir,settingsManager,extensionFactories:graphAgentExtensionFactories()});await resourceLoader.reload();let result=await this.sessionFactory({cwd:this.options.projectRoot,agentDir,sessionManager,settingsManager,resourceLoader,model:this.options.model,thinkingLevel:this.options.thinkingLevel,tools:[...node.tools],excludeTools:node.readOnly?["bash","edit","write"]:void 0});if(this.uiContext!==void 0){let session=result.session;typeof session.bindExtensions=="function"&&await session.bindExtensions({uiContext:this.uiContext,mode:"rpc"})}let unexpectedTool=node.readOnly?result.session.getActiveToolNames().find(tool=>!node.tools.includes(tool)):void 0;if(unexpectedTool!==void 0)throw result.session.dispose(),new GraphNodeContractError(node.id,`read-only agent node ${node.id} registered forbidden tool ${unexpectedTool}`);return node.context.mode==="thread"&&this.threadSessions.set(threadKey,result.session),{session:result.session,disposeAfter:node.context.mode==="isolated"}}async executeNode(node){if(node.type==="set")return{nodeId:node.id,assignments:node.assignments};if(node.type==="human")throw new Error(`human node ${node.id} must interrupt before execution`);if(node.type==="terminal")throw new Error(`terminal node ${node.id} must stop the run before execution`);if(node.workerRole!==void 0)return this.executeWorkerAgentNode(node);let{session,disposeAfter}=await this.createSessionForNode(node);this.runState.nodes[node.id].sessionId=session.sessionId;try{if(node.response===void 0){await session.prompt(this.nodePrompt(node));let providerError=session.getLastAssistantError?.();if(providerError!==void 0)throw new GraphNodeProviderError(node.id,providerError);return{nodeId:node.id,assignments:{}}}let schema=await loadResponseSchema(this.options.projectRoot,node.response.schema),validationErrors=[];for(let attempt2=0;attempt2<=node.response.retries;attempt2+=1){let prompt=attempt2===0?this.nodePrompt(node):`Your previous response failed ${node.response.schema}: ${validationErrors.join("; ")}. Return corrected JSON only.`;await session.prompt(prompt);let providerError=session.getLastAssistantError?.();if(providerError!==void 0)throw new GraphNodeProviderError(node.id,providerError);let source2=session.getLastAssistantText?.();if(source2===void 0){validationErrors=["assistant response text is unavailable"];continue}let output;try{output=JSON.parse(source2)}catch{validationErrors=["response is not valid JSON"];continue}if(validationErrors=validateJsonSchema(output,schema),validationErrors.length>0)continue;if(!isJsonObject(output)){validationErrors=["response must be a JSON object"];continue}let assignments={};for(let[statePath,responsePath]of Object.entries(node.response.state)){let value=getStatePath(output,responsePath);if(value===void 0){validationErrors=[`response state path ${responsePath} does not exist`];break}assignments[statePath]=structuredClone(value)}if(!(validationErrors.length>0)){if(node.response.path==="stack.json")try{assertDuneStack(output)}catch(error){validationErrors=[error instanceof DuneStackError||error instanceof Error?error.message:String(error)];continue}return await atomicWrite(join53(this.runDirectory(),node.response.path),`${JSON.stringify(output,null,2)}
1363
+ `),{nodeId:node.id,assignments}}}throw new GraphNodeContractError(node.id,`agent node ${node.id} failed response validation after ${node.response.retries+1} attempts: ${validationErrors.join("; ")}`)}finally{this.recordSessionCost(session),disposeAfter&&session.dispose()}}async executeWorkerAgentNode(node){if(node.workerRole===void 0||node.response===void 0)throw new GraphNodeContractError(node.id,`worker-role agent node ${node.id} requires workerRole and a response contract`);let bus=new BackgroundBus(this.options.projectRoot,this.runDirectory(),this.options.jobId,this.options.busDependencies??{}),agentId;try{let worker=await bus.spawn({role:node.workerRole,prompt:this.workerNodePrompt(node),model:this.options.model===void 0?void 0:`${this.options.model.provider}/${this.options.model.id}`});agentId=worker.agentId;let nodeState=this.runState.nodes[node.id];nodeState.sessionId=worker.sessionPath,nodeState.agentId=worker.agentId;let published;try{published=await bus.awaitInitialContract(worker.agentId)}catch(error){throw new GraphNodeContractError(node.id,`worker-role agent node ${node.id} failed closed without a receipt-backed ${node.response.path}: ${error instanceof Error?error.message:String(error)}`)}if(published.receipt.declared_path!==node.response.path)throw new GraphNodeContractError(node.id,`worker published ${published.receipt.declared_path}, expected ${node.response.path}`);let output=published.document;if(!isJsonObject(output))throw new GraphNodeContractError(node.id,`published ${node.response.path} is not a JSON object`);let assignments={};for(let[statePath,responsePath]of Object.entries(node.response.state)){let value=getStatePath(output,responsePath);if(value===void 0)throw new GraphNodeContractError(node.id,`published ${node.response.path} is missing state path ${responsePath}`);assignments[statePath]=structuredClone(value)}return await this.emitReviewVerdictIfNeeded(node,output),{nodeId:node.id,assignments}}finally{agentId!==void 0&&await bus.stop(agentId).catch(()=>{})}}async emitReviewVerdictIfNeeded(node,output){let path14=node.response?.path;if(!(node.workerRole==="reviewer"||path14==="verdict.json"||path14?.endsWith("/verdict.json")===!0))return;let fields=buildReviewVerdictEventFields(output);fields!==void 0&&await appendEvent(join53(this.runDirectory(),"events.jsonl"),{ts:new Date().toISOString(),type:"review.verdict",job_id:this.options.jobId,round:this.runState.budget.round,node:node.id,...fields})}async executeWithRetries(node){let nodeState=this.runState.nodes[node.id];for(nodeState.retryRun!==nodeState.runs&&(nodeState.retryRun=nodeState.runs,nodeState.transientRetries=0,nodeState.retryDelaysMs=[]);;)try{return await this.executeNode(node)}catch(error){if(error instanceof GraphNodeContractError)throw error;let reason=classifyTransientFailure(error);if(reason===void 0)throw error;let spent=nodeState.transientRetries??0;if(spent>=this.runState.budget.limits.maxTransientRetries)throw new TransientRetriesExhaustedError(node.id,reason,spent,error);let delayMs=this.retryBaseDelayMs*2**spent;nodeState.transientRetries=spent+1,nodeState.retryDelaysMs=[...nodeState.retryDelaysMs??[],delayMs],nodeState.error=`transient ${reason}: ${error instanceof Error?error.message:String(error)}`,await this.writeCheckpoint(),await this.sleep(delayMs)}}async fail(message,nodeIds,cause){this.runState.status="failed";for(let nodeId of nodeIds)this.runState.nodes[nodeId].status="failed",this.runState.nodes[nodeId].error=message;throw this.runState.superstep+=1,await this.writeCheckpoint(),cause??new Error(message)}readBudget(){let budget=this.runState.budget;return budget.elapsedMs=Math.max(0,this.now()-budget.startedAtMs),budget.costUsd=this.accumulatedCostUsd(),{superstep:this.runState.superstep,elapsedMs:budget.elapsedMs,costUsd:budget.costUsd}}async exhaust(exhaustion,nodeIds){this.runState.status="exhausted";for(let nodeId of nodeIds)this.runState.nodes[nodeId].status="exhausted";let terminal={status:"EXHAUSTED",limit:exhaustion.limit,reason:exhaustion.reason,round:this.runState.budget.round,superstep:this.runState.superstep,nodes:[...nodeIds]};return this.runState.terminal=terminal,this.runState.superstep+=1,await this.writeCheckpoint(),await this.emitTerminal(terminal),this.runState}async terminate(node,pending){this.runState.status="terminated",this.runState.active=[...pending];let terminal={status:node.status,reason:node.reason,round:this.runState.budget.round,superstep:this.runState.superstep,nodes:[node.id]};return this.runState.terminal=terminal,this.runState.nodes[node.id].status="completed",this.runState.superstep+=1,await this.writeCheckpoint(),await this.emitTerminal(terminal),this.runState}async emitTerminal(terminal){if(this.options.emitTerminal!==void 0){await this.options.emitTerminal(terminal);return}await appendEvent(join53(this.runDirectory(),"events.jsonl"),{ts:new Date(this.now()).toISOString(),type:"loop.terminal",job_id:this.options.jobId,round:terminal.round,node:terminal.nodes[0]??"graph",status:terminal.status,reason:terminal.reason})}async runSuperstep(){if(this.runState.status==="interrupted")throw new Error("graph is interrupted and must be resumed");if(this.runState.status!=="running")return this.runState;let limits=this.runState.budget.limits,runExhaustion=findExhaustedRunLimit(limits,this.readBudget());if(runExhaustion!==void 0)return this.exhaust(runExhaustion,this.runState.active);let activeNodes=this.runState.active.map(id=>{let node=this.nodes.get(id);if(node===void 0)throw new Error(`active graph node does not exist: ${id}`);return node});for(let node of activeNodes){let nodeExhaustion=findExhaustedNodeLimit(limits,node.id,this.runState.nodes[node.id].runs);if(nodeExhaustion!==void 0)return this.exhaust(nodeExhaustion,[node.id])}let humanNode=activeNodes.find(node=>node.type==="human");if(humanNode!==void 0){if(activeNodes.length!==1||humanNode.type!=="human")return this.fail("human nodes cannot share a superstep",this.runState.active);let nodeState=this.runState.nodes[humanNode.id];return nodeState.runs+=1,nodeState.status="interrupted",this.countRound(),this.runState.status="interrupted",this.runState.pendingHuman={nodeId:humanNode.id,title:humanNode.title,question:humanNode.question},this.runState.superstep+=1,await this.writeCheckpoint(),this.runState}let results=[],executed=[];for(let[index3,batch]of batchReadyNodes(activeNodes,limits.maxConcurrency).entries()){if(index3>0){let batchExhaustion=findExhaustedRunLimit(limits,this.readBudget());if(batchExhaustion!==void 0){let pending=activeNodes.filter(node=>!executed.includes(node)).map(node=>node.id),conflict2=this.commitResults(results,executed);return conflict2!==void 0?this.fail(conflict2,this.runState.active):(this.runState.active=pending,this.exhaust(batchExhaustion,pending))}}for(let node of batch){let nodeState=this.runState.nodes[node.id];nodeState.status!=="running"&&(nodeState.runs+=1),nodeState.status="running",delete nodeState.error}this.countRound();let settled=await Promise.allSettled(batch.map(node=>this.executeWithRetries(node))),rejected=[];for(let[index4,outcome]of settled.entries()){let node=batch[index4];if(outcome.status==="fulfilled"){results.push(outcome.value),executed.push(node);continue}rejected.push({node,error:outcome.reason}),this.runState.nodes[node.id].error=outcome.reason instanceof Error?outcome.reason.message:String(outcome.reason)}if(rejected.length>0){let conflict2=this.commitResults(results,executed);if(conflict2!==void 0)return this.fail(conflict2,this.runState.active);this.runState.active=activeNodes.filter(node=>!executed.includes(node)).map(node=>node.id);let first=rejected[0].error;return first instanceof TransientRetriesExhaustedError?this.exhaust({limit:"maxTransientRetries",reason:first.message},[first.nodeId]):this.fail(first instanceof Error?first.message:String(first),rejected.map(entry=>entry.node.id),first instanceof Error?first:void 0)}this.runState.budget.batches+=1}let conflict=this.commitResults(results,executed);if(conflict!==void 0)return this.fail(conflict,this.runState.active);this.readBudget(),await this.refreshFacts();let routed=this.route(executed.map(node=>node.id),this.runState.values);return routed.terminal!==void 0?this.terminate(routed.terminal,routed.targets):routed.gap!==void 0?this.fail(`no graph edge from ${routed.gap} matched the run state`,[routed.gap]):(this.runState.active=routed.targets,this.runState.status=this.runState.active.length===0?"completed":"running",this.runState.superstep+=1,await this.writeCheckpoint(),this.runState)}async refreshFacts(){let facts=await this.options.resolveFacts?.();if(facts===void 0)return;let values=structuredClone(this.runState.values);for(let[path14,value]of Object.entries(facts))setStatePath(values,path14,value);this.runState.values=values}commitResults(results,executed){let seenPaths=new Set,values=structuredClone(this.runState.values);for(let result of results)for(let[path14,value]of Object.entries(result.assignments)){if(seenPaths.has(path14))return`multiple nodes wrote state path ${path14} in one superstep`;seenPaths.add(path14),setStatePath(values,path14,value)}this.runState.values=values;for(let node of executed)this.runState.nodes[node.id].status="completed"}countRound(){this.runState.budget.round=Object.values(this.runState.nodes).reduce((round,node)=>Math.max(round,node.runs),0)}async runUntilPause(){for(;this.runState.status==="running";)await this.runSuperstep();return this.runState}async submitHuman(approved){let pending=this.runState.pendingHuman;if(this.runState.status!=="interrupted"||pending===void 0)throw new Error("graph has no pending human node");let node=this.nodes.get(pending.nodeId);if(node?.type!=="human")throw new Error(`pending human node does not exist: ${pending.nodeId}`);let values=structuredClone(this.runState.values);setStatePath(values,node.statePath,approved),this.runState.values=values,this.runState.nodes[node.id].status="completed",await this.refreshFacts();let routed=this.route([node.id],this.runState.values);return delete this.runState.pendingHuman,routed.terminal!==void 0?this.terminate(routed.terminal,routed.targets):routed.gap!==void 0?this.fail(`no graph edge from ${routed.gap} matched the run state`,[routed.gap]):(this.runState.active=routed.targets,this.runState.status=this.runState.active.length===0?"completed":"running",this.runState.superstep+=1,await this.writeCheckpoint(),this.runState)}async resume(approved){return await this.submitHuman(approved),this.runUntilPause()}async resumeWithUI(ui){let pending=this.runState.pendingHuman;if(pending===void 0)throw new Error("graph has no pending human node");return this.resume(await ui.confirm(pending.title,pending.question))}dispose(){for(let session of this.threadSessions.values())session.dispose();this.threadSessions.clear()}static async restore(graph,options){let directory=join53(options.projectRoot,CONFIG_DIR_NAME,"runs",options.jobId,"graph"),latest=(await readdir5(directory)).filter(name=>/^checkpoint-\d{6}\.json$/.test(name)).sort().at(-1);if(latest===void 0)throw new Error(`No graph checkpoint found for job ${options.jobId}`);let state2=JSON.parse(await readFile20(join53(directory,latest),"utf8"));return new _GraphEngine(graph,options,state2)}};var DEFAULT_EXA_BASE_URL="https://api.exa.ai",DEFAULT_PERPLEXITY_BASE_URL="https://api.perplexity.ai";var DEFAULT_RESEARCH_ENDPOINTS={exa:DEFAULT_EXA_BASE_URL,perplexity:DEFAULT_PERPLEXITY_BASE_URL},RESEARCH_BASE_URL_ENV={exa:"EXA_BASE_URL",perplexity:"PERPLEXITY_BASE_URL"},ResearchEndpointError=class extends Error{constructor(service,source2,reason){super(`${RESEARCH_BASE_URL_ENV[service]} from ${source2} is not a usable base URL: ${reason}`),this.name="ResearchEndpointError",this.service=service,this.source=source2}};function assertResearchBaseUrl(value,service,source2){let trimmed=value.trim();if(trimmed.length===0)throw new ResearchEndpointError(service,source2,"the value is empty");let url;try{url=new URL(trimmed)}catch{throw new ResearchEndpointError(service,source2,"it is not an absolute URL")}if(url.protocol!=="http:"&&url.protocol!=="https:")throw new ResearchEndpointError(service,source2,`the ${url.protocol.replace(":","")} scheme is not supported`);if(url.username.length>0||url.password.length>0)throw new ResearchEndpointError(service,source2,"it embeds credentials");if(url.search.length>0||url.hash.length>0)throw new ResearchEndpointError(service,source2,"a base URL carries no query or fragment");if(url.hostname.length===0)throw new ResearchEndpointError(service,source2,"it names no host");return`${url.origin}${url.pathname.replace(/\/+$/u,"")}`}function assertResearchTimeoutMs(value,source2){if(!Number.isFinite(value)||!Number.isInteger(value))throw new Error(`Research timeout from ${source2} must be an integer number of milliseconds`);if(value<1e3||value>12e4)throw new Error(`Research timeout from ${source2} must be between 1000 and 120000 ms, received ${value}`);return value}function resolveResearchEndpoints(overrides={},environment=process.env){let resolveOne=service=>{let configured=overrides[service];if(configured!==void 0&&configured.trim().length>0)return assertResearchBaseUrl(configured,service,"settings");let fromEnvironment=environment[RESEARCH_BASE_URL_ENV[service]];return fromEnvironment!==void 0&&fromEnvironment.trim().length>0?assertResearchBaseUrl(fromEnvironment,service,"the environment"):DEFAULT_RESEARCH_ENDPOINTS[service]},timeoutFromEnvironment=environment.RESEARCH_TIMEOUT_MS,timeoutMs=overrides.timeoutMs!==void 0?assertResearchTimeoutMs(overrides.timeoutMs,"settings"):timeoutFromEnvironment!==void 0&&timeoutFromEnvironment.trim().length>0?assertResearchTimeoutMs(Number(timeoutFromEnvironment),"the environment"):15e3;return{endpoints:{exa:resolveOne("exa"),perplexity:resolveOne("perplexity")},timeoutMs}}var ResearchTimeoutError=class extends Error{constructor(service,timeoutMs){super(`${service} request timed out after ${timeoutMs}ms`),this.name="TimeoutError",this.service=service,this.timeoutMs=timeoutMs}};async function fetchBounded(url,init,options){let timeoutMs=options.timeoutMs??15e3,deadline=new AbortController,timer=setTimeout(()=>deadline.abort(),timeoutMs),signals=options.signal===void 0?[deadline.signal]:[deadline.signal,options.signal];try{return await(options.fetch??fetch)(url,{...init,signal:AbortSignal.any(signals)})}catch(error){throw deadline.signal.aborted&&options.signal?.aborted!==!0?new ResearchTimeoutError(options.service,timeoutMs):error}finally{clearTimeout(timer)}}import{readFile as readFile21}from"node:fs/promises";import{join as join54}from"node:path";var ResearchHttpError=class extends Error{constructor(status,service){super(`${service} request failed: ${status}`),this.name="ResearchHttpError",this.status=status,this.service=service}};function boundedCount(value,fallback){return value===void 0||!Number.isFinite(value)?fallback:Math.max(1,Math.min(MAX_RESULTS_PER_REQUEST,Math.trunc(value)))}function usableUrl(value){if(typeof value!="string"||value.trim().length===0)return;let url;try{url=new URL(value.trim())}catch{return}return url.protocol==="http:"||url.protocol==="https:"?url.toString():void 0}function usableTitle(value,fallback){if(typeof value!="string")return fallback;let collapsed=value.replaceAll(/\s+/gu," ").trim();return collapsed.length===0?fallback:clampField(collapsed,300)}function usableDate(value){if(!(typeof value!="string"||value.trim().length===0))return clampField(value.trim(),64)}function boundedText(record){let parts=[],highlights=record.highlights;if(Array.isArray(highlights))for(let highlight2 of highlights)typeof highlight2=="string"&&highlight2.trim().length>0&&parts.push(highlight2.trim());if(parts.length===0&&typeof record.text=="string"&&record.text.trim().length>0&&parts.push(record.text.trim()),parts.length!==0)return clampField(parts.join(`
1364
1364
  `),MAX_FIELD_CHARACTERS)}function asRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}function readStatuses(payload){let failures=new Map,statuses=payload.statuses;if(!Array.isArray(statuses))return failures;for(let entry of statuses){let record=asRecord(entry);if(record===void 0)continue;let url=typeof record.id=="string"?record.id:typeof record.url=="string"?record.url:void 0;if(url===void 0||(typeof record.status=="string"?record.status.toLowerCase():void 0)==="success")continue;let errorRecord=asRecord(record.error);failures.set(url,{url:clampField(url,2048),...typeof errorRecord?.httpStatusCode=="number"?{status:errorRecord.httpStatusCode}:{},...typeof errorRecord?.tag=="string"?{error:clampField(errorRecord.tag,200)}:{}})}return failures}function normalize(payload){let envelope=asRecord(payload);if(envelope===void 0||!Array.isArray(envelope.results))return{results:[],failures:[]};let failures=readStatuses(envelope),results=[];for(let entry of envelope.results.slice(0,MAX_RESULTS_PER_REQUEST)){let record=asRecord(entry);if(record===void 0)continue;let url=usableUrl(record.url)??usableUrl(record.id);url!==void 0&&(failures.has(url)||typeof record.id=="string"&&failures.has(record.id)||results.push({title:usableTitle(record.title,url),url,...usableDate(record.publishedDate)===void 0?{}:{publishedDate:usableDate(record.publishedDate)},...boundedText(record)===void 0?{}:{text:boundedText(record)}}))}return{results,failures:[...failures.values()].slice(0,MAX_CONTENTS_URLS)}}async function request(path14,key,body,transport){let response=await fetchBounded(`${transport.baseUrl??DEFAULT_EXA_BASE_URL}/${path14}`,{method:"POST",headers:{authorization:`Bearer ${key}`,"content-type":"application/json"},body:JSON.stringify(body)},{service:"Exa",timeoutMs:transport.timeoutMs,signal:transport.signal,fetch:transport.fetch});if(!response.ok)throw new ResearchHttpError(response.status,"Exa");return normalize(await response.json())}async function exaSearch(query,key,options={}){let maxCharacters=Math.max(1,Math.min(MAX_FIELD_CHARACTERS,options.maxCharacters??MAX_FIELD_CHARACTERS));return(await request("search",key,{query:clampField(query,MAX_FIELD_CHARACTERS),type:"auto",numResults:boundedCount(options.numResults,5),contents:{highlights:{numSentences:3,highlightsPerUrl:2,maxCharacters}}},options)).results}async function exaContents(urls,key,options={}){let maxCharacters=Math.max(1,Math.min(MAX_FIELD_CHARACTERS,options.maxCharacters??MAX_FIELD_CHARACTERS)),bounded=urls.map(url=>usableUrl(url)).filter(url=>url!==void 0).slice(0,MAX_CONTENTS_URLS);return request("contents",key,{urls:bounded,highlights:{numSentences:3,highlightsPerUrl:2,maxCharacters},...options.includeText===!0?{text:{maxCharacters}}:{}},options)}var PERPLEXITY_SEARCH_PATH="/search",DEFAULT_MAX_TOKENS=2e3,DEFAULT_MAX_TOKENS_PER_PAGE=512;function asRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}function usableUrl2(value){if(!(typeof value!="string"||value.trim().length===0))try{let url=new URL(value.trim());return url.protocol==="http:"||url.protocol==="https:"?url.toString():void 0}catch{return}}function usableTitle2(value,fallback){if(typeof value!="string")return fallback;let collapsed=value.replaceAll(/\s+/gu," ").trim();return collapsed.length===0?fallback:clampField(collapsed,300)}function publishedDate(record){let value=record.date;return typeof value=="string"&&value.trim().length>0?clampField(value.trim(),64):void 0}function boundedSnippet(record){let candidate=typeof record.snippet=="string"?record.snippet:void 0;if(!(candidate===void 0||candidate.trim().length===0))return clampField(candidate.trim(),MAX_FIELD_CHARACTERS)}async function perplexitySearch(query,key,options={}){let maxResults=Math.max(1,Math.min(MAX_RESULTS_PER_REQUEST,Math.trunc(options.maxResults??5))),response=await fetchBounded(`${options.baseUrl??DEFAULT_PERPLEXITY_BASE_URL}${PERPLEXITY_SEARCH_PATH}`,{method:"POST",headers:{authorization:`Bearer ${key}`,"content-type":"application/json"},body:JSON.stringify({query:clampField(query,MAX_FIELD_CHARACTERS),max_results:maxResults,max_tokens:Math.max(1,Math.trunc(options.maxTokens??DEFAULT_MAX_TOKENS)),max_tokens_per_page:Math.max(1,Math.trunc(options.maxTokensPerPage??DEFAULT_MAX_TOKENS_PER_PAGE))})},{service:"Perplexity",timeoutMs:options.timeoutMs,signal:options.signal,fetch:options.fetch});if(!response.ok)throw new ResearchHttpError(response.status,"Perplexity");let payload=asRecord2(await response.json());if(payload===void 0||!Array.isArray(payload.results))return[];let results=[];for(let entry of payload.results.slice(0,MAX_RESULTS_PER_REQUEST)){let record=asRecord2(entry);if(record===void 0)continue;let url=usableUrl2(record.url);url!==void 0&&results.push({title:usableTitle2(record.title,url),url,...publishedDate(record)===void 0?{}:{publishedDate:publishedDate(record)},...boundedSnippet(record)===void 0?{}:{text:boundedSnippet(record)}})}return results}var REQUIRED_EXTERNAL_SOURCES=2;function taskHash(task){return contractHash(task)}var LOCAL_RESEARCH_CANDIDATES=["AGENTS.md","README.md","package.json","docs/spec.md","specs/requirements.md","specs/design.md","specs/tasks.md"];async function collectLocalSources(projectRoot,runDirectory,session){for(let path14 of LOCAL_RESEARCH_CANDIDATES)try{let content=await readFile21(join54(projectRoot,path14),"utf8");session.addLocalSource(path14,path14,clampField(content,1e3))}catch(error){if(error.code!=="ENOENT")throw error}for(let name of["requirements.md","design.md","tasks.md"]){let path14=join54("plan",name);try{let content=await readFile21(join54(runDirectory,path14),"utf8");session.addLocalSource(path14,path14,clampField(content,1e3))}catch(error){if(error.code!=="ENOENT")throw error}}}function alternateQuery(goal){return`${goal} official documentation reference`}async function conductResearch(projectRoot,runDirectory,task,dependencies={}){let session=new ResearchSession({jobId:task.job_id,mode:dependencies.mode??"auto",keys:dependencies.keys??{},eventsPath:dependencies.eventsPath,now:dependencies.now,round:dependencies.round,node:dependencies.node,operatorNoNetwork:dependencies.operatorNoNetwork,maxExternalCalls:dependencies.maxExternalCalls});await session.started();let servedBy,answered;for(let service of session.configuredServices){if(session.callsRemaining===0)break;let queries=[task.goal,alternateQuery(task.goal)];for(let[index3,query]of queries.entries()){let endpoints=dependencies.endpoints??DEFAULT_RESEARCH_ENDPOINTS,outcome=await session.call(service,query,async key=>service==="exa"?exaSearch(query,key,{numResults:MAX_RESULTS_PER_REQUEST,baseUrl:endpoints.exa,timeoutMs:dependencies.timeoutMs,fetch:dependencies.fetch,signal:dependencies.signal}):perplexitySearch(query,key,{maxResults:MAX_RESULTS_PER_REQUEST,baseUrl:endpoints.perplexity,timeoutMs:dependencies.timeoutMs,fetch:dependencies.fetch,signal:dependencies.signal}));if(!outcome.ok)break;if(answered=service,await session.addExternalResults(service,outcome.value)>=REQUIRED_EXTERNAL_SOURCES){servedBy=service;break}if(index3===queries.length-1)break}if(servedBy!==void 0)break}if(servedBy===void 0&&answered!==void 0)throw await session.completed(session.mode),new ResearchShortfallError(answered,session.distinctOrigins);let mode="local";servedBy!==void 0?mode=servedBy:(session.configuredServices.length>0&&await session.exhaust(),session.clearExternalSources(),await collectLocalSources(projectRoot,runDirectory,session));let document={job_id:task.job_id,task_hash:taskHash(task),mode,network:session.network,sources:session.collected};return await session.completed(mode),await writeResearchArtifacts(runDirectory,document),document}async function writeResearchArtifacts(runDirectory,document){await atomicWrite(join54(runDirectory,"research.json"),`${JSON.stringify(document,null,2)}
1365
1365
  `);let lines=[`# Research (${document.mode})`,"",`- network: ${document.network.state}${document.network.origin===void 0?"":` (${document.network.origin})`}`,...document.network.reason===void 0?[]:[`- reason: ${document.network.reason}`],"","## Sources","",...document.sources.map(source2=>source2.kind==="external"?`- [${source2.title}](${source2.ref})${source2.excerpt===void 0?"":` \u2014 ${source2.excerpt.replaceAll(`
1366
1366
  `," ")}`}`:`- \`${source2.ref}\`${source2.excerpt===void 0?"":` \u2014 ${source2.excerpt.replaceAll(`
@@ -1370,14 +1370,16 @@ ${decision.question}`,[...APPROVAL_OPTIONS]);return choice===APPROVAL_OPTIONS[0]
1370
1370
  `).map(line=>line.trim().replace(/^\$\s*/u,"")).filter(line=>line.length>0&&!line.startsWith("#"));if(commands.length>0)return{commands,source:"agents-md",reason:"AGENTS.md Quality gates block"}}let manifest=await readIfPresent2(join55(projectRoot,"package.json"));if(manifest!==void 0){let document={};try{document=JSON.parse(manifest)}catch{document={}}let scripts=isJsonObject(document.scripts)?document.scripts:{},manager=await detectPackageManager(projectRoot,document.packageManager),commands=["test","lint",...typeof scripts.typecheck=="string"?["typecheck"]:["check"]].filter(script=>typeof scripts[script]=="string").map(script=>scriptCommand(manager,script));if(commands.length>0)return{commands,source:"package-scripts",reason:`package.json scripts under ${manager}`}}return{commands:[],source:"none",reason:"no AGENTS.md Quality gates block and package.json declares no test, lint, typecheck or check script"}}async function runtimeDependencies(projectRoot){try{let document=JSON.parse(await readFile22(join55(projectRoot,"package.json"),"utf8"));return Object.keys(document.dependencies??{})}catch(error){if(error.code==="ENOENT")return[];throw error}}function contextFor(invocation,gates,plan){let lines=[`# K-\u03C0 ${invocation.mode} job`,"",`Goal: ${invocation.goal}`,`Mode: ${invocation.mode}`,`Quality gates: ${gates.source} \u2014 ${gates.reason}`];if(plan!==void 0){lines.push("",`Frozen plan: ${plan.label}`);for(let file of plan.files)lines.push("",`## ${basename17(file.source)}`,"",file.content.trimEnd())}return`${lines.join(`
1371
1371
  `)}
1372
1372
  `}async function writePlanSnapshot(runDirectory,plan){for(let file of plan.files)await atomicWrite(join55(runDirectory,file.destination),file.content);let fingerprints=Object.fromEntries(plan.files.map(file=>[file.destination,file.fingerprint]));await atomicWrite(join55(runDirectory,"fingerprints.json"),`${JSON.stringify({plan:fingerprints},null,2)}
1373
- `)}function activeNode(state2){return state2.pendingHuman?.nodeId??state2.active[0]??"done"}function stageFor(node){return node==="quality-green"?"test":node==="plan-check"?"plan":node}function stateDocument(task,state2,stop,terminalStatus,reason){let node=activeNode(state2);return{job_id:task.job_id,mode:task.mode,round:stop.round,maxRounds:stop.maxRounds,stage:stageFor(node),node,passed:isJsonObject(state2.values.test)?state2.values.test.passed:void 0,bounds:state2.values.bounds,review:state2.values.review,release:state2.values.release,ac:task.ac,status:terminalStatus??(state2.status==="interrupted"?"RUNNING":state2.status==="completed"?"DONE":state2.status==="running"?"RUNNING":state2.status.toUpperCase()),reason,graph_status:state2.status,superstep:state2.superstep,pending_question:state2.pendingHuman?.question,limits:state2.budget.limits,started_at_ms:state2.budget.startedAtMs,elapsed_ms:state2.budget.elapsedMs,cost_usd:state2.budget.costUsd,graph_round:state2.budget.round,batches:state2.budget.batches,exhausted_limit:state2.terminal?.limit,evidence_fingerprints:[...stop.evidenceFingerprints],output_fingerprints:[...stop.outputFingerprints],failing_ac_sets:[...stop.failingAcSets],retries:stop.retries,retry_delays_ms:[...stop.retryDelaysMs],playbook:task.playbook,todos:playbookTodos(task)}}function playbookTodos(task){if(!(task.playbook_steps===void 0||task.playbook_steps.length===0))return renderTodos(task.playbook_steps)}async function writeState(runDirectory,task,state2,stop,terminalStatus,reason){await atomicWrite(join55(runDirectory,"state.json"),`${JSON.stringify(stateDocument(task,state2,stop,terminalStatus,reason),null,2)}
1374
- `)}function stringArray(value){return Array.isArray(value)?value.filter(item=>typeof item=="string"):[]}function restoreStopState(document,maxRounds){let retries=typeof document.retries=="number"&&Number.isInteger(document.retries)?document.retries:0;return{...createStopState(maxRounds),round:typeof document.round=="number"?document.round:0,evidenceFingerprints:stringArray(document.evidence_fingerprints).map(stopFingerprint),outputFingerprints:stringArray(document.output_fingerprints).map(stopFingerprint),failingAcSets:stringArray(document.failing_ac_sets),retries:Math.max(0,Math.min(MAX_TRANSIENT_RETRIES,retries)),retryDelaysMs:Array.isArray(document.retry_delays_ms)?document.retry_delays_ms.filter(item=>typeof item=="number"&&Number.isFinite(item)):[]}}async function gitHead(projectRoot){try{let{stdout}=await execFile3("git",["rev-parse","--verify","HEAD"],{cwd:projectRoot});return stdout.trim()}catch{return}}async function createJobBranch(projectRoot,jobId){await execFile3("git",["switch","-c",`kpi/${jobId}`],{cwd:projectRoot})}var SNAPSHOT_EXCLUDED_TREES=["node_modules",".git",CONFIG_DIR_NAME];async function worktreeSnapshot(projectRoot){let{stdout}=await execFile3("git",["status","--porcelain=v1","-z","--untracked-files=all","--ignored=matching","--",".",...SNAPSHOT_EXCLUDED_TREES.map(tree=>`:(exclude)${tree}`)],{cwd:projectRoot}),records=stdout.split("\0"),paths=new Set;for(let index3=0;index3<records.length;index3+=1){let record=records[index3];if(record.length<4)continue;let status=record.slice(0,2);if(paths.add(record.slice(3)),/[RC]/u.test(status)){let source2=records[index3+1];source2!==void 0&&source2.length>0&&(paths.add(source2),index3+=1)}}let runsPrefix=`${CONFIG_DIR_NAME}/runs`,snapshot2=new Map;for(let path14 of paths)if(!(path14===runsPrefix||path14.startsWith(`${runsPrefix}/`)))try{let content=await readFile22(join55(projectRoot,path14));snapshot2.set(path14,createHash7("sha256").update(content).digest("hex"))}catch(error){let code=error.code;if(code==="ENOENT"){snapshot2.set(path14,"<absent>");continue}if(code!=="EISDIR")throw error;let entries=(await readdir6(join55(projectRoot,path14))).sort();snapshot2.set(path14,`<dir>${createHash7("sha256").update(entries.join("\0")).digest("hex")}`)}return snapshot2}function changedPaths(before,after){return[...new Set([...before.keys(),...after.keys()])].filter(path14=>before.get(path14)!==after.get(path14))}async function evidenceFingerprint(runDirectory){let content=await readFile22(join55(runDirectory,"evidence.json"));try{return canonicalFingerprint(JSON.parse(content.toString("utf8")))}catch{return`sha256:${createHash7("sha256").update(content).digest("hex")}`}}async function failingAcIds(runDirectory){let evidence;try{evidence=JSON.parse(await readFile22(join55(runDirectory,"evidence.json"),"utf8"))}catch{return[]}return!isJsonObject(evidence)||!Array.isArray(evidence.ac_results)?[]:evidence.ac_results.flatMap(result=>isJsonObject(result)&&typeof result.id=="string"&&result.passed!==!0?[result.id]:[])}function reviewFingerprint(state2){let review=state2.values.review;if(isJsonObject(review))return typeof review.output_fingerprint=="string"?review.output_fingerprint:void 0}function reviewApproved(state2){let review=state2.values.review;return isJsonObject(review)&&review.approved===!0}function evidencePasses(task,evidence){if(!isJsonObject(evidence))return!1;let commands=evidence.commands,acResults=evidence.ac_results;if(!Array.isArray(commands)||!Array.isArray(acResults))return!1;let latestCommandExit=new Map;for(let command of commands)isJsonObject(command)&&typeof command.cmd=="string"&&typeof command.exit=="number"&&latestCommandExit.set(command.cmd,command.exit);if(latestCommandExit.size===0||[...latestCommandExit.values()].some(exit=>exit!==0))return!1;let passedIds=new Set(acResults.flatMap(result=>isJsonObject(result)&&typeof result.id=="string"&&result.passed===!0?[result.id]:[]));return task.acceptance.filter(criterion=>criterion.required).every(criterion=>passedIds.has(criterion.id))}async function planWasProvided(jobDirectory){try{return(await readdir6(join55(jobDirectory,"plan"))).length>0}catch{return!1}}function shipMarkerPath(jobDirectory){return join55(jobDirectory,"ship.json")}var SHIP_TRAILER_NAME="KPI-Job",COMMIT_SHA_PATTERN=/^[0-9a-f]{40}$/u;function parseShipMarker(value){if(!isJsonObject(value))return;let{job_id:jobId,head,subject,at:at2}=value;if(!(typeof jobId!="string"||jobId.length===0)&&!(typeof head!="string"||!COMMIT_SHA_PATTERN.test(head))&&!(typeof subject!="string"||subject.length===0)&&!(typeof at2!="string"||Number.isNaN(Date.parse(at2)))&&Object.keys(value).length===4)return{job_id:jobId,head,subject,at:at2}}async function commitsSince(projectRoot,previousHead){let range2=previousHead===void 0?"HEAD":`${previousHead}..HEAD`,stdout;try{({stdout}=await execFile3("git",["log",range2,"--format=%H%x1f%s%x1f%B%x1e"],{cwd:projectRoot}))}catch{return[]}return stdout.split("").map(record=>record.replace(/^\n/u,"")).filter(record=>record.length>0).map(record=>{let[head,subject,body]=record.split("");return{head:head??"",subject:subject??"",body:body??""}})}function carriesJobTrailer(body,jobId){return body.split(/\r?\n/u).some(line=>line.trimEnd()===`${SHIP_TRAILER_NAME}: ${jobId}`)}async function isAncestorOfHead(projectRoot,head){try{return await execFile3("git",["merge-base","--is-ancestor",head,"HEAD"],{cwd:projectRoot}),!0}catch{return!1}}async function findJobCommit(projectRoot,jobId,previousHead){let marked=(await commitsSince(projectRoot,previousHead)).filter(commit2=>carriesJobTrailer(commit2.body,jobId));if(marked.length===0)return;if(marked.length>1)throw new Error(`Ambiguous ship commits for ${jobId}: ${marked.map(commit2=>commit2.head.slice(0,8)).join(", ")}`);let[commit]=marked;if(!CONVENTIONAL_COMMIT_PATTERN.test(commit.subject))throw new Error(`Ship commit is not Conventional Commits: ${commit.subject}`);if(!await isAncestorOfHead(projectRoot,commit.head))throw new Error(`Ship commit ${commit.head.slice(0,8)} is not an ancestor of HEAD`);return{head:commit.head,subject:commit.subject}}async function readShipMarker(projectRoot,jobDirectory,jobId){let parsed;try{parsed=parseShipMarker(JSON.parse(await readFile22(shipMarkerPath(jobDirectory),"utf8")))}catch{return}if(parsed===void 0||parsed.job_id!==jobId)return;let claimed=(await commitsSince(projectRoot,void 0)).find(commit=>commit.head===parsed.head);if(!(claimed===void 0||claimed.subject!==parsed.subject||!carriesJobTrailer(claimed.body,jobId)||!await isAncestorOfHead(projectRoot,parsed.head)))return parsed}async function startingHeadFor(jobDirectory){try{return(await readFile22(join55(jobDirectory,"previous-head.txt"),"utf8")).trim()||void 0}catch{return}}async function alreadyShipped(projectRoot,jobDirectory,jobId){if(await readShipMarker(projectRoot,jobDirectory,jobId)!==void 0)return!0;try{return await findJobCommit(projectRoot,jobId,await startingHeadFor(jobDirectory))!==void 0}catch{return!1}}async function writeShipMarker(projectRoot,jobDirectory,jobId,subject,head){let recorded=head??await gitHead(projectRoot);if(recorded===void 0)return;let marker={job_id:jobId,head:recorded,subject,at:new Date().toISOString()};await atomicWrite(shipMarkerPath(jobDirectory),`${JSON.stringify(marker,null,2)}
1375
- `)}function loopFacts(projectRoot,jobDirectory,task,baseline,planProvided){let boundsReason;return{boundsReason:()=>boundsReason,resolve:async()=>{let evidence;try{evidence=JSON.parse(await readFile22(join55(jobDirectory,"evidence.json"),"utf8"))}catch{evidence=void 0}let testPassed=evidence!==void 0&&evidencePasses(task,evidence),evidenceHead=isJsonObject(evidence)&&typeof evidence.head=="string"?evidence.head:void 0,fresh=evidenceHead!==void 0&&evidenceHead===await gitHead(projectRoot);boundsReason=void 0;let current=await worktreeSnapshot(projectRoot),violations=changedPaths(baseline,current).filter(path14=>!isWriteAllowed(projectRoot,path14,writeAllowForTask(task)));if(violations.length>0)boundsReason=`write outside write_allow: ${violations.join(", ")}`;else try{let changes=await observedChangesFromSnapshots(projectRoot,baseline,current,async path14=>{try{let{stdout}=await execFile3("git",["show",`HEAD:${path14}`],{cwd:projectRoot,encoding:"utf8",maxBuffer:2097152});return stdout}catch{return}});await assertMinimalistBounds(projectRoot,jobDirectory,task,changes)}catch(error){boundsReason=error instanceof Error?error.message:String(error)}return{"plan.provided":planProvided,"test.passed":testPassed,"bounds.held":boundsReason===void 0,"fingerprints.fresh":fresh,"ship.shipped":await alreadyShipped(projectRoot,jobDirectory,task.job_id)}}}}async function driveUntilPause(engine,projectRoot,jobDirectory,task,facts,stopState,onStateChange){let state2=engine.state,currentStopState=stopState,shippedThisRun=!1;for(;state2.status==="running";){if(state2.active.some(node=>node==="specify"||node==="plan"||node==="plan-check"))try{await assertResearchFresh(jobDirectory,task)}catch{try{let settings2=await readKpiSettings(projectRoot),{endpoints,timeoutMs}=resolveResearchEndpoints(settings2.researchEndpoints);await conductResearch(projectRoot,jobDirectory,task,{keys:await resolveResearchKeys(),mode:settings2.research,endpoints,timeoutMs,operatorNoNetwork:task.research_network==="offline",eventsPath:join55(jobDirectory,"events.jsonl"),round:currentStopState.round,node:state2.active[0]})}catch(error){if(!(error instanceof ResearchShortfallError))throw error;return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"NEEDS_HUMAN",reason:error.message}}}if(state2.active.includes("implement"))try{await assertResearchFresh(jobDirectory,task);let contract=await readTaskForJob(projectRoot,task.job_id).catch(()=>task);if(stackRequiredFor(contract)){let{module}=await freezeCurrentSlice(projectRoot,jobDirectory,contract);await scaffoldModule(projectRoot,module),await assertScaffoldedBeforeBehavior(projectRoot,module)}}catch(error){return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"UNSAFE",reason:error instanceof Error?error.message:String(error)}}let completedNodes=[...state2.active];completedNodes.includes("ship")&&(shippedThisRun=!0);let prePlan=state2.active.includes("plan");try{state2=await engine.runSuperstep()}catch(error){let message=error instanceof Error?error.message:String(error);if(prePlan&&(/stack\.json|stack\.schema|assertDuneStack|Dune|Layer folder|Module folder|Horizontal delivery|layer sweep|shared module/iu.test(message)||/failed response validation/iu.test(message))){let validation=/^agent node plan failed response validation after (\d+) attempts?: (.+)$/su.exec(message),reason=validation!==null&&/not valid JSON|assistant response text is unavailable|response must be a JSON object/iu.test(validation[2])?`stack.json is missing: plan response was not valid stack.json JSON after ${validation[1]} attempts (${validation[2]})`:message.replace(/^agent node plan failed response validation after \d+ attempts: /u,"");return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"UNSAFE",reason}}throw error}if(state2.status==="exhausted")return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"EXHAUSTED",reason:state2.terminal?.reason??"graph exhausted a configured cap",terminalEmitted:!0};if(state2.status==="terminated"){let terminal=state2.terminal;return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:terminal?.status??"BLOCKED",reason:terminal?.status==="UNSAFE"?facts.boundsReason()??terminal.reason:terminal?.reason??"the graph routed to a terminal",terminalEmitted:!0}}if(completedNodes.includes("review")){let outputFingerprint=reviewFingerprint(state2);if(outputFingerprint===void 0)return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"BLOCKED",reason:"review did not produce an output fingerprint"};if(currentStopState=transitionStopState(currentStopState,{type:"verifier",passed:reviewApproved(state2),evidenceFingerprint:await evidenceFingerprint(jobDirectory),outputFingerprint,failingAcIds:await failingAcIds(jobDirectory)}),currentStopState.status==="NO_PROGRESS"||currentStopState.status==="EXHAUSTED")return{state:currentStopState.status==="EXHAUSTED"?{...state2,terminal:{status:"EXHAUSTED",limit:"maxRounds",reason:"maximum verifier rounds exhausted",round:currentStopState.round,superstep:state2.superstep,nodes:[...state2.active]}}:state2,stopState:currentStopState,shippedThisRun,terminalStatus:currentStopState.status,reason:currentStopState.status==="NO_PROGRESS"?"the same acceptance criteria failed in two rounds":"maximum verifier rounds exhausted"}}await writeState(jobDirectory,task,state2,currentStopState),await onStateChange?.()}return{state:state2,stopState:currentStopState,shippedThisRun}}async function writeTerminalState(jobDirectory,eventsPath,task,result){let status=result.terminalStatus;status!==void 0&&(result.terminalEmitted!==!0&&await appendEvent(eventsPath,{ts:new Date().toISOString(),type:"loop.terminal",job_id:task.job_id,round:result.stopState.round,node:activeNode(result.state),status,reason:result.reason}),await writeState(jobDirectory,task,result.state,result.stopState,status,result.reason))}async function verifyShippedCommit(projectRoot,previousHead,jobId){let head=await gitHead(projectRoot);if(head===void 0||head===previousHead)throw new Error("Ship node did not create a commit");if(previousHead!==void 0){let{stdout:count}=await execFile3("git",["rev-list","--count",`${previousHead}..${head}`],{cwd:projectRoot});if(count.trim()!=="1")throw new Error(`Ship node created ${count.trim()} commits instead of one`)}let{stdout}=await execFile3("git",["log","-1","--pretty=%s"],{cwd:projectRoot}),subject=stdout.trim();if(!CONVENTIONAL_COMMIT_PATTERN.test(subject))throw new Error(`Ship commit is not Conventional Commits: ${subject}`);if(jobId!==void 0){let marked=await findJobCommit(projectRoot,jobId,previousHead);if(marked===void 0)throw new Error(`Ship commit does not carry ${SHIP_TRAILER_NAME}: ${jobId}`);if(marked.head!==head)throw new Error(`Ship commit ${marked.head.slice(0,8)} is not HEAD`)}return subject}async function finalizeShip(projectRoot,jobDirectory,jobId,previousHead,shippedThisRun){if(await readShipMarker(projectRoot,jobDirectory,jobId)!==void 0)return;if(shippedThisRun){let subject=await verifyShippedCommit(projectRoot,previousHead,jobId);await writeShipMarker(projectRoot,jobDirectory,jobId,subject);return}let recovered=await findJobCommit(projectRoot,jobId,previousHead);if(recovered===void 0)throw new Error(`No commit carries ${SHIP_TRAILER_NAME}: ${jobId}`);await writeShipMarker(projectRoot,jobDirectory,jobId,recovered.subject,recovered.head)}async function resumeLoop(jobId,ctx,dependencies={}){if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(jobId))throw new Error(`Invalid job id: ${jobId}`);let jobDirectory=join55(ctx.cwd,CONFIG_DIR_NAME,"runs",jobId),task=JSON.parse(await readFile22(join55(jobDirectory,"task.json"),"utf8")),stateDocument2=JSON.parse(await readFile22(join55(jobDirectory,"state.json"),"utf8"));if(stateDocument2.status==="DONE")return{jobId,status:"DONE"};let graph=await loadNamedGraph(ctx.cwd,task.mode==="autopilot"?"coding-loop.auto":"coding-loop.gated"),baselineSource=JSON.parse(await readFile22(join55(jobDirectory,"baseline.json"),"utf8")),baseline=new Map(Object.entries(baselineSource)),restoredPlanProvided=await planWasProvided(jobDirectory),facts=loopFacts(ctx.cwd,jobDirectory,task,baseline,restoredPlanProvided),engine=await GraphEngine.restore(graph,{projectRoot:ctx.cwd,jobId,createAgentSession:dependencies.createAgentSession,busDependencies:dependencies.busDependencies,now:dependencies.now,accumulatedCostUsd:dependencies.accumulatedCostUsd,limits:task.limits,sleep:dependencies.sleep,retryBaseDelayMs:dependencies.retryBaseDelayMs,resolveFacts:facts.resolve}),eventsPath=join55(jobDirectory,"events.jsonl"),stopState=restoreStopState(stateDocument2,engine.limits.maxRounds);try{let result=await driveUntilPause(engine,ctx.cwd,jobDirectory,task,facts,stopState,dependencies.onStateChange);if(result.terminalStatus!==void 0)return await writeTerminalState(jobDirectory,eventsPath,task,result),{jobId,status:result.terminalStatus,graphState:result.state};for(;result.state.status==="interrupted";){let pending=result.state.pendingHuman;if(pending===void 0)throw new Error("Interrupted graph has no pending human approval");let approved=await ctx.ui.confirm(pending.title,pending.question);if(await appendEvent(eventsPath,{ts:new Date().toISOString(),type:"approval.result",job_id:jobId,round:result.stopState.round,node:pending.nodeId,approved}),await engine.submitHuman(approved),result=await driveUntilPause(engine,ctx.cwd,jobDirectory,task,facts,result.stopState,dependencies.onStateChange),result.terminalStatus!==void 0)return await writeTerminalState(jobDirectory,eventsPath,task,result),{jobId,status:result.terminalStatus,graphState:result.state}}if(result.state.status!=="completed")throw new Error(`Cannot resume graph in ${result.state.status} state`);let release=result.state.values.release;if(!isJsonObject(release)||release.approved!==!0){let blocked={state:result.state,stopState:result.stopState,terminalStatus:"BLOCKED",reason:"graph completed without release approval"};return await writeTerminalState(jobDirectory,eventsPath,task,blocked),await dependencies.onStateChange?.(),{jobId,status:"BLOCKED",graphState:result.state}}try{await finalizeShip(ctx.cwd,jobDirectory,jobId,await startingHeadFor(jobDirectory),result.shippedThisRun===!0)}catch(error){let message=error instanceof Error?error.message:String(error),blocked={state:result.state,stopState:result.stopState,terminalStatus:"BLOCKED",reason:message};return await writeTerminalState(jobDirectory,eventsPath,task,blocked),await dependencies.onStateChange?.(),{jobId,status:"BLOCKED",graphState:result.state}}return await writeTerminalState(jobDirectory,eventsPath,task,{state:result.state,stopState:result.stopState,terminalStatus:"DONE",terminalEmitted:result.terminalEmitted}),await dependencies.onStateChange?.(),{jobId,status:"DONE",graphState:result.state}}finally{engine.dispose()}}async function runLoop2(invocation,ctx,dependencies={}){let plan=invocation.planPath===void 0?void 0:await snapshotPlan(ctx.cwd,invocation.planPath),compilation=compileAcceptanceCriteria(invocation.goal),gates=await detectQualityGates(ctx.cwd);gates.source==="none"&&ctx.ui.notify(`K-\u03C0 quality gates: ${gates.reason}`,"warning");let task={job_id:dependencies.jobId??makeJobId(invocation.goal),mode:invocation.mode,goal:invocation.goal,nongoals:[],acceptance:compilation.acceptance,constraints:invocation.mode==="autopilot"?["Never push","Commit only after deterministic release approval"]:["Never push","Human approval is required before commit"],quality_gates:gates.commands,ac:{quality:compilation.quality},dependency_baseline:await runtimeDependencies(ctx.cwd),...invocation.noNetwork===!0?{research_network:"offline"}:{},...invocation.limits!==void 0?{limits:invocation.limits}:{},...kModeState.plan===void 0?{}:{playbook:kModeState.plan.playbook,playbook_steps:kModeState.plan.steps.map(step=>step.skip===void 0?{node:step.node,text:step.text}:{node:step.node,text:step.text,skip:step.skip})}},job=await createJob(ctx.cwd,task,contextFor(invocation,gates,plan));if(plan!==void 0&&await writePlanSnapshot(job.directory,plan),invocation.mode==="autopilot"&&compilation.quality!=="executable"){let reason=`autopilot requires executable acceptance criteria; received ${compilation.quality}`;return await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"ac.refused",job_id:job.jobId,round:0,node:"ac-compiler",quality:compilation.quality,reason}),await atomicWrite(join55(job.directory,"state.json"),`${JSON.stringify({job_id:task.job_id,mode:task.mode,round:0,maxRounds:task.limits?.maxRounds??DEFAULT_MAX_ROUNDS,stage:"ac-compile",node:"ac-compiler",ac:task.ac,status:"NEEDS_HUMAN",reason,graph_status:"not_started"},null,2)}
1376
- `),await dependencies.onStateChange?.(),{jobId:job.jobId,status:"NEEDS_HUMAN"}}await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"handoff.created",job_id:job.jobId,round:0,node:plan===void 0?"ac-compiler":"plan-check",mode:invocation.mode});let graphName=invocation.mode==="autopilot"?"coding-loop.auto":"coding-loop.gated",graph=await loadNamedGraph(ctx.cwd,graphName),previousHead=await gitHead(ctx.cwd);invocation.mode==="autopilot"&&await createJobBranch(ctx.cwd,job.jobId);let baseline=await worktreeSnapshot(ctx.cwd);await atomicWrite(join55(job.directory,"baseline.json"),`${JSON.stringify(Object.fromEntries(baseline),null,2)}
1373
+ `)}function activeNode(state2){return state2.pendingHuman?.nodeId??state2.active[0]??"done"}function stageFor(node){return node==="quality-green"?"test":node==="plan-check"?"plan":node}function stateDocument(task,state2,stop,terminalStatus,reason,recovery){let node=activeNode(state2);return{job_id:task.job_id,mode:task.mode,round:stop.round,maxRounds:stop.maxRounds,stage:stageFor(node),node,passed:isJsonObject(state2.values.test)?state2.values.test.passed:void 0,bounds:state2.values.bounds,review:state2.values.review,release:state2.values.release,ac:task.ac,status:terminalStatus??(state2.status==="interrupted"?"RUNNING":state2.status==="completed"?"DONE":state2.status==="running"?"RUNNING":state2.status.toUpperCase()),reason,recovery,graph_status:state2.status,superstep:state2.superstep,pending_question:state2.pendingHuman?.question,limits:state2.budget.limits,started_at_ms:state2.budget.startedAtMs,elapsed_ms:state2.budget.elapsedMs,cost_usd:state2.budget.costUsd,graph_round:state2.budget.round,batches:state2.budget.batches,exhausted_limit:state2.terminal?.limit,evidence_fingerprints:[...stop.evidenceFingerprints],output_fingerprints:[...stop.outputFingerprints],failing_ac_sets:[...stop.failingAcSets],retries:stop.retries,retry_delays_ms:[...stop.retryDelaysMs],playbook:task.playbook,todos:playbookTodos(task)}}function playbookTodos(task){if(!(task.playbook_steps===void 0||task.playbook_steps.length===0))return renderTodos(task.playbook_steps)}async function writeState(runDirectory,task,state2,stop,terminalStatus,reason,recovery){await atomicWrite(join55(runDirectory,"state.json"),`${JSON.stringify(stateDocument(task,state2,stop,terminalStatus,reason,recovery),null,2)}
1374
+ `)}function stringArray(value){return Array.isArray(value)?value.filter(item=>typeof item=="string"):[]}function restoreStopState(document,maxRounds){let retries=typeof document.retries=="number"&&Number.isInteger(document.retries)?document.retries:0;return{...createStopState(maxRounds),round:typeof document.round=="number"?document.round:0,evidenceFingerprints:stringArray(document.evidence_fingerprints).map(stopFingerprint),outputFingerprints:stringArray(document.output_fingerprints).map(stopFingerprint),failingAcSets:stringArray(document.failing_ac_sets),retries:Math.max(0,Math.min(MAX_TRANSIENT_RETRIES,retries)),retryDelaysMs:Array.isArray(document.retry_delays_ms)?document.retry_delays_ms.filter(item=>typeof item=="number"&&Number.isFinite(item)):[]}}async function gitHead(projectRoot){try{let{stdout}=await execFile3("git",["rev-parse","--verify","HEAD"],{cwd:projectRoot});return stdout.trim()}catch{return}}function jobBranchName(jobId){return`kpi/${jobId}`}async function currentBranch(projectRoot){try{let{stdout}=await execFile3("git",["branch","--show-current"],{cwd:projectRoot});return stdout.trim()||void 0}catch{return}}async function branchExists(projectRoot,branch){try{return await execFile3("git",["rev-parse","--verify","--quiet",`refs/heads/${branch}`],{cwd:projectRoot}),!0}catch{return!1}}async function ensureJobBranch(projectRoot,jobId){let branch=jobBranchName(jobId);if(await currentBranch(projectRoot)===branch)return branch;let args=await branchExists(projectRoot,branch)?["switch",branch]:["switch","-c",branch];return await execFile3("git",args,{cwd:projectRoot}),branch}async function hasRemote(projectRoot,remote){try{return await execFile3("git",["remote","get-url",remote],{cwd:projectRoot}),!0}catch{return!1}}async function pushedHead(projectRoot,branch){try{let{stdout}=await execFile3("git",["rev-parse","--verify","--quiet",`refs/remotes/origin/${branch}`],{cwd:projectRoot});return stdout.trim()||void 0}catch{return}}var ShipDeliveryError=class extends Error{constructor(message,options){super(message,options),this.name="ShipDeliveryError"}},ShipIntegrityError=class extends Error{constructor(message){super(message),this.name="ShipIntegrityError"}};function describeError(error){if(error instanceof Error)return error.message;if(typeof error=="string")return error;if(error===void 0)return"an undefined value was thrown";try{return JSON.stringify(error)??String(error)}catch{return String(error)}}function recoveryReason(kind,message,jobId){return`${message}. ${kind==="provider"?"Select a healthy model or resolve that provider account":"Push the branch or open the pull request as named"}, then resume with /kpi ${jobId}`}function shipFailure(error,jobId){let message=describeError(error);return error instanceof ShipDeliveryError?{terminalStatus:"NEEDS_HUMAN",reason:recoveryReason("delivery",message,jobId),recovery:"delivery"}:error instanceof ShipIntegrityError?{terminalStatus:"BLOCKED",reason:message}:{terminalStatus:"BLOCKED",reason:`ship finalization failed unexpectedly (not an operator step): ${message}`}}async function verifyShipDelivery(projectRoot,jobId,head,readPullRequest){if(!await hasRemote(projectRoot,"origin"))return;let branch=jobBranchName(jobId),checkedOut=await currentBranch(projectRoot);if(checkedOut!==branch)throw new ShipDeliveryError(`Ship commit is on ${checkedOut??"a detached HEAD"}, not the job branch ${branch}`);let remoteHead=await pushedHead(projectRoot,branch);if(remoteHead===void 0)throw new ShipDeliveryError(`Job branch ${branch} was not pushed to origin`);if(remoteHead!==head&&!await isAncestor(projectRoot,head,remoteHead))throw new ShipDeliveryError(`origin/${branch} is at ${remoteHead.slice(0,8)}, which does not carry the ship commit`);let pullRequest;try{pullRequest=await(readPullRequest??readPullRequestWithGh)(projectRoot,branch)}catch(error){throw error instanceof PullRequestLookupError?new ShipDeliveryError(error.message,{cause:error}):error}if(pullRequest===void 0)throw new ShipDeliveryError(`No pull request is open for ${branch}; open one with gh pr create --head ${branch} --fill`);if(pullRequest.state!=="OPEN"&&pullRequest.state!=="MERGED")throw new ShipDeliveryError(`The pull request for ${branch} is ${pullRequest.state}: ${pullRequest.url}`);return{branch,prUrl:pullRequest.url}}var SNAPSHOT_EXCLUDED_TREES=["node_modules",".git",CONFIG_DIR_NAME];async function worktreeSnapshot(projectRoot){let{stdout}=await execFile3("git",["status","--porcelain=v1","-z","--untracked-files=all","--ignored=matching","--",".",...SNAPSHOT_EXCLUDED_TREES.map(tree=>`:(exclude)${tree}`)],{cwd:projectRoot}),records=stdout.split("\0"),paths=new Set;for(let index3=0;index3<records.length;index3+=1){let record=records[index3];if(record.length<4)continue;let status=record.slice(0,2);if(paths.add(record.slice(3)),/[RC]/u.test(status)){let source2=records[index3+1];source2!==void 0&&source2.length>0&&(paths.add(source2),index3+=1)}}let runsPrefix=`${CONFIG_DIR_NAME}/runs`,snapshot2=new Map;for(let path14 of paths)if(!(path14===runsPrefix||path14.startsWith(`${runsPrefix}/`)))try{let content=await readFile22(join55(projectRoot,path14));snapshot2.set(path14,createHash7("sha256").update(content).digest("hex"))}catch(error){let code=error.code;if(code==="ENOENT"){snapshot2.set(path14,"<absent>");continue}if(code!=="EISDIR")throw error;let entries=(await readdir6(join55(projectRoot,path14))).sort();snapshot2.set(path14,`<dir>${createHash7("sha256").update(entries.join("\0")).digest("hex")}`)}return snapshot2}function changedPaths(before,after){return[...new Set([...before.keys(),...after.keys()])].filter(path14=>before.get(path14)!==after.get(path14))}async function evidenceFingerprint(runDirectory){let content=await readFile22(join55(runDirectory,"evidence.json"));try{return canonicalFingerprint(JSON.parse(content.toString("utf8")))}catch{return`sha256:${createHash7("sha256").update(content).digest("hex")}`}}async function failingAcIds(runDirectory){let evidence;try{evidence=JSON.parse(await readFile22(join55(runDirectory,"evidence.json"),"utf8"))}catch{return[]}return!isJsonObject(evidence)||!Array.isArray(evidence.ac_results)?[]:evidence.ac_results.flatMap(result=>isJsonObject(result)&&typeof result.id=="string"&&result.passed!==!0?[result.id]:[])}function reviewFingerprint(state2){let review=state2.values.review;if(isJsonObject(review))return typeof review.output_fingerprint=="string"?review.output_fingerprint:void 0}function reviewApproved(state2){let review=state2.values.review;return isJsonObject(review)&&review.approved===!0}function evidencePasses(task,evidence){if(!isJsonObject(evidence))return!1;let commands=evidence.commands,acResults=evidence.ac_results;if(!Array.isArray(commands)||!Array.isArray(acResults))return!1;let latestCommandExit=new Map;for(let command of commands)isJsonObject(command)&&typeof command.cmd=="string"&&typeof command.exit=="number"&&latestCommandExit.set(command.cmd,command.exit);if(latestCommandExit.size===0||[...latestCommandExit.values()].some(exit=>exit!==0))return!1;let passedIds=new Set(acResults.flatMap(result=>isJsonObject(result)&&typeof result.id=="string"&&result.passed===!0?[result.id]:[]));return task.acceptance.filter(criterion=>criterion.required).every(criterion=>passedIds.has(criterion.id))}async function planWasProvided(jobDirectory){try{return(await readdir6(join55(jobDirectory,"plan"))).length>0}catch{return!1}}var PullRequestLookupError=class extends Error{constructor(message,options){super(message,options),this.name="PullRequestLookupError"}};async function readPullRequestWithGh(projectRoot,branch){let stdout;try{({stdout}=await execFile3("gh",["pr","view",branch,"--json","url,state"],{cwd:projectRoot}))}catch(error){let detail=error;if(/no pull requests found/iu.test(detail.stderr??""))return;if(detail.code==="ENOENT")throw new PullRequestLookupError(`No pull request could be verified for ${branch}: gh is not installed`);let firstLine=(detail.stderr??detail.message).split(/\r?\n/u).map(line=>line.trim()).find(line=>line.length>0)??"gh gave no reason",shown=firstLine.length>160?`${firstLine.slice(0,159)}\u2026`:firstLine;throw new PullRequestLookupError(`No pull request could be verified for ${branch}: gh pr view failed (${shown})`,{cause:error})}let parsed=JSON.parse(stdout);if(typeof parsed.url!="string"||typeof parsed.state!="string")throw new PullRequestLookupError(`gh pr view ${branch} returned no url and state`);return{url:parsed.url,state:parsed.state}}function shipMarkerPath(jobDirectory){return join55(jobDirectory,"ship.json")}var SHIP_TRAILER_NAME="KPI-Job",COMMIT_SHA_PATTERN=/^[0-9a-f]{40}$/u;function parseShipMarker(value){if(!isJsonObject(value))return;let{job_id:jobId,head,subject,at:at2}=value;if(typeof jobId!="string"||jobId.length===0||typeof head!="string"||!COMMIT_SHA_PATTERN.test(head)||typeof subject!="string"||subject.length===0||typeof at2!="string"||Number.isNaN(Date.parse(at2)))return;let{branch,pr_url:prUrl}=value;if(branch!==void 0&&(typeof branch!="string"||branch.length===0)||prUrl!==void 0&&(typeof prUrl!="string"||prUrl.length===0))return;let known=4+(branch===void 0?0:1)+(prUrl===void 0?0:1);if(Object.keys(value).length===known)return{job_id:jobId,head,subject,at:at2,...branch===void 0?{}:{branch},...prUrl===void 0?{}:{pr_url:prUrl}}}async function commitsSince(projectRoot,previousHead){let range2=previousHead===void 0?"HEAD":`${previousHead}..HEAD`,stdout;try{({stdout}=await execFile3("git",["log",range2,"--format=%H%x1f%s%x1f%B%x1e"],{cwd:projectRoot}))}catch{return[]}return stdout.split("").map(record=>record.replace(/^\n/u,"")).filter(record=>record.length>0).map(record=>{let[head,subject,body]=record.split("");return{head:head??"",subject:subject??"",body:body??""}})}function carriesJobTrailer(body,jobId){return body.split(/\r?\n/u).some(line=>line.trimEnd()===`${SHIP_TRAILER_NAME}: ${jobId}`)}async function isAncestor(projectRoot,commit,of){try{return await execFile3("git",["merge-base","--is-ancestor",commit,of],{cwd:projectRoot}),!0}catch{return!1}}function isAncestorOfHead(projectRoot,head){return isAncestor(projectRoot,head,"HEAD")}async function findJobCommit(projectRoot,jobId,previousHead){let marked=(await commitsSince(projectRoot,previousHead)).filter(commit2=>carriesJobTrailer(commit2.body,jobId));if(marked.length===0)return;if(marked.length>1)throw new ShipIntegrityError(`Ambiguous ship commits for ${jobId}: ${marked.map(commit2=>commit2.head.slice(0,8)).join(", ")}`);let[commit]=marked;if(!CONVENTIONAL_COMMIT_PATTERN.test(commit.subject))throw new ShipIntegrityError(`Ship commit is not Conventional Commits: ${commit.subject}`);if(!await isAncestorOfHead(projectRoot,commit.head))throw new ShipIntegrityError(`Ship commit ${commit.head.slice(0,8)} is not an ancestor of HEAD`);return{head:commit.head,subject:commit.subject}}async function readShipMarker(projectRoot,jobDirectory,jobId){let parsed;try{parsed=parseShipMarker(JSON.parse(await readFile22(shipMarkerPath(jobDirectory),"utf8")))}catch{return}if(parsed===void 0||parsed.job_id!==jobId)return;let claimed=(await commitsSince(projectRoot,void 0)).find(commit=>commit.head===parsed.head);if(!(claimed===void 0||claimed.subject!==parsed.subject||!carriesJobTrailer(claimed.body,jobId)||!await isAncestorOfHead(projectRoot,parsed.head)))return parsed}async function startingHeadFor(jobDirectory){try{return(await readFile22(join55(jobDirectory,"previous-head.txt"),"utf8")).trim()||void 0}catch{return}}async function alreadyShipped(projectRoot,jobDirectory,jobId){if(await readShipMarker(projectRoot,jobDirectory,jobId)!==void 0)return!0;try{return await findJobCommit(projectRoot,jobId,await startingHeadFor(jobDirectory))!==void 0}catch{return!1}}async function writeShipMarker(projectRoot,jobDirectory,jobId,subject,head,delivery){let recorded=head??await gitHead(projectRoot);if(recorded===void 0)return;let marker={job_id:jobId,head:recorded,subject,at:new Date().toISOString(),...delivery===void 0?{}:{branch:delivery.branch,pr_url:delivery.prUrl}};await atomicWrite(shipMarkerPath(jobDirectory),`${JSON.stringify(marker,null,2)}
1375
+ `)}function loopFacts(projectRoot,jobDirectory,task,baseline,planProvided){let boundsReason;return{boundsReason:()=>boundsReason,resolve:async()=>{let evidence;try{evidence=JSON.parse(await readFile22(join55(jobDirectory,"evidence.json"),"utf8"))}catch{evidence=void 0}let testPassed=evidence!==void 0&&evidencePasses(task,evidence),evidenceHead=isJsonObject(evidence)&&typeof evidence.head=="string"?evidence.head:void 0,fresh=evidenceHead!==void 0&&evidenceHead===await gitHead(projectRoot);boundsReason=void 0;let current=await worktreeSnapshot(projectRoot),violations=changedPaths(baseline,current).filter(path14=>!isWriteAllowed(projectRoot,path14,writeAllowForTask(task)));if(violations.length>0)boundsReason=`write outside write_allow: ${violations.join(", ")}`;else try{let changes=await observedChangesFromSnapshots(projectRoot,baseline,current,async path14=>{try{let{stdout}=await execFile3("git",["show",`HEAD:${path14}`],{cwd:projectRoot,encoding:"utf8",maxBuffer:2097152});return stdout}catch{return}});await assertMinimalistBounds(projectRoot,jobDirectory,task,changes)}catch(error){boundsReason=error instanceof Error?error.message:String(error)}return{"plan.provided":planProvided,"test.passed":testPassed,"bounds.held":boundsReason===void 0,"fingerprints.fresh":fresh,"ship.shipped":await alreadyShipped(projectRoot,jobDirectory,task.job_id)}}}}async function driveUntilPause(engine,projectRoot,jobDirectory,task,facts,stopState,onStateChange){let state2=engine.state,currentStopState=stopState,shippedThisRun=!1;for(;state2.status==="running";){if(state2.active.some(node=>node==="specify"||node==="plan"||node==="plan-check"))try{await assertResearchFresh(jobDirectory,task)}catch{try{let settings2=await readKpiSettings(projectRoot),{endpoints,timeoutMs}=resolveResearchEndpoints(settings2.researchEndpoints);await conductResearch(projectRoot,jobDirectory,task,{keys:await resolveResearchKeys(),mode:settings2.research,endpoints,timeoutMs,operatorNoNetwork:task.research_network==="offline",eventsPath:join55(jobDirectory,"events.jsonl"),round:currentStopState.round,node:state2.active[0]})}catch(error){if(!(error instanceof ResearchShortfallError))throw error;return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"NEEDS_HUMAN",reason:error.message}}}if(state2.active.includes("implement"))try{await assertResearchFresh(jobDirectory,task);let contract=await readTaskForJob(projectRoot,task.job_id).catch(()=>task);if(stackRequiredFor(contract)){let{module}=await freezeCurrentSlice(projectRoot,jobDirectory,contract);await scaffoldModule(projectRoot,module),await assertScaffoldedBeforeBehavior(projectRoot,module)}}catch(error){return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"UNSAFE",reason:error instanceof Error?error.message:String(error)}}let completedNodes=[...state2.active];if(completedNodes.includes("ship")){shippedThisRun=!0;try{await ensureJobBranch(projectRoot,task.job_id)}catch(error){return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"BLOCKED",reason:`could not switch to the job branch ${jobBranchName(task.job_id)}: ${error instanceof Error?error.message:String(error)}`}}}let prePlan=state2.active.includes("plan");try{state2=await engine.runSuperstep()}catch(error){if(error instanceof GraphNodeProviderError)return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"NEEDS_HUMAN",reason:recoveryReason("provider",error.message,task.job_id),recovery:"provider"};let message=error instanceof Error?error.message:String(error);if(prePlan&&(/stack\.json|stack\.schema|assertDuneStack|Dune|Layer folder|Module folder|Horizontal delivery|layer sweep|shared module/iu.test(message)||/failed response validation/iu.test(message))){let validation=/^agent node plan failed response validation after (\d+) attempts?: (.+)$/su.exec(message),reason=validation!==null&&/not valid JSON|assistant response text is unavailable|response must be a JSON object/iu.test(validation[2])?`stack.json is missing: plan response was not valid stack.json JSON after ${validation[1]} attempts (${validation[2]})`:message.replace(/^agent node plan failed response validation after \d+ attempts: /u,"");return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"UNSAFE",reason}}throw error}if(state2.status==="exhausted")return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"EXHAUSTED",reason:state2.terminal?.reason??"graph exhausted a configured cap",terminalEmitted:!0};if(state2.status==="terminated"){let terminal=state2.terminal;return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:terminal?.status??"BLOCKED",reason:terminal?.status==="UNSAFE"?facts.boundsReason()??terminal.reason:terminal?.reason??"the graph routed to a terminal",terminalEmitted:!0}}if(completedNodes.includes("review")){let outputFingerprint=reviewFingerprint(state2);if(outputFingerprint===void 0)return{state:state2,stopState:currentStopState,shippedThisRun,terminalStatus:"BLOCKED",reason:"review did not produce an output fingerprint"};if(currentStopState=transitionStopState(currentStopState,{type:"verifier",passed:reviewApproved(state2),evidenceFingerprint:await evidenceFingerprint(jobDirectory),outputFingerprint,failingAcIds:await failingAcIds(jobDirectory)}),currentStopState.status==="NO_PROGRESS"||currentStopState.status==="EXHAUSTED")return{state:currentStopState.status==="EXHAUSTED"?{...state2,terminal:{status:"EXHAUSTED",limit:"maxRounds",reason:"maximum verifier rounds exhausted",round:currentStopState.round,superstep:state2.superstep,nodes:[...state2.active]}}:state2,stopState:currentStopState,shippedThisRun,terminalStatus:currentStopState.status,reason:currentStopState.status==="NO_PROGRESS"?"the same acceptance criteria failed in two rounds":"maximum verifier rounds exhausted"}}await writeState(jobDirectory,task,state2,currentStopState),await onStateChange?.()}return{state:state2,stopState:currentStopState,shippedThisRun}}async function writeTerminalState(jobDirectory,eventsPath,task,result){let status=result.terminalStatus;status!==void 0&&(result.terminalEmitted!==!0&&await appendEvent(eventsPath,{ts:new Date().toISOString(),type:"loop.terminal",job_id:task.job_id,round:result.stopState.round,node:activeNode(result.state),status,reason:result.reason}),await writeState(jobDirectory,task,result.state,result.stopState,status,result.reason,result.recovery))}async function verifyShippedCommit(projectRoot,previousHead,jobId){let head=await gitHead(projectRoot);if(head===void 0||head===previousHead)throw new ShipIntegrityError("Ship node did not create a commit");if(previousHead!==void 0){let{stdout:count}=await execFile3("git",["rev-list","--count",`${previousHead}..${head}`],{cwd:projectRoot});if(count.trim()!=="1")throw new ShipIntegrityError(`Ship node created ${count.trim()} commits instead of one`)}let{stdout}=await execFile3("git",["log","-1","--pretty=%s"],{cwd:projectRoot}),subject=stdout.trim();if(!CONVENTIONAL_COMMIT_PATTERN.test(subject))throw new ShipIntegrityError(`Ship commit is not Conventional Commits: ${subject}`);if(jobId!==void 0){let marked=await findJobCommit(projectRoot,jobId,previousHead);if(marked===void 0)throw new ShipIntegrityError(`Ship commit does not carry ${SHIP_TRAILER_NAME}: ${jobId}`);if(marked.head!==head)throw new ShipIntegrityError(`Ship commit ${marked.head.slice(0,8)} is not HEAD`)}return subject}async function finalizeShip(projectRoot,jobDirectory,jobId,previousHead,shippedThisRun,readPullRequest){if(await readShipMarker(projectRoot,jobDirectory,jobId)!==void 0)return;if(shippedThisRun){let subject=await verifyShippedCommit(projectRoot,previousHead,jobId),head=await gitHead(projectRoot),delivery2=head===void 0?void 0:await verifyShipDelivery(projectRoot,jobId,head,readPullRequest);await writeShipMarker(projectRoot,jobDirectory,jobId,subject,head,delivery2);return}let recovered=await findJobCommit(projectRoot,jobId,previousHead);if(recovered===void 0)throw new Error(`No commit carries ${SHIP_TRAILER_NAME}: ${jobId}`);let delivery=await verifyShipDelivery(projectRoot,jobId,recovered.head,readPullRequest);await writeShipMarker(projectRoot,jobDirectory,jobId,recovered.subject,recovered.head,delivery)}async function resumeLoop(jobId,ctx,dependencies={}){if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(jobId))throw new Error(`Invalid job id: ${jobId}`);let jobDirectory=join55(ctx.cwd,CONFIG_DIR_NAME,"runs",jobId),task=JSON.parse(await readFile22(join55(jobDirectory,"task.json"),"utf8")),stateDocument2=JSON.parse(await readFile22(join55(jobDirectory,"state.json"),"utf8"));if(stateDocument2.status==="DONE")return{jobId,status:"DONE"};let graph=await loadNamedGraph(ctx.cwd,task.mode==="autopilot"?"coding-loop.auto":"coding-loop.gated"),baselineSource=JSON.parse(await readFile22(join55(jobDirectory,"baseline.json"),"utf8")),baseline=new Map(Object.entries(baselineSource)),restoredPlanProvided=await planWasProvided(jobDirectory),facts=loopFacts(ctx.cwd,jobDirectory,task,baseline,restoredPlanProvided),engine=await GraphEngine.restore(graph,{projectRoot:ctx.cwd,jobId,createAgentSession:dependencies.createAgentSession,busDependencies:dependencies.busDependencies,now:dependencies.now,accumulatedCostUsd:dependencies.accumulatedCostUsd,limits:task.limits,sleep:dependencies.sleep,retryBaseDelayMs:dependencies.retryBaseDelayMs,resolveFacts:facts.resolve,model:ctx.model,thinkingLevel:ctx.thinkingLevel}),eventsPath=join55(jobDirectory,"events.jsonl"),stopState=restoreStopState(stateDocument2,engine.limits.maxRounds);try{let result=await driveUntilPause(engine,ctx.cwd,jobDirectory,task,facts,stopState,dependencies.onStateChange);if(result.terminalStatus!==void 0)return await writeTerminalState(jobDirectory,eventsPath,task,result),{jobId,status:result.terminalStatus,reason:result.reason,recovery:result.recovery,graphState:result.state};for(;result.state.status==="interrupted";){let pending=result.state.pendingHuman;if(pending===void 0)throw new Error("Interrupted graph has no pending human approval");let approved=await ctx.ui.confirm(pending.title,pending.question);if(await appendEvent(eventsPath,{ts:new Date().toISOString(),type:"approval.result",job_id:jobId,round:result.stopState.round,node:pending.nodeId,approved}),await engine.submitHuman(approved),await writeState(jobDirectory,task,engine.state,result.stopState),result=await driveUntilPause(engine,ctx.cwd,jobDirectory,task,facts,result.stopState,dependencies.onStateChange),result.terminalStatus!==void 0)return await writeTerminalState(jobDirectory,eventsPath,task,result),{jobId,status:result.terminalStatus,reason:result.reason,recovery:result.recovery,graphState:result.state}}if(result.state.status!=="completed")throw new Error(`Cannot resume graph in ${result.state.status} state`);let release=result.state.values.release;if(!isJsonObject(release)||release.approved!==!0){let blocked={state:result.state,stopState:result.stopState,terminalStatus:"BLOCKED",reason:"graph completed without release approval"};return await writeTerminalState(jobDirectory,eventsPath,task,blocked),await dependencies.onStateChange?.(),{jobId,status:"BLOCKED",graphState:result.state}}try{await finalizeShip(ctx.cwd,jobDirectory,jobId,await startingHeadFor(jobDirectory),result.shippedThisRun===!0,dependencies.readPullRequest)}catch(error){let{terminalStatus,reason,recovery}=shipFailure(error,jobId),stopped={state:result.state,stopState:result.stopState,terminalStatus,reason,recovery};return await writeTerminalState(jobDirectory,eventsPath,task,stopped),await dependencies.onStateChange?.(),{jobId,status:terminalStatus,reason,recovery,graphState:result.state}}return await writeTerminalState(jobDirectory,eventsPath,task,{state:result.state,stopState:result.stopState,terminalStatus:"DONE",terminalEmitted:result.terminalEmitted}),await dependencies.onStateChange?.(),{jobId,status:"DONE",graphState:result.state}}finally{engine.dispose()}}async function runLoop2(invocation,ctx,dependencies={}){let plan=invocation.planPath===void 0?void 0:await snapshotPlan(ctx.cwd,invocation.planPath),compilation=compileAcceptanceCriteria(invocation.goal),gates=await detectQualityGates(ctx.cwd);gates.source==="none"&&ctx.ui.notify(`K-\u03C0 quality gates: ${gates.reason}`,"warning");let jobId=dependencies.jobId??makeJobId(invocation.goal),task={job_id:jobId,mode:invocation.mode,goal:invocation.goal,nongoals:[],acceptance:compilation.acceptance,constraints:invocation.mode==="autopilot"?["Commit only after deterministic release approval",`Push only the job branch kpi/${jobId} to origin after release approval, then open a pull request; never push another branch, force-push, push tags, delete a branch, or merge`]:["Human approval is required before commit",`Push only the job branch kpi/${jobId} to origin after approval, then open a pull request; never push another branch, force-push, push tags, delete a branch, or merge`],quality_gates:gates.commands,ac:{quality:compilation.quality},dependency_baseline:await runtimeDependencies(ctx.cwd),...invocation.noNetwork===!0?{research_network:"offline"}:{},...invocation.limits!==void 0?{limits:invocation.limits}:{},...kModeState.plan===void 0?{}:{playbook:kModeState.plan.playbook,playbook_steps:kModeState.plan.steps.map(step=>step.skip===void 0?{node:step.node,text:step.text}:{node:step.node,text:step.text,skip:step.skip})}},job=await createJob(ctx.cwd,task,contextFor(invocation,gates,plan));if(plan!==void 0&&await writePlanSnapshot(job.directory,plan),invocation.mode==="autopilot"&&compilation.quality!=="executable"){let reason=`autopilot requires executable acceptance criteria; received ${compilation.quality}`;return await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"ac.refused",job_id:job.jobId,round:0,node:"ac-compiler",quality:compilation.quality,reason}),await atomicWrite(join55(job.directory,"state.json"),`${JSON.stringify({job_id:task.job_id,mode:task.mode,round:0,maxRounds:task.limits?.maxRounds??DEFAULT_MAX_ROUNDS,stage:"ac-compile",node:"ac-compiler",ac:task.ac,status:"NEEDS_HUMAN",reason,graph_status:"not_started"},null,2)}
1376
+ `),await dependencies.onStateChange?.(),{jobId:job.jobId,status:"NEEDS_HUMAN",reason}}await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"handoff.created",job_id:job.jobId,round:0,node:plan===void 0?"ac-compiler":"plan-check",mode:invocation.mode});let graphName=invocation.mode==="autopilot"?"coding-loop.auto":"coding-loop.gated",graph=await loadNamedGraph(ctx.cwd,graphName),previousHead=await gitHead(ctx.cwd),baseline=await worktreeSnapshot(ctx.cwd);await atomicWrite(join55(job.directory,"baseline.json"),`${JSON.stringify(Object.fromEntries(baseline),null,2)}
1377
1377
  `),await atomicWrite(join55(job.directory,"previous-head.txt"),`${previousHead??""}
1378
- `);let facts=loopFacts(ctx.cwd,job.directory,task,baseline,plan!==void 0),engine=new GraphEngine(graph,{projectRoot:ctx.cwd,jobId:job.jobId,createAgentSession:dependencies.createAgentSession,busDependencies:dependencies.busDependencies,now:dependencies.now,accumulatedCostUsd:dependencies.accumulatedCostUsd,limits:task.limits,sleep:dependencies.sleep,retryBaseDelayMs:dependencies.retryBaseDelayMs,resolveFacts:facts.resolve,uiContext:ctx.ui});try{let stopState=createStopState(engine.limits.maxRounds);await writeState(job.directory,task,engine.state,stopState),await dependencies.onStateChange?.();let result=await driveUntilPause(engine,ctx.cwd,job.directory,task,facts,stopState,dependencies.onStateChange);if(result.terminalStatus!==void 0)return await writeTerminalState(job.directory,job.eventsPath,task,result),await dependencies.onStateChange?.(),{jobId:job.jobId,status:result.terminalStatus,graphState:result.state};for(;result.state.status==="interrupted";){let pending=result.state.pendingHuman;if(pending===void 0)throw new Error("Interrupted graph has no pending human approval");let approved=await ctx.ui.confirm(pending.title,pending.question);await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"approval.result",job_id:job.jobId,round:result.stopState.round,node:pending.nodeId,approved});let resumed=await engine.submitHuman(approved);if(stopState=result.stopState,result=await driveUntilPause(engine,ctx.cwd,job.directory,task,facts,stopState,dependencies.onStateChange),result.terminalStatus!==void 0)return await writeTerminalState(job.directory,job.eventsPath,task,result),await dependencies.onStateChange?.(),{jobId:job.jobId,status:result.terminalStatus,graphState:result.state};if(resumed.status==="completed")break}let state2=result.state,release=state2.values.release;if(state2.status!=="completed"||!isJsonObject(release)||release.approved!==!0){let blocked={state:state2,stopState:result.stopState,terminalStatus:"BLOCKED",reason:"graph completed without release approval"};return await writeTerminalState(job.directory,job.eventsPath,task,blocked),{jobId:job.jobId,status:"BLOCKED",graphState:state2}}try{await finalizeShip(ctx.cwd,job.directory,job.jobId,previousHead,result.shippedThisRun===!0)}catch(error){let message=error instanceof Error?error.message:String(error),blocked={state:state2,stopState:result.stopState,terminalStatus:"BLOCKED",reason:message};throw await writeTerminalState(job.directory,job.eventsPath,task,blocked),error}return await writeTerminalState(job.directory,job.eventsPath,task,{state:state2,stopState:result.stopState,terminalStatus:"DONE",terminalEmitted:result.terminalEmitted}),await dependencies.onStateChange?.(),{jobId:job.jobId,status:"DONE",graphState:state2}}finally{engine.dispose()}}import{basename as basename18}from"node:path";var DEFAULT_LEFT_SEGMENT_ORDER=["brand","model","thinking","path","git","context_pct","cost"],DEFAULT_RIGHT_SEGMENT_ORDER=["request"],DEFAULT_SEGMENT_ORDER=[...DEFAULT_LEFT_SEGMENT_ORDER,...DEFAULT_RIGHT_SEGMENT_ORDER],SEGMENT_SEPARATOR=" > ",COMPACT_LEFT_SEGMENT_ORDER=["brand","model","path","cost"],FULL_LEFT_SEGMENT_ORDER=["brand","model","thinking","path","git","context_pct","cost","usage","kpi_job"];function leftSegmentsForPreset(preset){return preset==="compact"?COMPACT_LEFT_SEGMENT_ORDER:preset==="full"?FULL_LEFT_SEGMENT_ORDER:DEFAULT_LEFT_SEGMENT_ORDER}function formatModel(name){return`\u2B21 ${name??"no model"}`}function formatThinking(level){return`\u25CF ${level??"off"}`}function formatPath(cwd){return`\u{1F4C1} ${basename18(cwd)||cwd}`}function formatGit(branch){return branch?`\u2387 ${branch}`:void 0}function contextColor(percent){return percent<50?"success":percent<=70?"warning":percent<=90?"accent":"error"}function formatContext(percent,contextWindow){return percent==null||contextWindow==null?"\u25A6 \u2014":`\u25A6 ${percent.toFixed(0)}%/${formatCount(contextWindow)}`}function formatCost(cost,slotKind="api_key"){return slotKind==="oauth"?"(sub)":slotKind==="local"?"(local) $0":`$${cost.toFixed(2)}`}function formatUsage(remainingPercent,slotKind){if(slotKind!=="local"&&!(remainingPercent===void 0||!Number.isFinite(remainingPercent)))return`${Math.round(remainingPercent)}%`}function formatKpiJob(fields){let parts=["K-\u03C0","LOOP",fields.mode,`r${fields.round}/${fields.maxRounds}`,`STAGE ${fields.stage}`,`GATE ${fields.gate}`];return fields.ac!==void 0&&fields.ac.length>0&&parts.push(`AC ${fields.ac}`),fields.route!==void 0&&fields.route.length>0&&parts.push(`ROUTE ${fields.route}`),parts.join(" ")}function formatStatusRow(statuses,preset){let parts=Array.from(statuses.entries()).filter(([key])=>preset==="full"||key!=="accounts").sort(([left],[right])=>left.localeCompare(right)).map(([,text])=>text.replace(/\s+/gu," ").trim()).filter(text=>text.length>0);return parts.length===0?void 0:parts.join(" ")}function formatRequest(request2){if(request2)return request2.length<=80?request2:`${request2.slice(0,79)}\u2026`}function formatCount(value){return value>=1e6?`${Number((value/1e6).toFixed(1))}M`:value>=1e3?`${Number((value/1e3).toFixed(1))}k`:String(value)}function assembleFooter(input){let preset=input.preset??"default",slotKind=input.slotKind,segments={brand:input.brand,model:formatModel(input.model),thinking:formatThinking(input.thinking),path:formatPath(input.path),cost:formatCost(input.cost,slotKind)},git=formatGit(input.git??null);git!==void 0&&(segments.git=git),segments.context_pct=formatContext(input.contextPercent,input.contextWindow);let usage=formatUsage(input.remainingPercent,slotKind);usage!==void 0&&(segments.usage=usage),input.kpiJob!==void 0&&(segments.kpi_job=formatKpiJob(input.kpiJob));let request2=formatRequest(input.request);request2!==void 0&&(segments.request=request2);let line=leftSegmentsForPreset(preset).map(id=>segments[id]).filter(text=>typeof text=="string"&&text.length>0).join(SEGMENT_SEPARATOR);request2!==void 0&&(line=`${line} \u2500\u2500\u2500\u2500 ${request2}`);let jobLine;return preset!=="full"&&input.kpiJob!==void 0&&(jobLine=formatKpiJob(input.kpiJob)),input.width!==void 0&&input.width>0&&line.length>input.width&&(line=`${line.slice(0,Math.max(0,input.width-1))}\u2026`),{line,...jobLine===void 0?{}:{jobLine},segments}}function nestedValue(state2,parent,child){let value=state2[parent];if(value!==null&&typeof value=="object"&&!Array.isArray(value))return value[child]}function stringValue(value,fallback){return typeof value=="string"?value:fallback}function numberValue(value,fallback){return typeof value=="number"&&Number.isFinite(value)?value:fallback}function booleanValue(value){return typeof value=="boolean"?value:void 0}function isPausedHuman(state2){if(state2.graph_status==="interrupted")return!0;let question=state2.pending_question;if(typeof question=="string"&&question.trim().length>0)return!0;let pending=state2.pending_human??state2.pendingHuman;return pending!==null&&typeof pending=="object"&&!Array.isArray(pending)}function displayStop(state2){return normalizeStop(stringValue(state2.status??state2.stop,"RUNNING"))}async function fileLitMap(directory){let entries=await Promise.all(RUN_FILE_NAMES.map(async name=>{try{let metadata=await stat10(join56(directory,name));return[name,metadata.isFile()&&metadata.size>0]}catch(error){if(error.code==="ENOENT")return[name,!1];throw error}}));return Object.fromEntries(entries)}async function busLogLit(directory){try{let metadata=await stat10(join56(directory,"bus.jsonl"));return metadata.isFile()&&metadata.size>0}catch(error){if(error.code==="ENOENT")return!1;throw error}}async function jobPlaybookFreeze(runDirectory,state2){let statePlaybook=typeof state2.playbook=="string"&&state2.playbook.trim().length>0?state2.playbook:void 0,stateTodos=Array.isArray(state2.todos)?state2.todos.filter(entry=>typeof entry=="string"):void 0;if(statePlaybook!==void 0)return{playbook:statePlaybook,todos:stateTodos??[]};try{let task=JSON.parse(await readFile23(join56(runDirectory,"task.json"),"utf8"));if(typeof task.playbook!="string"||task.playbook.trim().length===0)return;let todos=stateTodos??(Array.isArray(task.playbook_steps)?task.playbook_steps.filter(step=>typeof step?.node=="string"&&step.node.trim().length>0&&typeof step?.text=="string"&&step.text.trim().length>0).map(step=>typeof step.skip=="string"&&step.skip.trim().length>0?`${step.node}: ${step.text} \u2014 skip: ${step.skip}`:`${step.node}: ${step.text}`):[]);return{playbook:task.playbook,todos}}catch{return}}async function contextPackLamps(cwd,runDirectory){let roots=[join56(cwd,CONFIG_DIR_NAME,"context"),join56(runDirectory,"context"),runDirectory],names2=["product.md","structure.md","tech.md"],lit={product:!1,structure:!1,tech:!1};for(let root of roots)for(let name of names2){let key=name.replace(/\.md$/,"");if(!lit[key])try{let metadata=await stat10(join56(root,name));metadata.isFile()&&metadata.size>0&&(lit[key]=!0)}catch{}}return lit}async function loadResearchCell(runDirectory){try{let raw=JSON.parse(await readFile23(join56(runDirectory,"research.json"),"utf8"));return researchCellFromDocument(raw)}catch{return}}function fingerprintFromState(state2){let direct=state2.output_fingerprint??state2.fingerprint;if(typeof direct=="string")return direct;let fingerprints=state2.output_fingerprints;if(Array.isArray(fingerprints)&&fingerprints.length>0){let last=fingerprints.at(-1);return typeof last=="string"?last:void 0}}function verifierFor2(passed,fileLit){return passed===!0?"pass":passed===!1&&fileLit["verdict.json"]===!0?"fail":"pending"}async function buildBoardModel(cwd,options={}){let job=await readLiveJob(cwd);if(job===void 0)return;let state2=job.state,paused=isPausedHuman(state2),route=getFooterRouteSnapshot(),usage=formatUsage(route.remainingPercent,route.slotKind),freeze=await jobPlaybookFreeze(job.directory,state2),agents=options.agents??liveWorkerCount(),busLit=await busLogLit(job.directory),fileLit=await fileLitMap(job.directory),passed=booleanValue(typeof state2.passed=="boolean"?state2.passed:nestedValue(state2,"test","passed"));return{jobId:job.jobId,mode:stringValue(state2.mode,"gated"),round:numberValue(state2.round,0),maxRounds:numberValue(state2.maxRounds??nestedValue(state2,"limits","maxRounds"),3),stage:stringValue(state2.stage,"unknown"),node:stringValue(state2.node,"unknown"),stop:displayStop(state2),paused,gate:paused?"human":"machine",...typeof state2.pending_question=="string"?{pendingQuestion:state2.pending_question}:{},passed,verifier:verifierFor2(passed,fileLit),fingerprint:fingerprintFromState(state2),fileLit,contextPack:await contextPackLamps(cwd,job.directory),research:await loadResearchCell(job.directory),agents,kModeEnabled:kModeState.enabled,busLit,...freeze===void 0?{}:{kstack:{playbook:freeze.playbook,todos:freeze.todos}},...route.route===void 0?{}:{route:route.route},...usage===void 0?{}:{usage},...options.width===void 0?{}:{width:options.width}}}var boardThemeWarned=!1;function applyBoardTheme(ctx,paused){if(typeof ctx.ui.setTheme!="function")return;let name=paused?"protocol-blue":"loop-amber",result=ctx.ui.setTheme(name);return result?.success===!1&&!boardThemeWarned&&(boardThemeWarned=!0,ctx.ui.notify(`K-\u03C0 board theme ${name} was refused: ${result.error??"unknown reason"}`,"warning")),result}async function installWidget(ctx){let model2=await buildBoardModel(ctx.cwd);return model2===void 0?(ctx.ui.setWidget("kpi",void 0),!1):(applyBoardTheme(ctx,model2.paused),ctx.ui.setWidget("kpi",(_tui,theme2)=>createBoardComponent(model2,{layout:"compact",palette:paletteFromTheme(theme2)})),!0)}async function showStatus(ctx){let model2=await buildBoardModel(ctx.cwd);if(model2===void 0){ctx.ui.setWidget("kpi",void 0);let last=await readActiveJob(ctx.cwd),status=typeof last?.state.status=="string"?last.state.status:void 0;ctx.ui.notify(last===void 0?"no active job":`no active job \u2014 last job ${last.jobId} ${status??"ended"}`,"info");return}if(applyBoardTheme(ctx,model2.paused),ctx.ui.setWidget("kpi",(_tui,theme2)=>createBoardComponent(model2,{layout:"compact",palette:paletteFromTheme(theme2)})),ctx.mode!=="tui"||!ctx.hasUI){ctx.ui.notify(renderBoard(model2).join(`
1378
+ `);let facts=loopFacts(ctx.cwd,job.directory,task,baseline,plan!==void 0),engine=new GraphEngine(graph,{projectRoot:ctx.cwd,jobId:job.jobId,createAgentSession:dependencies.createAgentSession,busDependencies:dependencies.busDependencies,now:dependencies.now,accumulatedCostUsd:dependencies.accumulatedCostUsd,limits:task.limits,sleep:dependencies.sleep,retryBaseDelayMs:dependencies.retryBaseDelayMs,resolveFacts:facts.resolve,uiContext:ctx.ui,model:ctx.model,thinkingLevel:ctx.thinkingLevel});try{let stopState=createStopState(engine.limits.maxRounds);await writeState(job.directory,task,engine.state,stopState),await dependencies.onStateChange?.();let result=await driveUntilPause(engine,ctx.cwd,job.directory,task,facts,stopState,dependencies.onStateChange);if(result.terminalStatus!==void 0)return await writeTerminalState(job.directory,job.eventsPath,task,result),await dependencies.onStateChange?.(),{jobId:job.jobId,status:result.terminalStatus,reason:result.reason,recovery:result.recovery,graphState:result.state};for(;result.state.status==="interrupted";){let pending=result.state.pendingHuman;if(pending===void 0)throw new Error("Interrupted graph has no pending human approval");let approved=await ctx.ui.confirm(pending.title,pending.question);await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"approval.result",job_id:job.jobId,round:result.stopState.round,node:pending.nodeId,approved});let resumed=await engine.submitHuman(approved);if(stopState=result.stopState,await writeState(job.directory,task,engine.state,stopState),await dependencies.onStateChange?.(),result=await driveUntilPause(engine,ctx.cwd,job.directory,task,facts,stopState,dependencies.onStateChange),result.terminalStatus!==void 0)return await writeTerminalState(job.directory,job.eventsPath,task,result),await dependencies.onStateChange?.(),{jobId:job.jobId,status:result.terminalStatus,reason:result.reason,recovery:result.recovery,graphState:result.state};if(resumed.status==="completed")break}let state2=result.state,release=state2.values.release;if(state2.status!=="completed"||!isJsonObject(release)||release.approved!==!0){let blocked={state:state2,stopState:result.stopState,terminalStatus:"BLOCKED",reason:"graph completed without release approval"};return await writeTerminalState(job.directory,job.eventsPath,task,blocked),{jobId:job.jobId,status:"BLOCKED",graphState:state2}}try{await finalizeShip(ctx.cwd,job.directory,job.jobId,previousHead,result.shippedThisRun===!0,dependencies.readPullRequest)}catch(error){let{terminalStatus,reason,recovery}=shipFailure(error,job.jobId),stopped={state:state2,stopState:result.stopState,terminalStatus,reason,recovery};return await writeTerminalState(job.directory,job.eventsPath,task,stopped),await dependencies.onStateChange?.(),{jobId:job.jobId,status:terminalStatus,reason,recovery,graphState:state2}}return await writeTerminalState(job.directory,job.eventsPath,task,{state:state2,stopState:result.stopState,terminalStatus:"DONE",terminalEmitted:result.terminalEmitted}),await dependencies.onStateChange?.(),{jobId:job.jobId,status:"DONE",graphState:state2}}finally{engine.dispose()}}import{basename as basename18}from"node:path";var DEFAULT_LEFT_SEGMENT_ORDER=["brand","model","thinking","path","git","context_pct","cost"],DEFAULT_RIGHT_SEGMENT_ORDER=["request"],DEFAULT_SEGMENT_ORDER=[...DEFAULT_LEFT_SEGMENT_ORDER,...DEFAULT_RIGHT_SEGMENT_ORDER],SEGMENT_SEPARATOR=" > ",COMPACT_LEFT_SEGMENT_ORDER=["brand","model","path","cost"],FULL_LEFT_SEGMENT_ORDER=["brand","model","thinking","path","git","context_pct","cost","usage","kpi_job"];function leftSegmentsForPreset(preset){return preset==="compact"?COMPACT_LEFT_SEGMENT_ORDER:preset==="full"?FULL_LEFT_SEGMENT_ORDER:DEFAULT_LEFT_SEGMENT_ORDER}function formatModel(name){return`\u2B21 ${name??"no model"}`}function formatThinking(level){return`\u25CF ${level??"off"}`}function formatPath(cwd){return`\u{1F4C1} ${basename18(cwd)||cwd}`}function formatGit(branch){return branch?`\u2387 ${branch}`:void 0}function contextColor(percent){return percent<50?"success":percent<=70?"warning":percent<=90?"accent":"error"}function formatContext(percent,contextWindow){return percent==null||contextWindow==null?"\u25A6 \u2014":`\u25A6 ${percent.toFixed(0)}%/${formatCount(contextWindow)}`}function formatCost(cost,slotKind="api_key"){return slotKind==="oauth"?"(sub)":slotKind==="local"?"(local) $0":`$${cost.toFixed(2)}`}function formatUsage(remainingPercent,slotKind){if(slotKind!=="local"&&!(remainingPercent===void 0||!Number.isFinite(remainingPercent)))return`${Math.round(remainingPercent)}%`}function formatKpiJob(fields){let parts=["K-\u03C0","LOOP",fields.mode,`r${fields.round}/${fields.maxRounds}`,`STAGE ${fields.stage}`,`GATE ${fields.gate}`];return fields.ac!==void 0&&fields.ac.length>0&&parts.push(`AC ${fields.ac}`),fields.route!==void 0&&fields.route.length>0&&parts.push(`ROUTE ${fields.route}`),parts.join(" ")}function formatStatusRow(statuses,preset){let parts=Array.from(statuses.entries()).filter(([key])=>preset==="full"||key!=="accounts").sort(([left],[right])=>left.localeCompare(right)).map(([,text])=>text.replace(/\s+/gu," ").trim()).filter(text=>text.length>0);return parts.length===0?void 0:parts.join(" ")}function formatRequest(request2){if(request2)return request2.length<=80?request2:`${request2.slice(0,79)}\u2026`}function formatCount(value){return value>=1e6?`${Number((value/1e6).toFixed(1))}M`:value>=1e3?`${Number((value/1e3).toFixed(1))}k`:String(value)}function assembleFooter(input){let preset=input.preset??"default",slotKind=input.slotKind,segments={brand:input.brand,model:formatModel(input.model),thinking:formatThinking(input.thinking),path:formatPath(input.path),cost:formatCost(input.cost,slotKind)},git=formatGit(input.git??null);git!==void 0&&(segments.git=git),segments.context_pct=formatContext(input.contextPercent,input.contextWindow);let usage=formatUsage(input.remainingPercent,slotKind);usage!==void 0&&(segments.usage=usage),input.kpiJob!==void 0&&(segments.kpi_job=formatKpiJob(input.kpiJob));let request2=formatRequest(input.request);request2!==void 0&&(segments.request=request2);let line=leftSegmentsForPreset(preset).map(id=>segments[id]).filter(text=>typeof text=="string"&&text.length>0).join(SEGMENT_SEPARATOR);request2!==void 0&&(line=`${line} \u2500\u2500\u2500\u2500 ${request2}`);let jobLine;return preset!=="full"&&input.kpiJob!==void 0&&(jobLine=formatKpiJob(input.kpiJob)),input.width!==void 0&&input.width>0&&line.length>input.width&&(line=`${line.slice(0,Math.max(0,input.width-1))}\u2026`),{line,...jobLine===void 0?{}:{jobLine},segments}}function nestedValue(state2,parent,child){let value=state2[parent];if(value!==null&&typeof value=="object"&&!Array.isArray(value))return value[child]}function stringValue(value,fallback){return typeof value=="string"?value:fallback}function numberValue(value,fallback){return typeof value=="number"&&Number.isFinite(value)?value:fallback}function booleanValue(value){return typeof value=="boolean"?value:void 0}function isPausedHuman(state2){if(state2.graph_status==="interrupted")return!0;let question=state2.pending_question;if(typeof question=="string"&&question.trim().length>0)return!0;let pending=state2.pending_human??state2.pendingHuman;return pending!==null&&typeof pending=="object"&&!Array.isArray(pending)}function displayStop(state2){return normalizeStop(stringValue(state2.status??state2.stop,"RUNNING"))}async function fileLitMap(directory){let entries=await Promise.all(RUN_FILE_NAMES.map(async name=>{try{let metadata=await stat10(join56(directory,name));return[name,metadata.isFile()&&metadata.size>0]}catch(error){if(error.code==="ENOENT")return[name,!1];throw error}}));return Object.fromEntries(entries)}async function busLogLit(directory){try{let metadata=await stat10(join56(directory,"bus.jsonl"));return metadata.isFile()&&metadata.size>0}catch(error){if(error.code==="ENOENT")return!1;throw error}}async function jobPlaybookFreeze(runDirectory,state2){let statePlaybook=typeof state2.playbook=="string"&&state2.playbook.trim().length>0?state2.playbook:void 0,stateTodos=Array.isArray(state2.todos)?state2.todos.filter(entry=>typeof entry=="string"):void 0;if(statePlaybook!==void 0)return{playbook:statePlaybook,todos:stateTodos??[]};try{let task=JSON.parse(await readFile23(join56(runDirectory,"task.json"),"utf8"));if(typeof task.playbook!="string"||task.playbook.trim().length===0)return;let todos=stateTodos??(Array.isArray(task.playbook_steps)?task.playbook_steps.filter(step=>typeof step?.node=="string"&&step.node.trim().length>0&&typeof step?.text=="string"&&step.text.trim().length>0).map(step=>typeof step.skip=="string"&&step.skip.trim().length>0?`${step.node}: ${step.text} \u2014 skip: ${step.skip}`:`${step.node}: ${step.text}`):[]);return{playbook:task.playbook,todos}}catch{return}}async function contextPackLamps(cwd,runDirectory){let roots=[join56(cwd,CONFIG_DIR_NAME,"context"),join56(runDirectory,"context"),runDirectory],names2=["product.md","structure.md","tech.md"],lit={product:!1,structure:!1,tech:!1};for(let root of roots)for(let name of names2){let key=name.replace(/\.md$/,"");if(!lit[key])try{let metadata=await stat10(join56(root,name));metadata.isFile()&&metadata.size>0&&(lit[key]=!0)}catch{}}return lit}async function loadResearchCell(runDirectory){try{let raw=JSON.parse(await readFile23(join56(runDirectory,"research.json"),"utf8"));return researchCellFromDocument(raw)}catch{return}}function fingerprintFromState(state2){let direct=state2.output_fingerprint??state2.fingerprint;if(typeof direct=="string")return direct;let fingerprints=state2.output_fingerprints;if(Array.isArray(fingerprints)&&fingerprints.length>0){let last=fingerprints.at(-1);return typeof last=="string"?last:void 0}}function verifierFor2(passed,fileLit){return passed===!0?"pass":passed===!1&&fileLit["verdict.json"]===!0?"fail":"pending"}async function buildBoardModel(cwd,options={}){let job=await readLiveJob(cwd);if(job===void 0)return;let state2=job.state,paused=isPausedHuman(state2),route=getFooterRouteSnapshot(),usage=formatUsage(route.remainingPercent,route.slotKind),freeze=await jobPlaybookFreeze(job.directory,state2),agents=options.agents??liveWorkerCount(),busLit=await busLogLit(job.directory),fileLit=await fileLitMap(job.directory),passed=booleanValue(typeof state2.passed=="boolean"?state2.passed:nestedValue(state2,"test","passed"));return{jobId:job.jobId,mode:stringValue(state2.mode,"gated"),round:numberValue(state2.round,0),maxRounds:numberValue(state2.maxRounds??nestedValue(state2,"limits","maxRounds"),3),stage:stringValue(state2.stage,"unknown"),node:stringValue(state2.node,"unknown"),stop:displayStop(state2),paused,gate:paused?"human":"machine",...typeof state2.pending_question=="string"?{pendingQuestion:state2.pending_question}:{},passed,verifier:verifierFor2(passed,fileLit),fingerprint:fingerprintFromState(state2),fileLit,contextPack:await contextPackLamps(cwd,job.directory),research:await loadResearchCell(job.directory),agents,kModeEnabled:kModeState.enabled,busLit,...freeze===void 0?{}:{kstack:{playbook:freeze.playbook,todos:freeze.todos}},...route.route===void 0?{}:{route:route.route},...usage===void 0?{}:{usage},...options.width===void 0?{}:{width:options.width}}}var boardThemeWarned=!1;function applyBoardTheme(ctx,paused){if(typeof ctx.ui.setTheme!="function")return;let name=paused?"protocol-blue":"loop-amber",result=ctx.ui.setTheme(name);return result?.success===!1&&!boardThemeWarned&&(boardThemeWarned=!0,ctx.ui.notify(`K-\u03C0 board theme ${name} was refused: ${result.error??"unknown reason"}`,"warning")),result}async function installWidget(ctx){let model2=await buildBoardModel(ctx.cwd);return model2===void 0?(ctx.ui.setWidget("kpi",void 0),!1):(applyBoardTheme(ctx,model2.paused),ctx.ui.setWidget("kpi",(_tui,theme2)=>createBoardComponent(model2,{layout:"compact",palette:paletteFromTheme(theme2)})),!0)}async function showStatus(ctx){let model2=await buildBoardModel(ctx.cwd);if(model2===void 0){ctx.ui.setWidget("kpi",void 0);let last=await readActiveJob(ctx.cwd),status=typeof last?.state.status=="string"?last.state.status:void 0;ctx.ui.notify(last===void 0?"no active job":`no active job \u2014 last job ${last.jobId} ${status??"ended"}`,"info");return}if(applyBoardTheme(ctx,model2.paused),ctx.ui.setWidget("kpi",(_tui,theme2)=>createBoardComponent(model2,{layout:"compact",palette:paletteFromTheme(theme2)})),ctx.mode!=="tui"||!ctx.hasUI){ctx.ui.notify(renderBoard(model2).join(`
1379
1379
  `),"info");return}await ctx.ui.custom((_tui,theme2,_keybindings,done)=>{let board=createBoardComponent(model2,{layout:"full",palette:paletteFromTheme(theme2)});return{handleInput(){done()},invalidate(){board.invalidate()},render(width){return board.render(width)},dispose(){board.dispose()}}},{overlay:!0,overlayOptions:{width:"92%",maxHeight:"90%",anchor:"center"}})}async function stopJob(ctx){let job=await readActiveJob(ctx.cwd);if(job===void 0){ctx.ui.notify("no active job","info");return}let round=numberValue(job.state.round,0);await appendEvent(job.eventsPath,{ts:new Date().toISOString(),type:"loop.terminal",job_id:job.jobId,round,node:stringValue(job.state.node,"control-plane"),status:"BLOCKED",reason:"operator stop"});let stoppedState={...job.state,status:"BLOCKED"};await atomicWrite(job.statePath,`${JSON.stringify(stoppedState,null,2)}
1380
- `),await installWidget(ctx),ctx.ui.notify(`K-\u03C0 job ${job.jobId} BLOCKED`,"warning")}async function verifyJobLog(args,ctx){let requested=args.trim(),path14=requested.length>0?join56(ctx.cwd,CONFIG_DIR_NAME,"runs",requested,"events.jsonl"):(await readActiveJob(ctx.cwd))?.eventsPath;if(path14===void 0){ctx.ui.notify("no active job to verify; pass a job id","info");return}let report=await inspectChain(path14),jobId=requested.length>0?requested:(await readActiveJob(ctx.cwd))?.jobId;if(report.ok){ctx.ui.notify(`events.jsonl verified: ${report.records} records chained for ${jobId??"this job"}`,"info");return}ctx.ui.notify(`events.jsonl FAILED verification at line ${report.line??0}: ${report.reason??"unknown"} (${report.records} records verified before it)`,"error")}var ROUTING_NOTICES={off:"K-\u03C0 routing off: bare text is plain chat and only /kpi starts a job",auto:"K-\u03C0 routing auto: the agent starts a job for substantial work",always:"K-\u03C0 routing always: bare text starts a gated job"},TOLERATED_PROBE_ERRORS=new Set(["ENOENT","ENAMETOOLONG","ENOTDIR"]);async function isRunDirectory(cwd,jobId){try{return await readFile23(join56(cwd,CONFIG_DIR_NAME,"runs",jobId,"task.json"),"utf8"),!0}catch(error){if(TOLERATED_PROBE_ERRORS.has(error.code??""))return!1;throw error}}async function handleKpiCommand(args,ctx,dependencies){let command=args.trim();if(command===""||command==="status"){await showStatus(ctx);return}if(command==="stop"){await stopJob(ctx);return}if(isRoutingMode(command)){routingState.override=command,ctx.ui.notify(ROUTING_NOTICES[command],"info");return}if(command==="verify"||command.startsWith("verify ")&&JOB_ID_PATTERN.test(command.slice(7).trim())){await verifyJobLog(command.slice(6),ctx);return}try{let onStateChange=async()=>{await installWidget(ctx)},outcome=JOB_ID_PATTERN.test(command)&&await isRunDirectory(ctx.cwd,command)?await resumeLoop(command,ctx,{...dependencies,onStateChange}):await runLoop2(parseLoopInvocation(command),ctx,{...dependencies,onStateChange});ctx.ui.notify(`K-\u03C0 job ${outcome.jobId} ${outcome.status}`,"info")}catch(error){let message=error instanceof Error?error.message:String(error);ctx.ui.notify(`K-\u03C0 loop failed: ${message}`,"error")}}function registerControlPlane(pi,dependencies={}){pi.on("session_start",async(_event,ctx)=>{await installWidget(ctx)});let command={description:"Control the K-\u03C0 coding loop: <goal>, status, stop, verify, auto|always|off routing (--max-cost-usd / --timeout-ms / --max-rounds freeze onto task.limits)",handler:async(args,ctx)=>{await handleKpiCommand(args,ctx,dependencies)}};pi.registerCommand("kpi",command),pi.registerCommand("loop",command)}import{mkdirSync as mkdirSync12,readFileSync as readFileSync17,renameSync as renameSync4,writeFileSync as writeFileSync11}from"node:fs";import{dirname as dirname28,join as join57}from"node:path";async function login(interaction){let access4=await interaction.onPrompt({message:"Paste a Cursor access token",placeholder:"Cursor token"});if(access4.trim().length===0)throw new Error("Cursor token is required");return{access:access4.trim(),refresh:access4.trim(),expires:Date.now()+365*24*60*60*1e3}}async function refreshToken(credentials,signal){if(signal.aborted)throw signal.reason;return credentials}function getApiKey(credentials){return credentials.access}var CURSOR_BASE_URL="https://api2.cursor.sh/v1";function model(id,name=id){return{id,name,api:"openai-completions",reasoning:!0,input:["text","image"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:128e3,maxTokens:16384}}var CURSOR_FALLBACK_MODELS=[model("cursor-small","Cursor Small (fallback)")];function storedCursorModelsPath(agentDirectory=getAgentDir()){return join57(agentDirectory,"cursor-models.json")}function readStoredCursorModels(agentDirectory){try{let parsed=JSON.parse(readFileSync17(storedCursorModelsPath(agentDirectory),"utf8"));if(!Array.isArray(parsed))return;let models=parsed.flatMap(entry=>{if(typeof entry!="object"||entry===null)return[];let candidate=entry;return typeof candidate.id!="string"||candidate.id.length===0?[]:[model(candidate.id,typeof candidate.name=="string"?candidate.name:candidate.id)]});return models.length===0?void 0:models}catch{return}}function writeStoredCursorModels(models,agentDirectory){let path14=storedCursorModelsPath(agentDirectory),temporaryPath=`${path14}.${process.pid}.tmp`;try{mkdirSync12(dirname28(path14),{recursive:!0}),writeFileSync11(temporaryPath,`${JSON.stringify(models,null,2)}
1380
+ `),await installWidget(ctx),ctx.ui.notify(`K-\u03C0 job ${job.jobId} BLOCKED`,"warning")}async function verifyJobLog(args,ctx){let requested=args.trim(),path14=requested.length>0?join56(ctx.cwd,CONFIG_DIR_NAME,"runs",requested,"events.jsonl"):(await readActiveJob(ctx.cwd))?.eventsPath;if(path14===void 0){ctx.ui.notify("no active job to verify; pass a job id","info");return}let report=await inspectChain(path14),jobId=requested.length>0?requested:(await readActiveJob(ctx.cwd))?.jobId;if(report.ok){ctx.ui.notify(`events.jsonl verified: ${report.records} records chained for ${jobId??"this job"}`,"info");return}ctx.ui.notify(`events.jsonl FAILED verification at line ${report.line??0}: ${report.reason??"unknown"} (${report.records} records verified before it)`,"error")}var ROUTING_NOTICES={off:"K-\u03C0 routing off: bare text is plain chat and only /kpi starts a job",auto:"K-\u03C0 routing auto: the agent starts a job for substantial work",always:"K-\u03C0 routing always: bare text starts a gated job"},TOLERATED_PROBE_ERRORS=new Set(["ENOENT","ENAMETOOLONG","ENOTDIR"]);async function isRunDirectory(cwd,jobId){try{return await readFile23(join56(cwd,CONFIG_DIR_NAME,"runs",jobId,"task.json"),"utf8"),!0}catch(error){if(TOLERATED_PROBE_ERRORS.has(error.code??""))return!1;throw error}}async function handleKpiCommand(args,ctx,dependencies){let command=args.trim();if(command===""||command==="status"){await showStatus(ctx);return}if(command==="stop"){await stopJob(ctx);return}if(isRoutingMode(command)){routingState.override=command,ctx.ui.notify(ROUTING_NOTICES[command],"info");return}if(command==="verify"||command.startsWith("verify ")&&JOB_ID_PATTERN.test(command.slice(7).trim())){await verifyJobLog(command.slice(6),ctx);return}try{let onStateChange=async()=>{await installWidget(ctx)},outcome=JOB_ID_PATTERN.test(command)&&await isRunDirectory(ctx.cwd,command)?await resumeLoop(command,ctx,{...dependencies,onStateChange}):await runLoop2(parseLoopInvocation(command),ctx,{...dependencies,onStateChange}),reason=outcome.reason===void 0?"":`: ${outcome.reason}`;if(ctx.ui.notify(`K-\u03C0 job ${outcome.jobId} ${outcome.status}${reason}`,outcome.status==="DONE"?"info":"warning"),outcome.status==="NEEDS_HUMAN"&&ctx.hasUI&&outcome.recovery==="provider"){let resumeAfterFix=await ctx.ui.confirm("K-\u03C0 provider recovery",`${outcome.reason??"The provider account is unavailable."}
1381
+
1382
+ Resolve the account or choose another model, then resume this job?`);ctx.ui.notify(resumeAfterFix?`After resolving the provider, run /kpi ${outcome.jobId}`:`K-\u03C0 job ${outcome.jobId} remains at NEEDS_HUMAN`,"info")}}catch(error){let message=error instanceof Error?error.message:String(error);ctx.ui.notify(`K-\u03C0 loop failed: ${message}`,"error")}}function registerControlPlane(pi,dependencies={}){pi.on("session_start",async(_event,ctx)=>{await installWidget(ctx)});let command={description:"Control the K-\u03C0 coding loop: <goal>, status, stop, verify, auto|always|off routing (--max-cost-usd / --timeout-ms / --max-rounds freeze onto task.limits)",handler:async(args,ctx)=>{await handleKpiCommand(args,ctx,dependencies)}};pi.registerCommand("kpi",command),pi.registerCommand("loop",command)}import{mkdirSync as mkdirSync12,readFileSync as readFileSync17,renameSync as renameSync4,writeFileSync as writeFileSync11}from"node:fs";import{dirname as dirname28,join as join57}from"node:path";async function login(interaction){let access4=await interaction.onPrompt({message:"Paste a Cursor access token",placeholder:"Cursor token"});if(access4.trim().length===0)throw new Error("Cursor token is required");return{access:access4.trim(),refresh:access4.trim(),expires:Date.now()+365*24*60*60*1e3}}async function refreshToken(credentials,signal){if(signal.aborted)throw signal.reason;return credentials}function getApiKey(credentials){return credentials.access}var CURSOR_BASE_URL="https://api2.cursor.sh/v1";function model(id,name=id){return{id,name,api:"openai-completions",reasoning:!0,input:["text","image"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:128e3,maxTokens:16384}}var CURSOR_FALLBACK_MODELS=[model("cursor-small","Cursor Small (fallback)")];function storedCursorModelsPath(agentDirectory=getAgentDir()){return join57(agentDirectory,"cursor-models.json")}function readStoredCursorModels(agentDirectory){try{let parsed=JSON.parse(readFileSync17(storedCursorModelsPath(agentDirectory),"utf8"));if(!Array.isArray(parsed))return;let models=parsed.flatMap(entry=>{if(typeof entry!="object"||entry===null)return[];let candidate=entry;return typeof candidate.id!="string"||candidate.id.length===0?[]:[model(candidate.id,typeof candidate.name=="string"?candidate.name:candidate.id)]});return models.length===0?void 0:models}catch{return}}function writeStoredCursorModels(models,agentDirectory){let path14=storedCursorModelsPath(agentDirectory),temporaryPath=`${path14}.${process.pid}.tmp`;try{mkdirSync12(dirname28(path14),{recursive:!0}),writeFileSync11(temporaryPath,`${JSON.stringify(models,null,2)}
1381
1383
  `,{encoding:"utf8",mode:384}),renameSync4(temporaryPath,path14)}catch{}}async function refreshCursorModels(context,fetchImpl=fetch){if(!context.allowNetwork)return readStoredCursorModels()??[...CURSOR_FALLBACK_MODELS];let credential=context.credential,token=credential?.type==="oauth"?credential.access:credential?.key,response=await fetchImpl(`${CURSOR_BASE_URL}/models`,{headers:token===void 0?void 0:{authorization:`Bearer ${token}`},signal:context.signal});if(!response.ok)throw new Error(`Cursor model refresh failed: ${response.status}`);let payload=await response.json(),models=(payload.models??payload.data??[]).flatMap(entry=>typeof entry.id=="string"?[model(entry.id,typeof entry.name=="string"?entry.name:entry.id)]:[]);return models.length===0?readStoredCursorModels()??[...CURSOR_FALLBACK_MODELS]:(writeStoredCursorModels(models),models)}function registerCursorProvider(pi){pi.registerProvider("cursor",{name:"Cursor",baseUrl:CURSOR_BASE_URL,api:"openai-completions",authHeader:!0,models:readStoredCursorModels()??CURSOR_FALLBACK_MODELS,oauth:{name:"Cursor",isSubscription:!0,login,refreshToken,getApiKey},refreshModels:refreshCursorModels})}var claimEnvelope={id:typebox_exports.String(),kind:typebox_exports.String(),source_ids:typebox_exports.Array(typebox_exports.String()),status:typebox_exports.Union([typebox_exports.Literal("proposed"),typebox_exports.Literal("verified"),typebox_exports.Literal("rejected"),typebox_exports.Literal("superseded")]),observed_at:typebox_exports.String()};function registerKnowledgeGraph(pi){pi.registerTool({name:"kg_propose",label:"KG Propose",description:"Propose a knowledge graph claim. Writes one patch to the inbox for control-plane acceptance; the authoritative nodes, edges, sources, and snapshots are never writable from here.",parameters:typebox_exports.Object({source:typebox_exports.Optional(typebox_exports.Object({...claimEnvelope,uri:typebox_exports.String()})),node:typebox_exports.Optional(typebox_exports.Object(claimEnvelope)),edge:typebox_exports.Optional(typebox_exports.Object({...claimEnvelope,from:typebox_exports.String(),to:typebox_exports.String(),confidence:typebox_exports.Optional(typebox_exports.Number())}))}),async execute(_id,params,_signal,_update,context){let path14=await new KnowledgeGraphProposals(context.cwd).propose(params);return{content:[{type:"text",text:path14}],details:{path:path14}}}}),pi.registerCommand("kg",{description:"Query, propose, or accept K-\u03C0 knowledge graph claims",handler:async(args,context)=>{let[action,...rest]=args.trim().split(/\s+/u);if(action==="query"||action===""){let nodes=await new KnowledgeGraphProposals(context.cwd).query(rest.join(" "));context.ui.notify(nodes.map(node=>`${node.id}@${node.rev} ${node.status}`).join(`
1382
1384
  `)||"No claims","info");return}if(action==="propose"){let patch=JSON.parse(rest.join(" "));context.ui.notify(await new KnowledgeGraphProposals(context.cwd).propose(patch),"info");return}if(action==="accept"){let accepted=await new KnowledgeGraphControlPlane(context.cwd).accept(rest.join(" ")),summary=[];for(let kind of PATCH_KINDS){let record=accepted[kind];record!==void 0&&summary.push(`${kind} ${record.id}@${record.rev}`)}context.ui.notify(`Accepted ${summary.join(" ")}`,"info");return}throw new Error("Usage: /kg query <text> | propose <json> | accept <inbox-path>")}})}function registerPing(pi){pi.registerCommand("kpi-ping",{description:"Verify that k-pi loaded",handler:async(_args,ctx)=>{ctx.ui.notify("ok","info")}})}var PRINT_TOOLS=new Set(["read","grep","find","ls"]);function registerPrintProfile(pi){pi.on("session_start",(_event,context)=>{context.mode==="print"&&pi.setActiveTools(pi.getActiveTools().filter(tool=>PRINT_TOOLS.has(tool)))})}function field(event,key){let value=event?.[key];if(typeof value=="string"&&value.length>0)return value;if(typeof value=="number"&&Number.isFinite(value))return String(value);if(typeof value=="boolean")return value?"true":"false"}function formatEventEntry(type,event){let job=event?.job_id===void 0?"":` job=${event.job_id}`,round=event?.round===void 0?"":` r${event.round}`;if(type.startsWith("research.")){let mode=field(event,"mode"),service=field(event,"service"),network=field(event,"network_state"),count=field(event,"result_count"),reason=field(event,"reason"),query=field(event,"query"),parts=[`K-\u03C0 ${type}${job}${round}`];return mode&&parts.push(`mode=${mode}`),service&&parts.push(`svc=${service}`),network&&parts.push(`net=${network}`),count&&parts.push(`n=${count}`),reason&&parts.push(reason),query&&parts.push(`q=${query.length>40?`${query.slice(0,39)}\u2026`:query}`),parts.join(" ")}if(type==="accounts.failover"){let from=field(event,"from")??"?",to=field(event,"to")??"?",reason=field(event,"reason");return`K-\u03C0 accounts.failover${job}${round} ${from} \u2192 ${to}${reason?` (${reason})`:""}`}if(type==="agent.spawned"){let agent=field(event,"agent_id")??"?",role=field(event,"role")??"worker",pid=field(event,"pid");return`K-\u03C0 agent.spawned${job}${round} ${role} ${agent}${pid?` pid=${pid}`:""}`}if(type==="agent.message"){let agent=field(event,"agent_id")??"?",deliver=field(event,"deliver_as"),status2=field(event,"status");return`K-\u03C0 agent.message${job}${round} ${agent}${deliver?` as=${deliver}`:""}${status2?` ${status2}`:""}`}if(type==="checkpoint"){let detail=field(event,"detail");return`K-\u03C0 checkpoint${job}${round}${detail?` ${detail}`:""}`}if(type==="loop.terminal"){let status2=field(event,"status")??"DONE",reason=field(event,"reason");return`K-\u03C0 loop.terminal${job}${round} ${status2}${reason?` \u2014 ${reason}`:""}`}if(type==="review.verdict"){let status2=field(event,"status")??"?",approved=field(event,"approved"),blocking=field(event,"blocking_count")??"0",nonblocking=field(event,"nonblocking_count"),fp=field(event,"fingerprint"),parts=[`K-\u03C0 review.verdict${job}${round}`,status2];return approved!==void 0&&parts.push(approved==="true"?"approved":"not-approved"),parts.push(`blocking=${blocking}`),nonblocking!==void 0&&parts.push(`nonblocking=${nonblocking}`),fp!==void 0&&parts.push(`fp=${fp.length>16?fp.slice(0,16):fp}`),parts.join(" ")}let status=typeof event?.status=="string"?` status=${event.status}`:"";return`K-\u03C0 ${type}${job}${round}${status}`}function registerEventRenderers(pi){for(let type of EVENT_TYPES2)pi.registerEntryRenderer(type,entry=>{let line=formatEventEntry(type,entry.data);return{invalidate(){},render(){return[line]}}})}import{join as join58}from"node:path";var MAX_TOOL_OUTPUT_CHARACTERS=1e4,sessions=new Map;async function sessionFor(cwd,service){let job=await readActiveJob(cwd),jobId=job?.jobId??"no-job",settings2=await readKpiSettings(cwd),{endpoints,timeoutMs}=resolveResearchEndpoints(settings2.researchEndpoints),existing=sessions.get(jobId);if(existing!==void 0)return{session:existing,service,endpoints,timeoutMs};let session=new ResearchSession({jobId,mode:settings2.research,keys:await resolveResearchKeys(),eventsPath:job===void 0?void 0:join58(cwd,CONFIG_DIR_NAME,"runs",jobId,"events.jsonl"),round:typeof job?.state.round=="number"?job.state.round:0,node:typeof job?.state.node=="string"?job.state.node:"research"});return sessions.set(jobId,session),{session,service,endpoints,timeoutMs}}function summarize(results){let lines=results.map(result=>result.text===void 0?`- ${result.title} ${result.url}`:`- ${result.title} ${result.url}
1383
1385
  ${result.text}`);return clampField(lines.join(`
@@ -1480,7 +1482,7 @@ ${packageLines}`,1,0)),this.chatContainer.addChild(new DynamicBorder(text=>theme
1480
1482
 
1481
1483
  `),currentText=options?.currentText??this.editor.getText(),combinedText=[queuedText,currentText].filter(t=>t.trim()).join(`
1482
1484
 
1483
- `);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.agent.abort(),allQueued.length}queueCompactionMessage(text,mode){this.compactionQueuedMessages.push({text,mode}),this.editor.addToHistory?.(text),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text){if(!text.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text.indexOf(" "),commandName=spaceIndex===-1?text.slice(1):text.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))});dispose=created.dispose,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(),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)}`)},onModelThinkingLevelChange:(provider2,modelId,level)=>{this.settingsManager.setModelThinkingLevel(provider2,modelId,level);let current=this.session.model;current&&current.provider===provider2&&current.id===modelId&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider2,modelId)=>{this.settingsManager.removeModelThinkingLevel(provider2,modelId);let current=this.session.model;if(current&&current.provider===provider2&&current.id===modelId){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 model2=await this.findExactModelMatch(searchTerm);if(model2){try{await this.session.setModel(model2,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model2.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model2),this.checkDaxnutsEasterEgg(model2)}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 result=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result.errors.size>0&&this.showWarning(`Could not refresh ${[...result.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(model2=>model2.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model2=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model2||model2.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(model2.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(model2,persist)=>{try{await this.session.setModel(model2,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model2.provider}/${model2.id}`:`Model: ${model2.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model2),this.checkDaxnutsEasterEgg(model2)}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,model2=>selectModel(model2,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model2=>selectModel(model2,!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(model2=>`${model2.provider}/${model2.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(result=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model2=>`${model2.provider}/${model2.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result.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 result=await this.runtimeHost.fork(entryId);if(result.cancelled){this.ui.requestRender();return}this.editor.setText(result.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}this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort());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 result=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result.editorText&&!this.editor.getText().trim()&&this.editor.setText(result.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 text=>{if(!text){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text),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=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress),onProgress=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress),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 result=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result.cancelled||this.showStatus("Resumed session"),result}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result.cancelled||this.showStatus("Resumed session in current cwd"),result}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider2 of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider2.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider2.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0;(!authType||authType==="oauth")&&provider2.auth.oauth&&options.push({id:provider2.id,name:provider2.name,authType:"oauth",method:provider2.auth.oauth,status}),(!authType||authType==="api_key")&&provider2.auth.apiKey&&options.push({id:provider2.id,name:provider2.name,authType:"api_key",method:provider2.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(provider2=>provider2.id.toLowerCase()===normalizedProviderRef||provider2.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(provider2=>provider2.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(provider2=>provider2.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(provider2=>provider2.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(provider2=>provider2.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(provider2=>provider2.id===providerId&&provider2.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(provider2=>provider2.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}`,selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model2=>model2.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(model2=>model2.id===defaultModelId),!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 errorMessage2=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage2}. 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());let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);this.session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(result=>{result.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>restoreEditor2(),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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"api_key"),restoreEditor2(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor2();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((resolve26,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?resolve26(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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"oauth"),restoreEditor2(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel)}catch(error){restoreEditor2();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(resolve26=>process.nextTick(resolve26));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(text){let outputPath=this.getPathCommandArgument(text,"/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(text,command){if(text===command||!text.startsWith(`${command} `))return;let argsString=text.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(text){let inputPath=this.getPathCommandArgument(text,"/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 handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text=this.session.getLastAssistantText();if(!text){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text),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(text){let name=text.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 sessionName=this.sessionManager.getSessionName();sessionName!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name set: ${sessionName??name}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),info=`${theme.bold("Session Info")}
1485
+ `);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.agent.abort(),allQueued.length}queueCompactionMessage(text,mode){this.compactionQueuedMessages.push({text,mode}),this.editor.addToHistory?.(text),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text){if(!text.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text.indexOf(" "),commandName=spaceIndex===-1?text.slice(1):text.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))});dispose=created.dispose,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(),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)}`)},onModelThinkingLevelChange:(provider2,modelId,level)=>{this.settingsManager.setModelThinkingLevel(provider2,modelId,level);let current=this.session.model;current&&current.provider===provider2&&current.id===modelId&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider2,modelId)=>{this.settingsManager.removeModelThinkingLevel(provider2,modelId);let current=this.session.model;if(current&&current.provider===provider2&&current.id===modelId){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 model2=await this.findExactModelMatch(searchTerm);if(model2){try{await this.session.setModel(model2,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model2.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model2),this.checkDaxnutsEasterEgg(model2)}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 result=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result.errors.size>0&&this.showWarning(`Could not refresh ${[...result.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(model2=>model2.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model2=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model2||model2.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(model2.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(model2,persist)=>{try{await this.session.setModel(model2,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model2.provider}/${model2.id}`:`Model: ${model2.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model2),this.checkDaxnutsEasterEgg(model2)}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,model2=>selectModel(model2,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model2=>selectModel(model2,!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(model2=>`${model2.provider}/${model2.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(result=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model2=>`${model2.provider}/${model2.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result.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 result=await this.runtimeHost.fork(entryId);if(result.cancelled){this.ui.requestRender();return}this.editor.setText(result.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}this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort());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 result=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result.editorText&&!this.editor.getText().trim()&&this.editor.setText(result.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 text=>{if(!text){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text),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=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress),onProgress=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress),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 result=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result.cancelled||this.showStatus("Resumed session"),result}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result.cancelled||this.showStatus("Resumed session in current cwd"),result}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider2 of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider2.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider2.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0;(!authType||authType==="oauth")&&provider2.auth.oauth&&options.push({id:provider2.id,name:provider2.name,authType:"oauth",method:provider2.auth.oauth,status}),(!authType||authType==="api_key")&&provider2.auth.apiKey&&options.push({id:provider2.id,name:provider2.name,authType:"api_key",method:provider2.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(provider2=>provider2.id.toLowerCase()===normalizedProviderRef||provider2.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(provider2=>provider2.id)).size===1){this.showLoginAuthTypeSelector(providerOptions);return}this.showLoginProviderSelector(void 0,providerRef)}async startProviderLogin(providerOption){providerOption.authType==="oauth"&&isPoolId(providerOption.id)&&this.session.extensionRunner.getCommand("accounts")!==void 0?await this.session.prompt(`/accounts login-active ${providerOption.id}`):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(provider2=>provider2.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(provider2=>provider2.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(provider2=>provider2.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(provider2=>provider2.id===providerId&&provider2.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(provider2=>provider2.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}`,selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model2=>model2.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(model2=>model2.id===defaultModelId),!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 errorMessage2=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage2}. 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());let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);this.session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(result=>{result.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>restoreEditor2(),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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"api_key"),restoreEditor2(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor2();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((resolve26,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?resolve26(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 restoreEditor2=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,"oauth"),restoreEditor2(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel)}catch(error){restoreEditor2();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(resolve26=>process.nextTick(resolve26));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(text){let outputPath=this.getPathCommandArgument(text,"/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(text,command){if(text===command||!text.startsWith(`${command} `))return;let argsString=text.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(text){let inputPath=this.getPathCommandArgument(text,"/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 handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text=this.session.getLastAssistantText();if(!text){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text),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(text){let name=text.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 sessionName=this.sessionManager.getSessionName();sessionName!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Text(theme.fg("dim",`Session name set: ${sessionName??name}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),info=`${theme.bold("Session Info")}
1484
1486
 
1485
1487
  `;sessionName&&(info+=`${theme.fg("dim","Name:")} ${sessionName}
1486
1488
  `),info+=`${theme.fg("dim","File:")} ${stats.sessionFile??"In-memory"}