@astralyn/pi 0.87.3 → 0.87.5

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/bundle/chunks/{chunk-MJ45I4SM.js → chunk-APQ4ACY3.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-TYOQD6VQ.js → chunk-EWLAVDVN.js} +13 -13
  4. package/dist/bundle/chunks/{virtual-modules-NDGCHNG7.js → virtual-modules-W3OGMIX7.js} +1 -1
  5. package/dist/bundle/cli.js +1 -1
  6. package/dist/bundle/index.js +1 -1
  7. package/dist/bundle/rpc-entry.js +1 -1
  8. package/dist/core/background/service.d.ts.map +1 -1
  9. package/dist/core/background/service.js +4 -3
  10. package/dist/core/background/service.js.map +1 -1
  11. package/dist/core/background/types.d.ts +11 -0
  12. package/dist/core/background/types.d.ts.map +1 -1
  13. package/dist/core/background/types.js +14 -0
  14. package/dist/core/background/types.js.map +1 -1
  15. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  16. package/dist/core/tools/tool-definition-wrapper.js +11 -1
  17. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  18. package/dist/extensions/background/actions.d.ts.map +1 -1
  19. package/dist/extensions/background/actions.js +38 -31
  20. package/dist/extensions/background/actions.js.map +1 -1
  21. package/dist/extensions/todo/constants.d.ts +1 -1
  22. package/dist/extensions/todo/constants.d.ts.map +1 -1
  23. package/dist/extensions/todo/constants.js +2 -2
  24. package/dist/extensions/todo/constants.js.map +1 -1
  25. package/dist/extensions/todo/index.js +1 -1
  26. package/dist/extensions/todo/index.js.map +1 -1
  27. package/dist/extensions/todo/schema.d.ts +1 -0
  28. package/dist/extensions/todo/schema.d.ts.map +1 -1
  29. package/dist/extensions/todo/schema.js +1 -1
  30. package/dist/extensions/todo/schema.js.map +1 -1
  31. package/dist/extensions/todo/state.d.ts.map +1 -1
  32. package/dist/extensions/todo/state.js +20 -8
  33. package/dist/extensions/todo/state.js.map +1 -1
  34. package/dist/extensions/todo/view.d.ts +1 -1
  35. package/dist/extensions/todo/view.d.ts.map +1 -1
  36. package/dist/extensions/todo/view.js +4 -24
  37. package/dist/extensions/todo/view.js.map +1 -1
  38. package/docs/bundled/extensions/todo.md +5 -5
  39. package/npm-shrinkwrap.json +2 -2
  40. package/package.json +1 -1
@@ -662,8 +662,8 @@ ${guidance}`:"",remaining=BACKGROUND_RESULT_BYTES-Buffer.byteLength(prefix)-Buff
662
662
 
663
663
  ---
664
664
 
665
- `)+suffix}return prefix+modelText(snapshot.output??{text:"No text result.",truncated:!1},remaining,lines)+suffix}function backgroundCompletionMessage(task){let details=backgroundCompletionSnapshot(task);return{role:"custom",customType:"background-completion",display:!0,content:notificationText(details),details,timestamp:Date.now()}}var BACKGROUND_HISTORY_VERSION=2;function dataObject(value2){if(value2===null||typeof value2!="object"||Array.isArray(value2))throw new Error("Expected object");let prototype=Object.getPrototypeOf(value2);if(prototype!==Object.prototype&&prototype!==null)throw new Error("Expected plain object");return value2}function field2(object2,key){let descriptor=Object.getOwnPropertyDescriptor(object2,key);if(descriptor&&!("value"in descriptor))throw new Error("Unexpected accessor");return descriptor?.value}function historyString(value2,bytes,exact=!1){if(typeof value2!="string")throw new Error("Expected string");if(exact&&(!value2||value2.length>bytes||Buffer.byteLength(value2)>bytes||value2.includes("\0")))throw new Error("Invalid identity or path");return boundText(value2,bytes)}function historyDetails(value2){let budget=BACKGROUND_DETAILS_BYTES;function copy(value3,depth){if(--budget<0||depth>32)throw new Error("History details too large");if(value3===null||typeof value3=="boolean"||typeof value3=="number"&&Number.isFinite(value3))return value3;if(typeof value3=="string"){if(budget-=value3.length,budget<0)throw new Error("History details too large");return value3}if(Array.isArray(value3)){if(value3.length>budget)throw new Error("History details too large");return Array.from({length:value3.length},(_2,index3)=>copy(field2(value3,String(index3)),depth+1))}let object2=dataObject(value3),out=Object.create(null);for(let key in object2)Object.hasOwn(object2,key)&&(budget-=key.length+3,out[key]=copy(field2(object2,key),depth+1));return out}try{return copy(value2,0)}catch{return}}function parseBackgroundHistory(record){try{let envelope=dataObject(record);if(field2(envelope,"version")!==BACKGROUND_HISTORY_VERSION)return;let source=dataObject(field2(envelope,"task")),kind=field2(source,"kind"),mode=field2(source,"mode"),status=field2(source,"status");if(kind!=="bash"&&kind!=="subagent"||mode!=="foreground"&&mode!=="background"||status!=="completed"&&status!=="partial"&&status!=="failed"&&status!=="cancelled"&&status!=="timeout")return;let startedAt=field2(source,"startedAt"),endedAt=field2(source,"endedAt");if(typeof startedAt!="number"||!Number.isSafeInteger(startedAt)||startedAt<0||typeof endedAt!="number"||!Number.isSafeInteger(endedAt)||endedAt<startedAt)return;let anchor=field2(source,"anchorId"),task={id:historyString(field2(source,"id"),512,!0),kind,mode,status,startedAt,endedAt,title:historyString(field2(source,"title"),BACKGROUND_TITLE_BYTES),toolCallId:historyString(field2(source,"toolCallId"),512,!0),anchorId:anchor===null?null:historyString(anchor,8192,!0)};if(!task.id.startsWith(`${kind}-`)||task.id.length<=kind.length+1)return;for(let[key,bytes]of[["command",8192],["cwd",4096],["error",4096],["outputPath",8192]]){let value2=field2(source,key);value2!==void 0&&(task[key]=historyString(value2,bytes,key==="outputPath"))}for(let key of["commandTruncated","resultTruncated"]){let value2=field2(source,key);if(value2!==void 0&&typeof value2!="boolean")return;task[key]=value2}let exitCode=field2(source,"exitCode");if(exitCode!==void 0){if(exitCode!==null&&(typeof exitCode!="number"||!Number.isSafeInteger(exitCode)))return;task.exitCode=exitCode}task.command!==void 0&&task.command!==field2(source,"command")&&(task.commandTruncated=!0);let projection=field2(source,"projection");projection!==void 0&&(task.projection=readBackgroundProjection(projection));let result2=field2(source,"result");if(result2!==void 0){let object2=dataObject(result2),blocks=field2(object2,"content");if(!Array.isArray(blocks))return;let content=[],remaining=BACKGROUND_RESULT_BYTES;for(let index3=0;index3<blocks.length&&remaining>0;index3++){let block=dataObject(field2(blocks,String(index3))),type=field2(block,"type");if(type!=="text"&&type!=="image")return;let original=type==="text"?field2(block,"text"):void 0,text2=type==="text"?historyString(original,remaining):"[Image omitted from background history]";text2!==original&&(task.resultTruncated=!0),content.push({type:"text",text:text2}),remaining-=Math.max(1,Buffer.byteLength(text2))}content.length<blocks.length&&(task.resultTruncated=!0),task.result=boundedResult({content,details:historyDetails(field2(object2,"details"))})}return task}catch{return}}var SUBAGENT_BACKGROUND_REJECTION="Background execution is not available inside subagents. Run this command with background: false (or omit background). Only the parent agent or the user can background the entire subagent invocation. No command was started.";function isBackgroundTerminal(status){return status!=="queued"&&status!=="running"&&status!=="stopping"}function isForegroundShellTask(task){return task.kind==="bash"&&task.mode==="foreground"}var BackgroundExecutionError=class extends Error{constructor(message,status){super(message),this.name="BackgroundExecutionError",this.status=status}};function errorText(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Background execution failed (unprintable error)"}}function storeResult(task,result2,truncated=!1){let bounded=boundedResult(result2);task.result=bounded,task.resultTruncated=truncated||bounded.content.length!==result2.content.length||bounded.content.some((block,index3)=>{let original=result2.content[index3];return original?.type!=="text"||block.type!=="text"||block.text!==original.text})}function oldestTask(tasks){let oldest;for(let task of tasks)(!oldest||task.endedAt<oldest.endedAt)&&(oldest=task);return oldest}var BackgroundService=class{get closed(){return this._closed}constructor(options={}){this.records=new Map,this.listeners=new Set,this._closed=!1,this.cleanups=new Set,this.pauses=0,this.options=options,this.configuredEnabled=options.enabled??!1,this.maxActive=Math.max(1,finiteLimit(options.maxActive,8,128)),this.maxHistory=finiteLimit(options.maxHistory,32,1024),this.maxRetained=this.maxActive+2*Math.max(1,this.maxHistory)+this.maxHistory}restoreHistory(records){if(this.closed)return;let history=this.historyRecords(),shells=history.filter(record=>isForegroundShellTask(record.task)).length,shellCapacity=Math.max(0,this.maxHistory-shells),taskCapacity=Math.max(0,this.maxHistory-(history.length-shells)),capacity=Math.max(0,Math.min(shellCapacity+taskCapacity,this.maxRetained-this.records.size-this.cleanups.size)),newest=new Map;for(let value2 of records){let task=parseBackgroundHistory(value2);if(!task)continue;let existing=this.records.get(task.id);if(existing){existing.settled&&(existing.visible=!0);continue}if(capacity===0)continue;let previous=newest.get(task.id);if(previous&&previous.endedAt>task.endedAt)continue;newest.delete(task.id);let shell=isForegroundShellTask(task),limit=shell?shellCapacity:taskCapacity;if(limit===0)continue;newest.set(task.id,task);let group=[...newest.values()].filter(candidate=>isForegroundShellTask(candidate)===shell);if(group.length>limit&&newest.delete(oldestTask(group).id),newest.size>capacity){let foreground=[...newest.values()].filter(isForegroundShellTask);newest.delete(oldestTask(foreground.length?foreground:newest.values()).id)}}for(let task of[...newest.values()].sort((a,b2)=>a.endedAt-b2.endedAt))this.records.set(task.id,{task,controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:!1,settled:!0,accounted:!0,visible:!0,suppressed:!0,delivery:"delivered",pins:0,waiters:new Set,removeParent:()=>{},handoff:()=>{},done:Promise.resolve()})}get enabled(){return this.configuredEnabled&&!this.closed&&this.options.role!=="subagent"}setEnabled(enabled){this.configuredEnabled=enabled,this.emit()}async execute(execution){if(this.options.role==="subagent")throw new Error(SUBAGENT_BACKGROUND_REJECTION);if(this.closed)throw new Error("Background service is closed");if(!this.enabled)throw new Error("Background execution is not available in this host");if(execution.signal?.aborted)throw execution.signal.reason??new Error("Execution aborted");if([...this.records.values()].filter(record2=>!record2.settled).length>=this.maxActive)throw new Error(`Background execution limit reached (${this.maxActive})`);if(this.records.size+this.cleanups.size>=this.maxRetained)throw new Error("Background history retention limit reached; deliver pending notifications or release pinned or claimed records");let anchorId=this.options.anchor?.()??null;if(anchorId!==null&&Buffer.byteLength(anchorId)>8192)throw new Error("Background branch anchor is too large");let task={id:`${execution.kind}-${randomUUID2()}`,kind:execution.kind,title:boundText(execution.title,BACKGROUND_TITLE_BYTES),toolCallId:boundText(execution.toolCallId,512),anchorId,mode:execution.background?"background":"foreground",status:"queued",startedAt:Date.now(),command:execution.command===void 0?void 0:boundText(execution.command,8192),commandTruncated:execution.command===void 0?void 0:boundText(execution.command,8192)!==execution.command,cwd:execution.cwd===void 0?void 0:boundText(execution.cwd,4096)},resolveCaller,rejectCaller,caller=new Promise((resolve17,reject)=>{resolveCaller=resolve17,rejectCaller=reject}),resolveDone,record={task,controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:execution.background??!1,settled:!1,accounted:!1,visible:!0,suppressed:!1,delivery:"pending",pins:0,waiters:new Set,removeParent:()=>{},handoff:()=>{!record.accepted||!record.detachRequested||record.settled||record.handedOff||this.closed||record.suppressed||record.controller.signal.aborted||(record.handedOff=!0,task.mode="background",record.removeParent(),resolveCaller({kind:"background",task:this.snapshot(record)}),this.emit())},done:new Promise(resolve17=>{resolveDone=resolve17})},parentSignal=execution.signal,onUpdate=execution.background?void 0:execution.onUpdate,parentAbort=()=>{(!record.detachRequested||!record.accepted)&&this.cancel(record)};parentSignal?.addEventListener("abort",parentAbort,{once:!0}),record.removeParent=()=>{parentSignal?.removeEventListener("abort",parentAbort),onUpdate=void 0},this.records.set(task.id,record);let control={id:task.id,signal:record.controller.signal,get mode(){return task.mode},accept:()=>{record.settled||record.accepted||this.closed||record.controller.signal.aborted||(record.accepted=!0,task.status==="queued"&&(task.status="running"),record.detachRequested&&record.removeParent(),queueMicrotask(()=>queueMicrotask(record.handoff)),this.emit())},publish:(result2,projection)=>{if(!(record.settled||this.closed)){if(storeResult(task,result2),result2.usage!==void 0&&(record.publishedUsage=structuredClone(result2.usage)),projection&&(task.projection=readBackgroundProjection(projection)),!record.detachRequested&&!record.handedOff)try{onUpdate?.(result2)}catch{}this.emit()}},setOutputPath:(path14,cleanup)=>{if(record.settled){if(cleanup)throw new Error("Background execution has settled");return}if(record.cleanup)throw new Error("Managed output is already registered");if(Buffer.byteLength(path14)>8192)throw new Error("Background output path is too large");record.cleanup=cleanup,task.outputPath=path14,this.emit()}},finish=(completion,error)=>{if(record.settled)return;record.settled=!0,record.removeParent(),task.endedAt=Date.now();let failed=completion===void 0;task.status=completion?.status??(error instanceof BackgroundExecutionError?error.status:record.controller.signal.aborted?"cancelled":failed?"failed":"completed"),completion&&(storeResult(task,completion.result),completion.error!==void 0&&(task.error=boundText(completion.error,4096)),completion.exitCode!==void 0&&(task.exitCode=completion.exitCode)),failed&&(task.error=errorText(error),storeResult(task,{content:[{type:"text",text:task.error},...task.result?.content??[]],details:task.result?.details},task.resultTruncated));let settlementWarning;try{this.options.onSettled?.(this.snapshot(record),completion?.usage??completion?.result.usage??record.publishedUsage)}catch(accountingError){let warning=`Usage settlement failed: ${errorText(accountingError)}`;settlementWarning=warning,task.error=boundText([task.error,warning].filter(Boolean).join(`
666
- `),8192),storeResult(task,{content:[{type:"text",text:warning},...task.result?.content??[]],details:task.result?.details},task.resultTruncated)}if(record.publishedUsage=void 0,record.accounted=!0,!record.handedOff)if(record.delivery="delivered",failed)rejectCaller(error);else{let{usage:_usage,...result2}=completion.result;settlementWarning&&(result2.content=[{type:"text",text:settlementWarning},...result2.content]),resolveCaller({kind:"result",result:result2,status:task.status,error:task.error})}for(let waiter of[...record.waiters])waiter();resolveDone(),this.trim(),this.emit()};try{let running=execution.run(control);Promise.resolve(running).then(result2=>finish(result2),error=>finish(void 0,error))}catch(error){finish(void 0,error)}return this.emit(),caller}detachForeground(){if(!this.enabled)return 0;let records=[...this.records.values()].filter(record=>!record.settled&&!record.detachRequested&&!record.controller.signal.aborted);for(let record of records)record.detachRequested=!0,record.task.mode="background",record.accepted&&record.removeParent();for(let record of records)record.handoff();return records.length&&this.emit(),records.length}list(){return[...this.records.values()].filter(record=>record.visible).map(record=>this.snapshot(record))}lookup(id){let exact=this.records.get(id);if(exact)return exact;let matches=[...this.records.values()].filter(({task})=>task.id.startsWith(id)||task.id.slice(task.kind.length+1).startsWith(id));if(!id||matches.length!==1)throw new Error(matches.length>1?"Ambiguous background task ID":"Unknown background task ID");return matches[0]}get(id){return this.snapshot(this.lookup(id))}async read(id,options={}){let record=this.lookup(id),release2=this.pin(record.task.id);try{let task=this.snapshot(record);if(task.outputPath)try{return{task,...await readOutputSlice(task.outputPath,options)}}catch(error){return{task,readError:boundText(`Output could not be read: ${errorText(error)}`,4096),...sliceText(this.resultText(task),options)}}return{task,readError:record.readError,...sliceText(this.resultText(task),options)}}finally{release2()}}resultText(task){return boundText(task.result?.content.filter(block=>block.type==="text").map(block=>block.text).join(`
665
+ `)+suffix}return prefix+modelText(snapshot.output??{text:"No text result.",truncated:!1},remaining,lines)+suffix}function backgroundCompletionMessage(task){let details=backgroundCompletionSnapshot(task);return{role:"custom",customType:"background-completion",display:!0,content:notificationText(details),details,timestamp:Date.now()}}var BACKGROUND_HISTORY_VERSION=2;function dataObject(value2){if(value2===null||typeof value2!="object"||Array.isArray(value2))throw new Error("Expected object");let prototype=Object.getPrototypeOf(value2);if(prototype!==Object.prototype&&prototype!==null)throw new Error("Expected plain object");return value2}function field2(object2,key){let descriptor=Object.getOwnPropertyDescriptor(object2,key);if(descriptor&&!("value"in descriptor))throw new Error("Unexpected accessor");return descriptor?.value}function historyString(value2,bytes,exact=!1){if(typeof value2!="string")throw new Error("Expected string");if(exact&&(!value2||value2.length>bytes||Buffer.byteLength(value2)>bytes||value2.includes("\0")))throw new Error("Invalid identity or path");return boundText(value2,bytes)}function historyDetails(value2){let budget=BACKGROUND_DETAILS_BYTES;function copy(value3,depth){if(--budget<0||depth>32)throw new Error("History details too large");if(value3===null||typeof value3=="boolean"||typeof value3=="number"&&Number.isFinite(value3))return value3;if(typeof value3=="string"){if(budget-=value3.length,budget<0)throw new Error("History details too large");return value3}if(Array.isArray(value3)){if(value3.length>budget)throw new Error("History details too large");return Array.from({length:value3.length},(_2,index3)=>copy(field2(value3,String(index3)),depth+1))}let object2=dataObject(value3),out=Object.create(null);for(let key in object2)Object.hasOwn(object2,key)&&(budget-=key.length+3,out[key]=copy(field2(object2,key),depth+1));return out}try{return copy(value2,0)}catch{return}}function parseBackgroundHistory(record){try{let envelope=dataObject(record);if(field2(envelope,"version")!==BACKGROUND_HISTORY_VERSION)return;let source=dataObject(field2(envelope,"task")),kind=field2(source,"kind"),mode=field2(source,"mode"),status=field2(source,"status");if(kind!=="bash"&&kind!=="subagent"||mode!=="foreground"&&mode!=="background"||status!=="completed"&&status!=="partial"&&status!=="failed"&&status!=="cancelled"&&status!=="timeout")return;let startedAt=field2(source,"startedAt"),endedAt=field2(source,"endedAt");if(typeof startedAt!="number"||!Number.isSafeInteger(startedAt)||startedAt<0||typeof endedAt!="number"||!Number.isSafeInteger(endedAt)||endedAt<startedAt)return;let anchor=field2(source,"anchorId"),task={id:historyString(field2(source,"id"),512,!0),kind,mode,status,startedAt,endedAt,title:historyString(field2(source,"title"),BACKGROUND_TITLE_BYTES),toolCallId:historyString(field2(source,"toolCallId"),512,!0),anchorId:anchor===null?null:historyString(anchor,8192,!0)};if(!task.id.startsWith(`${kind}-`)||task.id.length<=kind.length+1)return;for(let[key,bytes]of[["command",8192],["cwd",4096],["error",4096],["outputPath",8192]]){let value2=field2(source,key);value2!==void 0&&(task[key]=historyString(value2,bytes,key==="outputPath"))}for(let key of["commandTruncated","resultTruncated"]){let value2=field2(source,key);if(value2!==void 0&&typeof value2!="boolean")return;task[key]=value2}let exitCode=field2(source,"exitCode");if(exitCode!==void 0){if(exitCode!==null&&(typeof exitCode!="number"||!Number.isSafeInteger(exitCode)))return;task.exitCode=exitCode}task.command!==void 0&&task.command!==field2(source,"command")&&(task.commandTruncated=!0);let projection=field2(source,"projection");projection!==void 0&&(task.projection=readBackgroundProjection(projection));let result2=field2(source,"result");if(result2!==void 0){let object2=dataObject(result2),blocks=field2(object2,"content");if(!Array.isArray(blocks))return;let content=[],remaining=BACKGROUND_RESULT_BYTES;for(let index3=0;index3<blocks.length&&remaining>0;index3++){let block=dataObject(field2(blocks,String(index3))),type=field2(block,"type");if(type!=="text"&&type!=="image")return;let original=type==="text"?field2(block,"text"):void 0,text2=type==="text"?historyString(original,remaining):"[Image omitted from background history]";text2!==original&&(task.resultTruncated=!0),content.push({type:"text",text:text2}),remaining-=Math.max(1,Buffer.byteLength(text2))}content.length<blocks.length&&(task.resultTruncated=!0),task.result=boundedResult({content,details:historyDetails(field2(object2,"details"))})}return task}catch{return}}var SUBAGENT_BACKGROUND_REJECTION="Background execution is not available inside subagents. Run this command with background: false (or omit background). Only the parent agent or the user can background the entire subagent invocation. No command was started.";function isBackgroundTerminal(status){return status!=="queued"&&status!=="running"&&status!=="stopping"}function isForegroundShellTask(task){return task.kind==="bash"&&task.mode==="foreground"}var BackgroundExecutionError=class extends Error{constructor(message,status){super(message),this.name="BackgroundExecutionError",this.status=status}},BackgroundLookupError=class extends Error{constructor(kind,matches){super(kind==="ambiguous"?"Ambiguous background task ID":"Unknown background task ID"),this.name="BackgroundLookupError",this.kind=kind,this.matches=matches}};function errorText(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Background execution failed (unprintable error)"}}function storeResult(task,result2,truncated=!1){let bounded=boundedResult(result2);task.result=bounded,task.resultTruncated=truncated||bounded.content.length!==result2.content.length||bounded.content.some((block,index3)=>{let original=result2.content[index3];return original?.type!=="text"||block.type!=="text"||block.text!==original.text})}function oldestTask(tasks){let oldest;for(let task of tasks)(!oldest||task.endedAt<oldest.endedAt)&&(oldest=task);return oldest}var BackgroundService=class{get closed(){return this._closed}constructor(options={}){this.records=new Map,this.listeners=new Set,this._closed=!1,this.cleanups=new Set,this.pauses=0,this.options=options,this.configuredEnabled=options.enabled??!1,this.maxActive=Math.max(1,finiteLimit(options.maxActive,8,128)),this.maxHistory=finiteLimit(options.maxHistory,32,1024),this.maxRetained=this.maxActive+2*Math.max(1,this.maxHistory)+this.maxHistory}restoreHistory(records){if(this.closed)return;let history=this.historyRecords(),shells=history.filter(record=>isForegroundShellTask(record.task)).length,shellCapacity=Math.max(0,this.maxHistory-shells),taskCapacity=Math.max(0,this.maxHistory-(history.length-shells)),capacity=Math.max(0,Math.min(shellCapacity+taskCapacity,this.maxRetained-this.records.size-this.cleanups.size)),newest=new Map;for(let value2 of records){let task=parseBackgroundHistory(value2);if(!task)continue;let existing=this.records.get(task.id);if(existing){existing.settled&&(existing.visible=!0);continue}if(capacity===0)continue;let previous=newest.get(task.id);if(previous&&previous.endedAt>task.endedAt)continue;newest.delete(task.id);let shell=isForegroundShellTask(task),limit=shell?shellCapacity:taskCapacity;if(limit===0)continue;newest.set(task.id,task);let group=[...newest.values()].filter(candidate=>isForegroundShellTask(candidate)===shell);if(group.length>limit&&newest.delete(oldestTask(group).id),newest.size>capacity){let foreground=[...newest.values()].filter(isForegroundShellTask);newest.delete(oldestTask(foreground.length?foreground:newest.values()).id)}}for(let task of[...newest.values()].sort((a,b2)=>a.endedAt-b2.endedAt))this.records.set(task.id,{task,controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:!1,settled:!0,accounted:!0,visible:!0,suppressed:!0,delivery:"delivered",pins:0,waiters:new Set,removeParent:()=>{},handoff:()=>{},done:Promise.resolve()})}get enabled(){return this.configuredEnabled&&!this.closed&&this.options.role!=="subagent"}setEnabled(enabled){this.configuredEnabled=enabled,this.emit()}async execute(execution){if(this.options.role==="subagent")throw new Error(SUBAGENT_BACKGROUND_REJECTION);if(this.closed)throw new Error("Background service is closed");if(!this.enabled)throw new Error("Background execution is not available in this host");if(execution.signal?.aborted)throw execution.signal.reason??new Error("Execution aborted");if([...this.records.values()].filter(record2=>!record2.settled).length>=this.maxActive)throw new Error(`Background execution limit reached (${this.maxActive})`);if(this.records.size+this.cleanups.size>=this.maxRetained)throw new Error("Background history retention limit reached; deliver pending notifications or release pinned or claimed records");let anchorId=this.options.anchor?.()??null;if(anchorId!==null&&Buffer.byteLength(anchorId)>8192)throw new Error("Background branch anchor is too large");let task={id:`${execution.kind}-${randomUUID2()}`,kind:execution.kind,title:boundText(execution.title,BACKGROUND_TITLE_BYTES),toolCallId:boundText(execution.toolCallId,512),anchorId,mode:execution.background?"background":"foreground",status:"queued",startedAt:Date.now(),command:execution.command===void 0?void 0:boundText(execution.command,8192),commandTruncated:execution.command===void 0?void 0:boundText(execution.command,8192)!==execution.command,cwd:execution.cwd===void 0?void 0:boundText(execution.cwd,4096)},resolveCaller,rejectCaller,caller=new Promise((resolve17,reject)=>{resolveCaller=resolve17,rejectCaller=reject}),resolveDone,record={task,controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:execution.background??!1,settled:!1,accounted:!1,visible:!0,suppressed:!1,delivery:"pending",pins:0,waiters:new Set,removeParent:()=>{},handoff:()=>{!record.accepted||!record.detachRequested||record.settled||record.handedOff||this.closed||record.suppressed||record.controller.signal.aborted||(record.handedOff=!0,task.mode="background",record.removeParent(),resolveCaller({kind:"background",task:this.snapshot(record)}),this.emit())},done:new Promise(resolve17=>{resolveDone=resolve17})},parentSignal=execution.signal,onUpdate=execution.background?void 0:execution.onUpdate,parentAbort=()=>{(!record.detachRequested||!record.accepted)&&this.cancel(record)};parentSignal?.addEventListener("abort",parentAbort,{once:!0}),record.removeParent=()=>{parentSignal?.removeEventListener("abort",parentAbort),onUpdate=void 0},this.records.set(task.id,record);let control={id:task.id,signal:record.controller.signal,get mode(){return task.mode},accept:()=>{record.settled||record.accepted||this.closed||record.controller.signal.aborted||(record.accepted=!0,task.status==="queued"&&(task.status="running"),record.detachRequested&&record.removeParent(),queueMicrotask(()=>queueMicrotask(record.handoff)),this.emit())},publish:(result2,projection)=>{if(!(record.settled||this.closed)){if(storeResult(task,result2),result2.usage!==void 0&&(record.publishedUsage=structuredClone(result2.usage)),projection&&(task.projection=readBackgroundProjection(projection)),!record.detachRequested&&!record.handedOff)try{onUpdate?.(result2)}catch{}this.emit()}},setOutputPath:(path14,cleanup)=>{if(record.settled){if(cleanup)throw new Error("Background execution has settled");return}if(record.cleanup)throw new Error("Managed output is already registered");if(Buffer.byteLength(path14)>8192)throw new Error("Background output path is too large");record.cleanup=cleanup,task.outputPath=path14,this.emit()}},finish=(completion,error)=>{if(record.settled)return;record.settled=!0,record.removeParent(),task.endedAt=Date.now();let failed=completion===void 0;task.status=completion?.status??(error instanceof BackgroundExecutionError?error.status:record.controller.signal.aborted?"cancelled":failed?"failed":"completed"),completion&&(storeResult(task,completion.result),completion.error!==void 0&&(task.error=boundText(completion.error,4096)),completion.exitCode!==void 0&&(task.exitCode=completion.exitCode)),failed&&(task.error=errorText(error),storeResult(task,{content:[{type:"text",text:task.error},...task.result?.content??[]],details:task.result?.details},task.resultTruncated));let settlementWarning;try{this.options.onSettled?.(this.snapshot(record),completion?.usage??completion?.result.usage??record.publishedUsage)}catch(accountingError){let warning=`Usage settlement failed: ${errorText(accountingError)}`;settlementWarning=warning,task.error=boundText([task.error,warning].filter(Boolean).join(`
666
+ `),8192),storeResult(task,{content:[{type:"text",text:warning},...task.result?.content??[]],details:task.result?.details},task.resultTruncated)}if(record.publishedUsage=void 0,record.accounted=!0,!record.handedOff)if(record.delivery="delivered",failed)rejectCaller(error);else{let{usage:_usage,...result2}=completion.result;settlementWarning&&(result2.content=[{type:"text",text:settlementWarning},...result2.content]),resolveCaller({kind:"result",result:result2,status:task.status,error:task.error})}for(let waiter of[...record.waiters])waiter();resolveDone(),this.trim(),this.emit()};try{let running=execution.run(control);Promise.resolve(running).then(result2=>finish(result2),error=>finish(void 0,error))}catch(error){finish(void 0,error)}return this.emit(),caller}detachForeground(){if(!this.enabled)return 0;let records=[...this.records.values()].filter(record=>!record.settled&&!record.detachRequested&&!record.controller.signal.aborted);for(let record of records)record.detachRequested=!0,record.task.mode="background",record.accepted&&record.removeParent();for(let record of records)record.handoff();return records.length&&this.emit(),records.length}list(){return[...this.records.values()].filter(record=>record.visible).map(record=>this.snapshot(record))}lookup(id){let exact=this.records.get(id);if(exact)return exact;let matches=[...this.records.values()].filter(({task})=>task.id.startsWith(id)||task.id.slice(task.kind.length+1).startsWith(id));if(!id||matches.length!==1)throw new BackgroundLookupError(matches.length>1?"ambiguous":"unknown",matches.map(record=>this.snapshot(record)));return matches[0]}get(id){return this.snapshot(this.lookup(id))}async read(id,options={}){let record=this.lookup(id),release2=this.pin(record.task.id);try{let task=this.snapshot(record);if(task.outputPath)try{return{task,...await readOutputSlice(task.outputPath,options)}}catch(error){return{task,readError:boundText(`Output could not be read: ${errorText(error)}`,4096),...sliceText(this.resultText(task),options)}}return{task,readError:record.readError,...sliceText(this.resultText(task),options)}}finally{release2()}}resultText(task){return boundText(task.result?.content.filter(block=>block.type==="text").map(block=>block.text).join(`
667
667
  `)||task.projection?.text||task.error||"No output yet.")}async wait(id,timeoutMs=2e4,signal){if(signal?.aborted)throw signal.reason??new Error("Wait aborted");let record=this.lookup(id);return record.settled?this.snapshot(record):new Promise((resolve17,reject)=>{let finished=!1,timer,complete2=(aborted=!1)=>{finished||(finished=!0,timer!==void 0&&clearTimeout(timer),signal?.removeEventListener("abort",abort),record.waiters.delete(wake),aborted?reject(signal?.reason??new Error("Wait aborted")):resolve17(this.snapshot(record)),this.trim(),this.emit())},wake=()=>complete2(),abort=()=>complete2(!0);record.waiters.add(wake),signal?.addEventListener("abort",abort,{once:!0}),timer=setTimeout(wake,finiteLimit(timeoutMs,2e4,6e4)),this.closed&&wake()})}kill(id){return this.cancel(this.lookup(id))}cancel(record){return record.settled||record.controller.signal.aborted?!1:(record.task.status="stopping",record.controller.abort(),this.emit(),!0)}subscribe(listener){return this.closed?()=>{}:(this.listeners.add(listener),()=>{this.listeners.delete(listener)})}pin(id){let record=this.lookup(id);record.pins++;let released=!1;return()=>{released||(released=!0,record.pins--,this.trim(),!this.closed&&this.pauses===0&&this.candidate(record)&&this.emit())}}pause(){this.pauses++;let resumed=!1;return()=>{resumed||(resumed=!0,this.pauses--,this.emit())}}pendingNotifications(){return this.closed||this.pauses>0?[]:[...this.records.values()].filter(record=>this.candidate(record)).map(record=>this.snapshot(record))}candidate(record){return record.visible&&record.settled&&record.accounted&&record.handedOff&&!record.suppressed&&record.delivery==="pending"&&record.waiters.size===0&&record.pins===0}claimNotification(id){if(this.closed||this.pauses>0)return!1;let record=this.records.get(id);return!record||!this.candidate(record)?!1:(record.delivery="claimed",!0)}markDelivered(id){let record=this.records.get(id);record&&(record.delivery="delivered",this.trim())}releaseNotification(id){let record=this.records.get(id);!record||record.delivery!=="claimed"||(record.delivery="pending",this.trim(),this.emit())}close(){if(!this.closed){this._closed=!0,this.listeners.clear();for(let record of this.records.values()){record.suppressed=!0,record.removeParent(),this.cancel(record);for(let waiter of[...record.waiters])waiter()}this.trim()}}async shutdown(graceMs=2e3){this.close(),await this.drain([...this.records.values()],graceMs)}async cancelOutsideBranch(ancestors){for(let record of this.records.values())record.visible=record.task.anchorId===null||ancestors.has(record.task.anchorId),record.visible&&record.delivery==="pending"&&(record.suppressed=!1);let outside=[...this.records.values()].filter(record=>!record.visible);for(let record of outside)record.suppressed=!0;for(let record of outside)this.cancel(record);this.trim(),this.emit(),await this.drain(outside,2e3)}async drain(records,graceMs){let timer;try{await Promise.race([Promise.all(records.map(record=>record.done)).then(()=>Promise.all(this.cleanups)),new Promise(resolve17=>{timer=setTimeout(resolve17,finiteLimit(graceMs,2e3,6e4))})])}finally{timer!==void 0&&clearTimeout(timer)}}snapshot(record){return structuredClone(record.task)}cleanupOutput(record){if(!record.settled||record.pins||record.waiters.size||!record.cleanup)return;let cleanup=record.cleanup;record.cleanup=void 0,record.task.outputPath=void 0,record.readError="Output has expired: the managed log was released; showing the stored result.";let pending=Promise.resolve().then(cleanup).catch(error=>{try{this.options.onCleanupError?.(errorText(error))}catch{}}).finally(()=>this.cleanups.delete(pending));this.cleanups.add(pending)}historyRecords(){return[...this.records.values()].filter(record=>record.settled&&record.delivery==="delivered"&&!record.pins&&!record.waiters.size)}trim(){if(this.closed){for(let record of this.records.values())this.cleanupOutput(record);return}let history=this.historyRecords(),expired=history.filter(record=>!record.visible);for(let shell of[!1,!0]){let group=history.filter(record=>record.visible&&isForegroundShellTask(record.task)===shell);group.sort((left,right)=>(left.task.endedAt??0)-(right.task.endedAt??0)),expired.push(...group.slice(0,Math.max(0,group.length-this.maxHistory)))}for(let record of expired)this.records.delete(record.task.id),this.cleanupOutput(record)}emit(){if(!this.closed)for(let listener of[...this.listeners]){if(this.closed)break;try{listener()}catch{}}}};var import_yaml=__toESM(require_dist(),1);var normalizeNewlines=value2=>value2.replace(/\r\n/g,`
668
668
  `).replace(/\r/g,`
669
669
  `),extractFrontmatter=content=>{let normalized=normalizeNewlines(stripBom(content));if(!normalized.startsWith("---"))return{yamlString:null,body:normalized};let endIndex=normalized.indexOf(`
@@ -1123,13 +1123,13 @@ ${instructions}`}],timestamp:Date.now()}],maxTokens=Math.min(4096,model.maxToken
1123
1123
  Received arguments:
1124
1124
  `,HINT_MARKER=`
1125
1125
 
1126
- Hint: `,RECEIVED_ARGUMENTS_MAX_BYTES=2*1024,RECEIVED_ARGUMENTS_MAX_LINES=40,FIELD_HINTS_MAX=10;function isRecord3(value2){return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)}function collectFieldHints(schema,args){let hints=[],visit=(node,value2,path14)=>{if(hints.length>=FIELD_HINTS_MAX||!isRecord3(node))return;if(node.type==="array"&&Array.isArray(value2)){for(let index3=0;index3<value2.length;index3++)visit(node.items,value2[index3],`${path14}[${index3}]`);return}if(node.type!=="object"||!isRecord3(value2))return;let properties=isRecord3(node.properties)?node.properties:{},fields=Object.keys(properties),where=path14||"root";if(node.additionalProperties===!1){for(let[key,entry]of Object.entries(value2))if(entry!==null&&!(key in properties)&&hints.length<FIELD_HINTS_MAX){let subject=path14?`${path14}.${key}`:key;hints.push(`${subject} is not a field; fields at ${where}: ${fields.join(", ")}`)}}if(Array.isArray(node.required)){for(let key of node.required)if(typeof key=="string"&&value2[key]===void 0&&hints.length<FIELD_HINTS_MAX){let subject=path14?`${path14}.${key}`:key;hints.push(`${subject} is required; fields at ${where}: ${fields.join(", ")}`)}}for(let key of fields)value2[key]!==void 0&&value2[key]!==null&&visit(properties[key],value2[key],path14?`${path14}.${key}`:key)};return visit(schema,args,""),hints}function enrichValidationError(error,parameters,args){let message=error instanceof Error?error.message:String(error);if(message.includes(HINT_MARKER))return error instanceof Error?error:new Error(message);let hints=collectFieldHints(parameters,args),markerIndex=message.indexOf(RECEIVED_ARGUMENTS_MARKER),head=markerIndex===-1?message:message.slice(0,markerIndex),received=markerIndex===-1?"":message.slice(markerIndex+RECEIVED_ARGUMENTS_MARKER.length),enriched=hints.length>0?`${head}
1126
+ Hint: `,RECEIVED_ARGUMENTS_MAX_BYTES=2*1024,RECEIVED_ARGUMENTS_MAX_LINES=40,FIELD_HINTS_MAX=10;function isRecord3(value2){return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)}function collectFieldHints(schema,args){let hints=[],visit=(node,value2,path14)=>{if(hints.length>=FIELD_HINTS_MAX||!isRecord3(node))return;if(Array.isArray(node.anyOf)){let variants=node.anyOf.filter(variant=>!isRecord3(variant)||variant.type!=="null");value2!==null&&variants.length===1&&visit(variants[0],value2,path14);return}if(node.type==="array"&&Array.isArray(value2)){for(let index3=0;index3<value2.length;index3++)visit(node.items,value2[index3],`${path14}[${index3}]`);return}if(node.type!=="object"||!isRecord3(value2))return;let properties=isRecord3(node.properties)?node.properties:{},fields=Object.keys(properties),where=path14||"root";if(node.additionalProperties===!1){for(let[key,entry]of Object.entries(value2))if(entry!==null&&!(key in properties)&&hints.length<FIELD_HINTS_MAX){let subject=path14?`${path14}.${key}`:key;hints.push(`${subject} is not a field; fields at ${where}: ${fields.join(", ")}`)}}if(Array.isArray(node.required)){for(let key of node.required)if(typeof key=="string"&&value2[key]===void 0&&hints.length<FIELD_HINTS_MAX){let subject=path14?`${path14}.${key}`:key;hints.push(`${subject} is required; fields at ${where}: ${fields.join(", ")}`)}}for(let key of fields)value2[key]!==void 0&&value2[key]!==null&&visit(properties[key],value2[key],path14?`${path14}.${key}`:key)};return visit(schema,args,""),hints}function enrichValidationError(error,parameters,args){let message=error instanceof Error?error.message:String(error);if(message.includes(HINT_MARKER))return error instanceof Error?error:new Error(message);let hints=collectFieldHints(parameters,args),markerIndex=message.indexOf(RECEIVED_ARGUMENTS_MARKER),head=markerIndex===-1?message:message.slice(0,markerIndex),received=markerIndex===-1?"":message.slice(markerIndex+RECEIVED_ARGUMENTS_MARKER.length),enriched=hints.length>0?`${head}
1127
1127
 
1128
1128
  Hint: ${hints.join(`
1129
1129
  Hint: `)}`:head;if(markerIndex!==-1){let bounded=truncateHead(received,{maxBytes:RECEIVED_ARGUMENTS_MAX_BYTES,maxLines:RECEIVED_ARGUMENTS_MAX_LINES});enriched+=`${RECEIVED_ARGUMENTS_MARKER}${bounded.content}`,bounded.truncated&&(enriched+=`
1130
1130
  \u2026 (arguments truncated)`)}return new Error(enriched)}function wrapPrepareArguments(definition){let tool={name:definition.name,description:definition.description,parameters:definition.parameters};return raw=>{let args=definition.prepareArguments?definition.prepareArguments(raw):raw;try{validateToolArguments(tool,{type:"toolCall",id:"",name:definition.name,arguments:args})}catch(error){throw enrichValidationError(error,definition.parameters,args)}return args}}function wrapToolDefinition(definition,ctxFactory){return{name:definition.name,label:definition.label,description:definition.description,parameters:definition.parameters,constrainedSampling:definition.constrainedSampling,toolGroup:definition.toolGroup,prepareArguments:wrapPrepareArguments(definition),executionMode:definition.executionMode,execute:(toolCallId,params,signal,onUpdate,ctx)=>definition.execute(toolCallId,params,signal,onUpdate,ctx??ctxFactory?.())}}function createToolDefinitionFromAgentTool(tool){return{name:tool.name,label:tool.label,description:tool.description,parameters:tool.parameters,constrainedSampling:tool.constrainedSampling,toolGroup:tool.toolGroup,prepareArguments:tool.prepareArguments,executionMode:tool.executionMode,execute:async(toolCallId,params,signal,onUpdate)=>tool.execute(toolCallId,params,signal,onUpdate)}}function wrapRegisteredTool(registeredTool,runner){return wrapToolDefinition(registeredTool.definition,()=>runner.createContext())}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import*as fs5 from"node:fs";import{createRequire as createRequire4}from"node:module";import*as path7 from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import{spawn as spawn3}from"node:child_process";async function execCommand(command,args,cwd,options){return new Promise(resolve17=>{let proc=spawn3(command,args,{cwd,shell:!1,stdio:["ignore","pipe","pipe"]}),stdout="",stderr="",killed=!1,timeoutId,killProcess=()=>{killed||(killed=!0,proc.kill("SIGTERM"),setTimeout(()=>{proc.killed||proc.kill("SIGKILL")},5e3))};options?.signal&&(options.signal.aborted?killProcess():options.signal.addEventListener("abort",killProcess,{once:!0})),options?.timeout&&options.timeout>0&&(timeoutId=setTimeout(()=>{killProcess()},options.timeout)),proc.stdout?.on("data",data=>{stdout+=data.toString()}),proc.stderr?.on("data",data=>{stderr+=data.toString()}),waitForChildProcess(proc).then(code=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve17({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve17({stdout,stderr,code:1,killed})})})}var ENABLED=process.env.PI_TIMING==="1",timingNamespaces=new Map;function resetTimings(namespace="main"){ENABLED&&timingNamespaces.set(namespace,{timings:[],lastTime:Date.now()})}function time(label,namespace="main"){if(!ENABLED)return;let now=Date.now();timingNamespaces.has(namespace)||resetTimings(namespace);let timingNamespace=timingNamespaces.get(namespace);timingNamespace.timings.push({label,ms:now-timingNamespace.lastTime}),timingNamespace.lastTime=now}function printTimingGroup(title,timings){let printableTimings=timings.filter(timing=>timing.ms>=0);if(printableTimings.length!==0){console.error(`
1131
1131
  --- ${title} ---`);for(let t of printableTimings)console.error(` ${t.label}: ${t.ms}ms`);console.error(` TOTAL: ${printableTimings.reduce((a,b2)=>a+b2.ms,0)}ms`),console.error(`${"-".repeat(title.length+8)}
1132
- `)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire4(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-NDGCHNG7.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],assertActive:()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??STALE_EXTENSION_CONTEXT_MESSAGE;for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){assertActive(),extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value2]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value2);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=extensionPath.startsWith("<")&&extensionPath.endsWith(">")?extensionPath.slice(1,-1).split(":")[0]||"temporary":"local",baseDir=extensionPath.startsWith("<")?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err2){return{extension:null,error:`Failed to load extension: ${err2 instanceof Error?err2.message:String(err2)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId2){return this.runtime.getModel(provider,modelId2)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}import{constants as constants2}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn4}from"child_process";import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";function ansiRegex({onlyFirst=!1}={}){let pattern="(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";return new RegExp(pattern,onlyFirst?void 0:"g")}var regex=ansiRegex();function stripAnsi(value2){if(typeof value2!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value2}\``);return!value2.includes("\x1B")&&!value2.includes("\x9B")?value2:value2.replace(regex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value2){return typeof value2=="string"?value2:value2==null?"":null}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
1132
+ `)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire4(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path7.extname(fileURLToPath5(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-CLT3YR3B.js"):import("./jiti-loader-BFSSLU7G.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-W3OGMIX7.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname2=path7.dirname(fileURLToPath5(import.meta.url)),packageIndex=path7.resolve(__dirname2,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),resolveImport=specifier=>fileURLToPath5(import.meta.resolve(specifier)),piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveImport("@earendil-works/pi-agent-core"),piTuiEntry=resolveImport("@earendil-works/pi-tui"),piAiCompatEntry=resolveImport("@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveImport("@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveImport("@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,[DISTRIBUTION_PACKAGE_NAME]:piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],assertActive:()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??STALE_EXTENSION_CONTEXT_MESSAGE;for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)}};return runtime}function createExtensionAPI(extension,runtime,cwd,eventBus){let pendingFlagValues=new Map,pendingRuntimeChanges=[],loadingUnsubscribers=[],state2="loading",assertActive=()=>{if(state2==="failed")throw new Error(`Extension "${extension.path}" failed to load and its API is no longer active.`);runtime.assertActive()},applyRuntimeChange=change=>{state2==="loading"?pendingRuntimeChanges.push(change):change()},clearPending=()=>{pendingFlagValues.clear(),pendingRuntimeChanges.length=0,loadingUnsubscribers.length=0};return{api:{on(event,handler){assertActive();let registeredHandler=(...args)=>handler(...args),list2=extension.handlers.get(event)??[];return list2.push(registeredHandler),extension.handlers.set(event,list2),()=>{let handlers=extension.handlers.get(event);if(!handlers)return;let handlerIndex=handlers.indexOf(registeredHandler);handlerIndex!==-1&&(handlers.splice(handlerIndex,1),handlers.length===0&&extension.handlers.delete(event))}},registerTool(tool){if(assertActive(),typeof tool.parameters!="object"||tool.parameters===null||Array.isArray(tool.parameters))throw new Error(`Tool "${tool.name}" registered by extension "${extension.path}" must define an object parameter schema.`);extension.tools.set(tool.name,{definition:tool,sourceInfo:extension.sourceInfo}),runtime.refreshTools()},registerCommand(name,options){assertActive(),extension.commands.set(name,{name,sourceInfo:extension.sourceInfo,...options})},registerShortcut(shortcut,options){assertActive(),extension.shortcuts.set(shortcut,{shortcut,extensionPath:extension.path,...options})},registerFlag(name,options){if(assertActive(),options.default!==void 0&&typeof options.default!==options.type)throw new Error(`Invalid default for flag "${name}": expected ${options.type}, got ${typeof options.default}`);extension.flags.set(name,{name,extensionPath:extension.path,...options}),options.default!==void 0&&!runtime.flagValues.has(name)&&(state2==="loading"?pendingFlagValues.has(name)||pendingFlagValues.set(name,options.default):runtime.flagValues.set(name,options.default))},registerMessageRenderer(customType,renderer){assertActive(),extension.messageRenderers.set(customType,renderer)},registerMarkdownTransformer(transformer){assertActive(),extension.markdownTransformer=transformer},registerEntryRenderer(customType,renderer){assertActive(),extension.entryRenderers??=new Map,extension.entryRenderers.set(customType,renderer)},getFlag(name){if(assertActive(),!!extension.flags.has(name))return runtime.flagValues.has(name)?runtime.flagValues.get(name):pendingFlagValues.get(name)},sendMessage(message,options){assertActive(),runtime.sendMessage(message,options)},sendUserMessage(content,options){assertActive(),runtime.sendUserMessage(content,options)},appendEntry(customType,data){assertActive(),runtime.appendEntry(customType,data)},setSessionName(name){assertActive(),runtime.setSessionName(name)},getSessionName(){return assertActive(),runtime.getSessionName()},setLabel(entryId,label){assertActive(),runtime.setLabel(entryId,label)},exec(command,args,options){return assertActive(),execCommand(command,args,options?.cwd??cwd,options)},getActiveTools(){return assertActive(),runtime.getActiveTools()},getAllTools(){return assertActive(),runtime.getAllTools()},setActiveTools(toolNames){assertActive(),runtime.setActiveTools(toolNames)},getCommands(){return assertActive(),runtime.getCommands()},setModel(model){return assertActive(),runtime.setModel(model)},getThinkingLevel(){return assertActive(),runtime.getThinkingLevel()},setThinkingLevel(level){assertActive(),runtime.setThinkingLevel(level)},registerProvider(providerOrName,config){if(assertActive(),typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");applyRuntimeChange(()=>runtime.registerProvider(providerOrName,config,extension.path));return}applyRuntimeChange(()=>runtime.registerNativeProvider(providerOrName,extension.path))},unregisterProvider(name){assertActive(),applyRuntimeChange(()=>runtime.unregisterProvider(name,extension.path))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value2]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value2);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let createJitiImpl=await getCreateJiti(),resolutionOptions=usesEmbeddedModules?{virtualModules:await getVirtualModules(),tryNative:!1}:isTypeScriptSourceRuntime?{virtualModules:await getVirtualModules(),tsconfigPaths:!0}:{alias:getAliases()},factory=await createJitiImpl(import.meta.url,{moduleCache:!1,...resolutionOptions}).import(extensionPath,{default:!0});if(typeof factory=="function")return isCurrentCacheToken(cacheToken)&&extensionCache.set(extensionPath,factory),factory}function createExtension(extensionPath,resolvedPath){let source=extensionPath.startsWith("<")&&extensionPath.endsWith(">")?extensionPath.slice(1,-1).split(":")[0]||"temporary":"local",baseDir=extensionPath.startsWith("<")?void 0:path7.dirname(resolvedPath);return{path:extensionPath,resolvedPath,sourceInfo:createSyntheticSourceInfo(extensionPath,{source,baseDir}),handlers:new Map,tools:new Map,messageRenderers:new Map,entryRenderers:new Map,commands:new Map,flags:new Map,shortcuts:new Map}}async function initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime){let extension=createExtension(extensionPath,resolvedPath),load=createExtensionAPI(extension,runtime,cwd,eventBus);try{await factory(load.api),load.commit()}catch(error){throw load.discard(),error}return time(`${extensionPath} factory`,"extensions"),extension}async function loadExtension(extensionPath,cwd,eventBus,runtime,cacheToken){let resolvedPath=resolvePath(extensionPath,cwd,{normalizeUnicodeSpaces:!0});try{let factory=await loadExtensionModule(resolvedPath,cacheToken);return time(`${extensionPath} module import`,"extensions"),factory?{extension:await initializeExtension(factory,extensionPath,resolvedPath,cwd,eventBus,runtime),error:null}:{extension:null,error:`Extension does not export a valid factory function: ${extensionPath}`}}catch(err2){return{extension:null,error:`Failed to load extension: ${err2 instanceof Error?err2.message:String(err2)}`}}}async function loadExtensionFromFactory(factory,cwd,eventBus,runtime,extensionPath="<inline>"){let resolvedCwd=resolvePath(cwd);return initializeExtension(factory,extensionPath,extensionPath,resolvedCwd,eventBus,runtime)}async function loadExtensionsInternal(paths,cwd,eventBus,runtime,useCache=!1){let extensions=[],errors=[],cacheToken=useCache?useExtensionCacheCwd(cwd):void 0,resolvedCwd=cacheToken?.cwd??resolvePath(cwd),resolvedEventBus=eventBus??createEventBus(),resolvedRuntime=runtime??createExtensionRuntime();for(let extPath of paths){let{extension,error}=await loadExtension(extPath,resolvedCwd,resolvedEventBus,resolvedRuntime,cacheToken);if(error){errors.push({path:extPath,error});continue}extension&&extensions.push(extension)}return{extensions,errors,runtime:resolvedRuntime}}async function loadExtensions(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime)}async function loadExtensionsCached(paths,cwd,eventBus,runtime){return loadExtensionsInternal(paths,cwd,eventBus,runtime,!0)}function isExtensionFile(name){return name.endsWith(".ts")||name.endsWith(".js")}function resolveExtensionEntries2(dir){let packageJsonPath=path7.join(dir,"package.json");if(fs5.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path7.resolve(dir,extPath);fs5.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path7.join(dir,"index.ts"),indexJs=path7.join(dir,"index.js");return fs5.existsSync(indexTs)?[indexTs]:fs5.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs5.existsSync(dir))return[];let discovered=[];try{let entries=fs5.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path7.join(dir,entry.name);if((entry.isFile()||entry.isSymbolicLink())&&isExtensionFile(entry.name)){discovered.push(entryPath);continue}if(entry.isDirectory()||entry.isSymbolicLink()){let entries2=resolveExtensionEntries2(entryPath);entries2&&discovered.push(...entries2)}}}catch{return[]}return discovered}async function discoverAndLoadExtensions(configuredPaths,cwd,agentDir=getAgentDir(),eventBus){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),allPaths=[],seen=new Set,addPaths=paths=>{for(let p of paths){let resolved=path7.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path7.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path7.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs5.existsSync(resolved)&&fs5.statSync(resolved).isDirectory()){let entries=resolveExtensionEntries2(resolved);if(entries){addPaths(entries);continue}addPaths(discoverExtensionsInDir(resolved));continue}addPaths([resolved])}return loadExtensions(allPaths,resolvedCwd,eventBus)}var ModelRegistry=class{constructor(runtime){this.runtime=runtime}getRuntime(){return this.runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(provider,modelId2){return this.runtime.getModel(provider,modelId2)}hasConfiguredAuth(model){return this.runtime.hasConfiguredAuth(model.provider)}async getApiKeyAndHeaders(model){try{let resolution=await this.runtime.getAuth(model);if(!resolution){let compatibility=this.runtime.getCompatibilityRequestConfig(model);return compatibility.authHeader?{ok:!1,error:`No API key found for "${model.provider}"`}:{ok:!0,headers:compatibility.headers}}return{ok:!0,apiKey:resolution.auth.apiKey,headers:resolution.auth.headers,...resolution.auth.baseUrl?{baseUrl:resolution.auth.baseUrl}:{},env:resolution.env}}catch(error){let cause=error instanceof Error?error.cause:void 0,message=cause instanceof Error?cause.message:error instanceof Error?error.message:String(error);return{ok:!1,error:message==="authHeader requires a resolved API key"?`No API key found for "${model.provider}"`:message}}}getProviderAuthStatus(provider){return this.runtime.getProviderAuthStatus(provider)}getProvider(provider){return this.runtime.getProvider(provider)}stream(model,context,options){return this.runtime.stream(model,context,options)}streamSimple(model,context,options){return this.runtime.streamSimple(model,context,options)}complete(model,context,options){return this.runtime.complete(model,context,options)}getProviderDisplayName(provider){return this.runtime.getProvider(provider)?.name??provider}getProviderAuth(provider){return this.runtime.getAuth(provider)}async getApiKeyForProvider(provider){try{return(await this.runtime.getAuth(provider))?.auth.apiKey}catch{return}}isUsingOAuth(model){return this.runtime.isUsingOAuth(model.provider)}registerProvider(providerOrName,config){if(typeof providerOrName=="string"){if(!config)throw new Error("Provider config is required when registering by name");this.runtime.registerProvider(providerOrName,config);return}this.runtime.registerNativeProvider(providerOrName)}unregisterProvider(providerName){this.runtime.unregisterProvider(providerName)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0){if(!text2)return{visualLines:[],skippedCount:0};let allVisualLines=new Text(text2,paddingX,0).render(width);if(allVisualLines.length<=maxVisualLines)return{visualLines:allVisualLines,skippedCount:0};let truncatedLines=allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}import{constants as constants2}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn4}from"child_process";import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";function ansiRegex({onlyFirst=!1}={}){let pattern="(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";return new RegExp(pattern,onlyFirst?void 0:"g")}var regex=ansiRegex();function stripAnsi(value2){if(typeof value2!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value2}\``);return!value2.includes("\x1B")&&!value2.includes("\x9B")?value2:value2.replace(regex,"")}function shortenPath2(path14){if(typeof path14!="string")return"";let home=os4.homedir();return path14.startsWith(home)?`~${path14.slice(home.length)}`:path14}function linkPath(styledText,rawPath,cwd){if(!getCapabilities().hyperlinks)return styledText;let absolutePath=resolvePath(rawPath,cwd);return hyperlink(styledText,pathToFileURL2(absolutePath).href)}function str(value2){return typeof value2=="string"?value2:value2==null?"":null}function replaceTabs(text2){return text2.replace(/\t/g," ")}function normalizeDisplayText(text2){return text2.replace(/\r/g,"")}function getTextOutput(result2,showImages){if(!result2)return"";let textBlocks=result2.content.filter(c=>c.type==="text"),imageBlocks=result2.content.filter(c=>c.type==="image"),output=textBlocks.map(c=>sanitizeBinaryOutput(stripAnsi(c.text||"")).replace(/\r/g,"")).join(`
1133
1133
  `),caps=getCapabilities();if(imageBlocks.length>0&&(!caps.images||!showImages)){let imageIndicators=imageBlocks.map(img=>{let mimeType=img.mimeType??"image/unknown",dims=img.data&&img.mimeType?getImageDimensions(img.data,img.mimeType)??void 0:void 0;return imageFallback(mimeType,dims)}).join(`
1134
1134
  `);output=output?`${output}
1135
1135
  ${imageIndicators}`:imageIndicators}return output}function invalidArgText(theme2){return theme2.fg("error","[invalid arg]")}function renderToolPath(rawPath,theme2,cwd,options){if(rawPath===null)return invalidArgText(theme2);let value2=rawPath||options?.emptyFallback;return value2?linkPath(theme2.fg("accent",shortenPath2(value2)),value2,cwd):theme2.fg("toolOutput","...")}function collapsedLinesHint(theme2,hidden,direction,options){let totalSuffix=options?.total!==void 0?`, ${options.total} total`:"",noun=hidden===1?"line":"lines";return theme2.fg("muted",`\u2026 (${hidden} ${direction} ${noun}${totalSuffix},`)+` ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}var BASH_PREVIEW_LINES=5,BASH_UPDATE_THROTTLE_MS=100,BashCallRenderComponent=class{constructor(config){this.command="",this.expanded=!1,this.config=config}update(args,expanded){let command=str(args?.command),timeout=args?.timeout;this.command===command&&this.timeout===timeout&&this.expanded===expanded||(this.command=command,this.timeout=timeout,this.expanded=expanded,this.invalidate())}render(width){return(this.cachedLines===void 0||this.cachedWidth!==width)&&(this.cachedLines=this.renderLines(Math.max(1,width)),this.cachedWidth=width),this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}renderLines(width){let fullCall=formatFullShellCall(this.command,this.timeout,this.config),fullLines=new Text(fullCall,0,0).render(width);return this.expanded||fullLines.length<=1?fullLines:[formatTruncatedShellCall(this.command,this.timeout,width,this.config)]}},BashResultRenderComponent=class extends Container{constructor(){super(...arguments),this.state={cachedWidth:void 0,cachedLines:void 0,cachedSkipped:void 0}}};function formatShellPrompt(prompt){return theme.fg("toolTitle",theme.bold(`${prompt} `))}function formatShellTimeout(timeout){return timeout?theme.fg("muted",` (timeout ${timeout}s)`):""}function styleShellCommand(command,config){let language=config.name==="powershell"?"powershell":"bash";return highlightCode(command,language).join(`
@@ -1495,16 +1495,16 @@ changes anytime in settings.json.`),1,0)),this.addChild(new Spacer(1)),this.addO
1495
1495
  ${message}`,[{label:"Yes",value:!0},{label:"No",value:!1}])??!1,input:async(title,placeholder)=>{if(options.hasUI&&options.mode==="interactive")return showStartupInput(options.settingsManager,title,placeholder)},notify:(message,type="info")=>{if(options.mode!=="interactive"){let color2=type==="error"?source_default.red:type==="warning"?source_default.yellow:source_default.cyan;console.error(color2(message))}}}}}async function selectSession(currentSessionsLoader,allSessionsLoader,settingsManager){let ui=await createStartupTui(settingsManager);return new Promise(resolve17=>{let keybindings=KeybindingsManager2.create();setKeybindings(keybindings);let resolved=!1,selector=new SessionSelectorComponent(currentSessionsLoader,allSessionsLoader,path14=>{resolved||(resolved=!0,ui.stop(),resolve17(path14))},()=>{resolved||(resolved=!0,ui.stop(),resolve17(null))},()=>{ui.stop(),process.exit(0)},()=>ui.requestRender(),{showRenameHint:!1,keybindings});ui.addChild(selector),ui.setFocus(selector.getSessionList()),startStartupTui(ui,settingsManager)})}function formatProjectTrustPrompt(cwd){return`Trust project folder?
1496
1496
  ${cwd}
1497
1497
 
1498
- This allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`}async function selectProjectTrustOption(cwd,ctx){let options=getProjectTrustOptions(cwd,{includeSessionOnly:!0}),selected=await ctx.ui.select(formatProjectTrustPrompt(cwd),options.map(option=>option.label));return options.find(option=>option.label===selected)}function saveProjectTrustPromptResult(trustStore,result2){result2.updates.length>0&&trustStore.setMany(result2.updates)}async function resolveProjectTrusted(options){if(options.trustOverride!==void 0)return options.trustOverride;if(!hasTrustRequiringProjectResources(options.cwd))return!0;if(options.extensionsResult){let{result:result2,errors}=await emitProjectTrustEvent(options.extensionsResult,{type:"project_trust",cwd:options.cwd},options.projectTrustContext);for(let error of errors)options.onExtensionError?.(`Extension "${error.extensionPath}" project_trust error: ${error.error}`);if(result2){let trusted=result2.trusted==="yes";return result2.remember===!0&&options.trustStore.set(options.cwd,trusted),trusted}}let decision=options.trustStore.get(options.cwd);if(decision!==null)return decision;switch(options.defaultProjectTrust??"ask"){case"always":return!0;case"never":return!1;case"ask":break}if(!options.projectTrustContext.hasUI)return!1;let selected=await selectProjectTrustOption(options.cwd,options.projectTrustContext);return selected!==void 0?(saveProjectTrustPromptResult(options.trustStore,selected),selected.trusted):!1}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path14,error})=>({type:"warning",message:path14?`Invalid settings file ${path14}: ${error.message}`:`Invalid ${scope} settings: ${error.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic=>{let key=`${diagnostic.type}\0${diagnostic.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}registerKeybindings({"app.backgroundTasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground Bash and Subagent executions to the background"},"app.backgroundTasks.focusList":{defaultKeys:"left",description:"Focus the background task list"},"app.backgroundTasks.focusPreview":{defaultKeys:"right",description:"Focus the background task preview"},"app.backgroundTasks.kill":{defaultKeys:"k",description:"Kill selected background task"},"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"}});var BG_NOTIFICATION_TYPE="background-task",BG_COMPLETION_TYPE="background-completion";var bgSchema=typebox_exports.Object({action:StringEnum(["read","wait","kill","list"],{description:"Which background-task operation to perform"}),taskId:typebox_exports.Optional(typebox_exports.String({description:"Bash task or Subagent group id (read/wait/kill)"})),mode:typebox_exports.Optional(StringEnum(["tail","head"],{description:"Read from the end (default) or the start of the output (read)"})),bytes:typebox_exports.Optional(typebox_exports.Number({description:`Max bytes to return (read, default ${formatSize(8192)}, max ${formatSize(51200)})`})),waitMs:typebox_exports.Optional(typebox_exports.Number({description:`Max time to wait in ms, default ${2e4}, max ${6e4} (wait)`})),sinceBytes:typebox_exports.Optional(typebox_exports.Number({description:"Only return output written after this byte offset \u2014 take it from a previous read/wait result (wait)"}))});function requireTaskId(input2){let taskId=input2.taskId;if(!taskId||taskId.trim().length===0)throw new Error(`action '${input2.action}' requires 'taskId' \u2014 use action list to find the execution id.`);return taskId}function clampReadBytes(bytes){let value2=bytes!==void 0&&Number.isFinite(bytes)?bytes:8192;return Math.min(51200,Math.max(256,Math.floor(value2)))}function clampWaitMs(waitMs){let value2=waitMs!==void 0&&Number.isFinite(waitMs)?waitMs:2e4;return Math.min(6e4,Math.max(1e3,Math.floor(value2)))}function clampSinceBytes(sinceBytes){return sinceBytes===void 0||!Number.isFinite(sinceBytes)?void 0:Math.max(0,Math.floor(sinceBytes))}var BG_TOOL_DESCRIPTION="Inspect and control backgrounded work: Bash tasks and Subagent groups started with background: true. Completion is delivered to you automatically as a notification \u2014 never poll. list: bounded activity/history listing; find task IDs here. read: bounded output or report slice (head/tail). wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. kill: request cancellation of a task or a whole Subagent group, never an individual worker. bg cannot start work; pass background: true to bash or subagent. Output is capped at 50KB per response.",BG_PROMPT_SNIPPET="Manage Bash tasks and Subagent groups (list, read, wait, kill)",BG_PROMPT_GUIDELINES=["Start background work through bash or subagent with background: true; continue independent work while it runs.","A finished background task delivers its result automatically as a notification; use bg wait only when your next step is blocked on it, and never sleep-poll with repeated reads."];var SPINNER_BLOOM=["\xB7","\u2722","\u273C","\u2736","\u273B","\u273D"],STATUS_SPINNER_FRAMES=[...SPINNER_BLOOM,...[...SPINNER_BLOOM].reverse()],STATUS_SPINNER_INTERVAL_MS=120;function statusSpinnerFrame(now){let frame2=Math.floor(now/STATUS_SPINNER_INTERVAL_MS)%STATUS_SPINNER_FRAMES.length;return STATUS_SPINNER_FRAMES[frame2]??STATUS_SPINNER_FRAMES[0]??"\xB7"}function statusMarker(status,opts){if(opts?.stalled)return{glyph:"!",color:"warning"};switch(status){case"running":return{glyph:opts?.now!==void 0?statusSpinnerFrame(opts.now):"\u203A",color:"accent"};case"completed":return{glyph:"\u2713",color:"success"};case"failed":return{glyph:"\xD7",color:"error"};case"timeout":return{glyph:"\xD7",color:"warning"};case"cancelled":case"killed":case"stopping":case"partial":case"aborted":return{glyph:"\u25CB",color:"warning"};case"queued":return{glyph:"\u25CB",color:"muted"};default:return{glyph:"\u2022",color:"muted"}}}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function formatDuration(ms){let totalSeconds=Math.max(0,Math.round(ms/1e3));if(totalSeconds<60)return`${totalSeconds}s`;let minutes=Math.floor(totalSeconds/60),seconds=totalSeconds%60;return minutes<60?`${minutes}m${String(seconds).padStart(2,"0")}s`:`${Math.floor(minutes/60)}h${String(minutes%60).padStart(2,"0")}m`}function fileNameOf(path14){return path14.replace(/\\/g,"/").split("/").at(-1)??path14}function formatAge(endedAt,now=Date.now()){let seconds=Math.max(0,Math.round((now-endedAt)/1e3));if(seconds<60)return`${seconds}s ago`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ago`;let hours=Math.floor(minutes/60);return hours<24?`${hours}h ago`:`${Math.floor(hours/24)}d ago`}function runtimeMs(task,now=Date.now()){return(task.endedAt??now)-task.startedAt}function runtimeLabel(task,now=Date.now()){return formatDuration(runtimeMs(task,now))}function hasExitCode(exitCode){return exitCode!=null}function exitSuffix(exitCode,separator){return hasExitCode(exitCode)?`${separator}exit ${exitCode}`:""}function taskLabel(task){let command=firstCommandLine(task.command);return task.description?`${task.description} \u2014 ${command}`:command}function workerLabel(worker){return worker.description?`${worker.label} \u2014 ${worker.description}`:worker.label}function commandLabel(command,width){return truncateToWidth(firstCommandLine(command),width,"\u2026")}function statusGlyph(status,stalled){return statusMarker(status,{stalled}).glyph}function statusColor(status,stalled){return statusMarker(status,{stalled}).color}function boundedText(text2){return truncateHead(sanitizeBinaryOutput(text2),{maxBytes:50*1024,maxLines:2e3}).content}function result(text2,details){return{content:[{type:"text",text:boundedText(text2)}],details}}function describeTaskLine(task,now=Date.now()){return`${task.id} ${task.kind} ${task.status} (${task.mode}) ${runtimeLabel(task,now)} ${task.title.slice(0,200)}`}var UNKNOWN_ID_MESSAGE="Unknown background task ID",AMBIGUOUS_ID_MESSAGE="Ambiguous background task ID",LOOKUP_LIST_LIMIT=10;function matchesLookupPrefix(task,id){return task.id.startsWith(id)||task.id.slice(task.kind.length+1).startsWith(id)}function lookupFailure(background,id,error){let message=error instanceof Error?error.message:String(error),ambiguous=message.includes(AMBIGUOUS_ID_MESSAGE);if(!ambiguous&&!message.includes(UNKNOWN_ID_MESSAGE))return error instanceof Error?error:new Error(message);if(ambiguous){let matches=background.list().filter(task=>matchesLookupPrefix(task,id)),lines2=matches.map(task=>describeTaskLine(task)).join(`
1499
- `);return new Error(`Ambiguous background task ID "${id}" matches ${matches.length} tasks:
1500
- ${lines2}`)}let tasks=background.list(),active=tasks.filter(task=>!isBackgroundTerminal(task.status)),finished=tasks.filter(task=>isBackgroundTerminal(task.status)),shown=[...active,...finished].slice(0,LOOKUP_LIST_LIMIT);if(shown.length===0)return new Error(`No background task "${id}" in this session. No background tasks in this session.`);let lines=shown.map(task=>describeTaskLine(task)).join(`
1498
+ This allows ${APP_NAME} to load ${CONFIG_DIR_NAME} settings and resources, install missing project packages, and execute project extensions.`}async function selectProjectTrustOption(cwd,ctx){let options=getProjectTrustOptions(cwd,{includeSessionOnly:!0}),selected=await ctx.ui.select(formatProjectTrustPrompt(cwd),options.map(option=>option.label));return options.find(option=>option.label===selected)}function saveProjectTrustPromptResult(trustStore,result2){result2.updates.length>0&&trustStore.setMany(result2.updates)}async function resolveProjectTrusted(options){if(options.trustOverride!==void 0)return options.trustOverride;if(!hasTrustRequiringProjectResources(options.cwd))return!0;if(options.extensionsResult){let{result:result2,errors}=await emitProjectTrustEvent(options.extensionsResult,{type:"project_trust",cwd:options.cwd},options.projectTrustContext);for(let error of errors)options.onExtensionError?.(`Extension "${error.extensionPath}" project_trust error: ${error.error}`);if(result2){let trusted=result2.trusted==="yes";return result2.remember===!0&&options.trustStore.set(options.cwd,trusted),trusted}}let decision=options.trustStore.get(options.cwd);if(decision!==null)return decision;switch(options.defaultProjectTrust??"ask"){case"always":return!0;case"never":return!1;case"ask":break}if(!options.projectTrustContext.hasUI)return!1;let selected=await selectProjectTrustOption(options.cwd,options.projectTrustContext);return selected!==void 0?(saveProjectTrustPromptResult(options.trustStore,selected),selected.trusted):!1}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path14,error})=>({type:"warning",message:path14?`Invalid settings file ${path14}: ${error.message}`:`Invalid ${scope} settings: ${error.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic=>{let key=`${diagnostic.type}\0${diagnostic.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}registerKeybindings({"app.backgroundTasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground Bash and Subagent executions to the background"},"app.backgroundTasks.focusList":{defaultKeys:"left",description:"Focus the background task list"},"app.backgroundTasks.focusPreview":{defaultKeys:"right",description:"Focus the background task preview"},"app.backgroundTasks.kill":{defaultKeys:"k",description:"Kill selected background task"},"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"}});var BG_NOTIFICATION_TYPE="background-task",BG_COMPLETION_TYPE="background-completion";var bgSchema=typebox_exports.Object({action:StringEnum(["read","wait","kill","list"],{description:"Which background-task operation to perform"}),taskId:typebox_exports.Optional(typebox_exports.String({description:"Bash task or Subagent group id (read/wait/kill)"})),mode:typebox_exports.Optional(StringEnum(["tail","head"],{description:"Read from the end (default) or the start of the output (read)"})),bytes:typebox_exports.Optional(typebox_exports.Number({description:`Max bytes to return (read, default ${formatSize(8192)}, max ${formatSize(51200)})`})),waitMs:typebox_exports.Optional(typebox_exports.Number({description:`Max time to wait in ms, default ${2e4}, max ${6e4} (wait)`})),sinceBytes:typebox_exports.Optional(typebox_exports.Number({description:"Only return output written after this byte offset \u2014 take it from a previous read/wait result (wait)"}))});function requireTaskId(input2){let taskId=input2.taskId;if(!taskId||taskId.trim().length===0)throw new Error(`action '${input2.action}' requires 'taskId' \u2014 use action list to find the execution id.`);return taskId}function clampReadBytes(bytes){let value2=bytes!==void 0&&Number.isFinite(bytes)?bytes:8192;return Math.min(51200,Math.max(256,Math.floor(value2)))}function clampWaitMs(waitMs){let value2=waitMs!==void 0&&Number.isFinite(waitMs)?waitMs:2e4;return Math.min(6e4,Math.max(1e3,Math.floor(value2)))}function clampSinceBytes(sinceBytes){return sinceBytes===void 0||!Number.isFinite(sinceBytes)?void 0:Math.max(0,Math.floor(sinceBytes))}var BG_TOOL_DESCRIPTION="Inspect and control backgrounded work: Bash tasks and Subagent groups started with background: true. Completion is delivered to you automatically as a notification \u2014 never poll. list: bounded activity/history listing; find task IDs here. read: bounded output or report slice (head/tail). wait: block up to waitMs for a task to settle; cancelling the wait ends only the wait, never the task. kill: request cancellation of a task or a whole Subagent group, never an individual worker. bg cannot start work; pass background: true to bash or subagent. Output is capped at 50KB per response.",BG_PROMPT_SNIPPET="Manage Bash tasks and Subagent groups (list, read, wait, kill)",BG_PROMPT_GUIDELINES=["Start background work through bash or subagent with background: true; continue independent work while it runs.","A finished background task delivers its result automatically as a notification; use bg wait only when your next step is blocked on it, and never sleep-poll with repeated reads."];var SPINNER_BLOOM=["\xB7","\u2722","\u273C","\u2736","\u273B","\u273D"],STATUS_SPINNER_FRAMES=[...SPINNER_BLOOM,...[...SPINNER_BLOOM].reverse()],STATUS_SPINNER_INTERVAL_MS=120;function statusSpinnerFrame(now){let frame2=Math.floor(now/STATUS_SPINNER_INTERVAL_MS)%STATUS_SPINNER_FRAMES.length;return STATUS_SPINNER_FRAMES[frame2]??STATUS_SPINNER_FRAMES[0]??"\xB7"}function statusMarker(status,opts){if(opts?.stalled)return{glyph:"!",color:"warning"};switch(status){case"running":return{glyph:opts?.now!==void 0?statusSpinnerFrame(opts.now):"\u203A",color:"accent"};case"completed":return{glyph:"\u2713",color:"success"};case"failed":return{glyph:"\xD7",color:"error"};case"timeout":return{glyph:"\xD7",color:"warning"};case"cancelled":case"killed":case"stopping":case"partial":case"aborted":return{glyph:"\u25CB",color:"warning"};case"queued":return{glyph:"\u25CB",color:"muted"};default:return{glyph:"\u2022",color:"muted"}}}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function formatDuration(ms){let totalSeconds=Math.max(0,Math.round(ms/1e3));if(totalSeconds<60)return`${totalSeconds}s`;let minutes=Math.floor(totalSeconds/60),seconds=totalSeconds%60;return minutes<60?`${minutes}m${String(seconds).padStart(2,"0")}s`:`${Math.floor(minutes/60)}h${String(minutes%60).padStart(2,"0")}m`}function fileNameOf(path14){return path14.replace(/\\/g,"/").split("/").at(-1)??path14}function formatAge(endedAt,now=Date.now()){let seconds=Math.max(0,Math.round((now-endedAt)/1e3));if(seconds<60)return`${seconds}s ago`;let minutes=Math.floor(seconds/60);if(minutes<60)return`${minutes}m ago`;let hours=Math.floor(minutes/60);return hours<24?`${hours}h ago`:`${Math.floor(hours/24)}d ago`}function runtimeMs(task,now=Date.now()){return(task.endedAt??now)-task.startedAt}function runtimeLabel(task,now=Date.now()){return formatDuration(runtimeMs(task,now))}function hasExitCode(exitCode){return exitCode!=null}function exitSuffix(exitCode,separator){return hasExitCode(exitCode)?`${separator}exit ${exitCode}`:""}function taskLabel(task){let command=firstCommandLine(task.command);return task.description?`${task.description} \u2014 ${command}`:command}function workerLabel(worker){return worker.description?`${worker.label} \u2014 ${worker.description}`:worker.label}function commandLabel(command,width){return truncateToWidth(firstCommandLine(command),width,"\u2026")}function statusGlyph(status,stalled){return statusMarker(status,{stalled}).glyph}function statusColor(status,stalled){return statusMarker(status,{stalled}).color}function boundedText(text2){return truncateHead(sanitizeBinaryOutput(text2),{maxBytes:50*1024,maxLines:2e3}).content}function result(text2,details){return{content:[{type:"text",text:boundedText(text2)}],details}}function describeTaskLine(task,now=Date.now()){return`${task.id} ${task.kind} ${task.status} (${task.mode}) ${runtimeLabel(task,now)} ${task.title.slice(0,200)}`}var LOOKUP_LIST_LIMIT=10;function recentFinishedFirst(tasks){return tasks.sort((left,right)=>(right.endedAt??0)-(left.endedAt??0))}function listedTasks(background){let all=background.list(),tasks=all.filter(task=>task.mode==="background");return{tasks,foregroundOmitted:all.length-tasks.length}}function foregroundOmissionNote(omitted){return omitted>0?`
1499
+ ${omitted} foreground ${omitted===1?"execution":"executions"} omitted \u2014 foreground work is delivered inline in the transcript.`:""}function lookupFailure(background,id,error){if(!(error instanceof BackgroundLookupError))return error instanceof Error?error:new Error(String(error));if(error.kind==="ambiguous"){let lines2=error.matches.map(task=>describeTaskLine(task)).join(`
1500
+ `);return new Error(`Ambiguous background task ID "${id}" matches ${error.matches.length} tasks:
1501
+ ${lines2}`)}let{tasks,foregroundOmitted}=listedTasks(background),active=tasks.filter(task=>!isBackgroundTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isBackgroundTerminal(task.status))),shown=[...active,...finished].slice(0,LOOKUP_LIST_LIMIT);if(shown.length===0)return new Error(`No background task "${id}" in this session. No background tasks in this session.`);let lines=shown.map(task=>describeTaskLine(task)).join(`
1501
1502
  `);return new Error(`No background task "${id}" in this session. IDs from other sessions are not valid here.
1502
1503
  Current tasks:
1503
- ${lines}`)}function readText(header,slice){let boundedField=(text2,maxBytes)=>truncateHead(boundText(sanitizeBinaryOutput(text2),maxBytes),{maxBytes,maxLines:100}).content;return[boundedField(header,4096),slice.task.error?`Task error: ${boundedField(slice.task.error,4096)}`:"",slice.readError?`Output read error: ${boundedField(slice.readError,4096)}`:"",boundedField(slice.task.outputPath??"",8192),slice.text||"(no output yet)"].filter(Boolean).join(`
1504
- `)}async function runRead(background,input2){let id=requireTaskId(input2);try{let mode=input2.mode??"tail",slice=await background.read(id,{mode,bytes:clampReadBytes(input2.bytes)});return result(readText(`[${describeTaskLine(slice.task)} \xB7 ${slice.totalBytes} bytes${slice.truncated?" \xB7 truncated":""}]`,slice),{action:"read",taskId:slice.task.id,mode,sliceBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,outputPath:slice.task.outputPath??"",kind:slice.task.kind,status:slice.task.status})}catch(error){throw lookupFailure(background,id,error)}}async function runWait(background,input2,signal){let id=requireTaskId(input2);try{let release2=background.pin(id);try{let start=Date.now(),task=await background.wait(id,clampWaitMs(input2.waitMs),signal),timedOut=!isBackgroundTerminal(task.status),windowNote=background.closed?" \xB7 host closed; execution state unconfirmed":timedOut?" \xB7 wait window expired; execution continues":"",slice=await background.read(id,{bytes:32768,sinceBytes:clampSinceBytes(input2.sinceBytes)});return signal?.throwIfAborted(),result(readText(`[${describeTaskLine(task)}${windowNote}]`,slice),{action:"wait",taskId:task.id,...timedOut?{}:{backgroundTaskId:task.id},status:task.status,kind:task.kind,timedOut,exitCode:void 0,waitedMs:Date.now()-start,deltaBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,deltaTruncated:slice.truncated,outputPath:task.outputPath??""})}finally{release2()}}catch(error){throw lookupFailure(background,id,error)}}function runKill(background,input2){let id=requireTaskId(input2);try{let task=background.get(id),requested=background.kill(task.id);return result(requested?`Cancellation requested for ${task.id}. The task or whole group is stopping; cleanup may still be in progress.`:`No new cancellation requested for ${task.id} (${background.get(task.id).status}).`,{action:"kill",taskId:task.id,command:task.command??task.title,requested,status:background.get(task.id).status})}catch(error){throw lookupFailure(background,id,error)}}function runList(background){let all=background.list(),tasks=all.filter(task=>task.mode==="background"),foregroundOmitted=all.length-tasks.length,active=tasks.filter(task=>!isBackgroundTerminal(task.status)),finished=tasks.filter(task=>isBackgroundTerminal(task.status)),shown=[...active,...finished.slice(0,5)].slice(0,100),hidden=tasks.length-shown.length,foregroundNote=foregroundOmitted>0?`
1505
- ${foregroundOmitted} foreground ${foregroundOmitted===1?"execution":"executions"} omitted \u2014 foreground work is delivered inline in the transcript.`:"";return result(shown.length?`${shown.map(task=>describeTaskLine(task)).join(`
1504
+ ${lines}${foregroundOmissionNote(foregroundOmitted)}`)}function readText(header,slice){let boundedField=(text2,maxBytes)=>truncateHead(boundText(sanitizeBinaryOutput(text2),maxBytes),{maxBytes,maxLines:100}).content;return[boundedField(header,4096),slice.task.error?`Task error: ${boundedField(slice.task.error,4096)}`:"",slice.readError?`Output read error: ${boundedField(slice.readError,4096)}`:"",boundedField(slice.task.outputPath??"",8192),slice.text||"(no output yet)"].filter(Boolean).join(`
1505
+ `)}async function runRead(background,input2){let id=requireTaskId(input2);try{let mode=input2.mode??"tail",slice=await background.read(id,{mode,bytes:clampReadBytes(input2.bytes)});return result(readText(`[${describeTaskLine(slice.task)} \xB7 ${slice.totalBytes} bytes${slice.truncated?" \xB7 truncated":""}]`,slice),{action:"read",taskId:slice.task.id,mode,sliceBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,outputPath:slice.task.outputPath??"",kind:slice.task.kind,status:slice.task.status})}catch(error){throw lookupFailure(background,id,error)}}async function runWait(background,input2,signal){let id=requireTaskId(input2);try{let release2=background.pin(id);try{let start=Date.now(),task=await background.wait(id,clampWaitMs(input2.waitMs),signal),timedOut=!isBackgroundTerminal(task.status),windowNote=background.closed?" \xB7 host closed; execution state unconfirmed":timedOut?" \xB7 wait window expired; execution continues":"",slice=await background.read(id,{bytes:32768,sinceBytes:clampSinceBytes(input2.sinceBytes)});return signal?.throwIfAborted(),result(readText(`[${describeTaskLine(task)}${windowNote}]`,slice),{action:"wait",taskId:task.id,...timedOut?{}:{backgroundTaskId:task.id},status:task.status,kind:task.kind,timedOut,exitCode:void 0,waitedMs:Date.now()-start,deltaBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,deltaTruncated:slice.truncated,outputPath:task.outputPath??""})}finally{release2()}}catch(error){throw lookupFailure(background,id,error)}}function runKill(background,input2){let id=requireTaskId(input2);try{let task=background.get(id),requested=background.kill(task.id);return result(requested?`Cancellation requested for ${task.id}. The task or whole group is stopping; cleanup may still be in progress.`:`No new cancellation requested for ${task.id} (${background.get(task.id).status}).`,{action:"kill",taskId:task.id,command:task.command??task.title,requested,status:background.get(task.id).status})}catch(error){throw lookupFailure(background,id,error)}}function runList(background){let{tasks,foregroundOmitted}=listedTasks(background),active=tasks.filter(task=>!isBackgroundTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isBackgroundTerminal(task.status))),shown=[...active,...finished.slice(0,5)].slice(0,100),hidden=tasks.length-shown.length;return result(shown.length?`${shown.map(task=>describeTaskLine(task)).join(`
1506
1506
  `)}${hidden>0?`
1507
- ${hidden} more records not shown.`:""}${foregroundNote}`:`No background tasks. Start work through bash or subagent with background: true.${foregroundNote}`,{action:"list",running:active.length,finished:finished.length,shown:shown.length,hidden,...foregroundOmitted>0?{foregroundOmitted}:{}})}var SOURCE_LIMIT=64*1024,CARD_ROWS=128,OUTPUT_ROWS=20,REPORT_ROWS=24;function clean(text2){return sanitizeBinaryOutput(stripTerminalSequences(text2)).replace(/\r\n?/g,`
1507
+ ${hidden} more records not shown.`:""}${foregroundOmissionNote(foregroundOmitted)}`:`No background tasks. Start work through bash or subagent with background: true.${foregroundOmissionNote(foregroundOmitted)}`,{action:"list",running:active.length,finished:finished.length,shown:shown.length,hidden,...foregroundOmitted>0?{foregroundOmitted}:{}})}var SOURCE_LIMIT=64*1024,CARD_ROWS=128,OUTPUT_ROWS=20,REPORT_ROWS=24;function clean(text2){return sanitizeBinaryOutput(stripTerminalSequences(text2)).replace(/\r\n?/g,`
1508
1508
  `)}function savedText(message){let content=message.content,text2="",clipped=!1;if(typeof content=="string")text2=content.slice(0,SOURCE_LIMIT),clipped=content.length>SOURCE_LIMIT;else if(Array.isArray(content)){let visited2=0;for(let block of content){if(++visited2>256){clipped=!0;break}if(!block||block.type!=="text"||typeof block.text!="string")continue;let next=`${text2?`
1509
1509
  `:""}${block.text.slice(0,SOURCE_LIMIT+1)}`,remaining=SOURCE_LIMIT-text2.length;if(text2+=next.slice(0,remaining),next.length>remaining||block.text.length>SOURCE_LIMIT){clipped=!0;break}}}return{text:clean(text2),clipped}}function completionView(message){let snapshot=readBackgroundCompletion(message.details);if(!snapshot){let{text:text2,clipped}=savedText(message);return{body:text2,truncated:clipped}}let view={kind:snapshot.kind,status:snapshot.status,id:clean(snapshot.taskId),body:"",diagnostic:snapshot.error===void 0?void 0:clean(snapshot.error),truncated:!1};return snapshot.kind==="bash"?(view.shell=snapshot.shell===void 0?void 0:clean(snapshot.shell),view.command=snapshot.command===void 0?void 0:clean(snapshot.command.text),view.cwd=snapshot.cwd===void 0?void 0:clean(snapshot.cwd),view.path=snapshot.outputPath===void 0?void 0:clean(snapshot.outputPath),view.body=clean(snapshot.output.text),view.truncated=snapshot.output.truncated||snapshot.command?.truncated===!0):snapshot.workers.length?view.workers=snapshot.workers.map((worker,index3)=>({index:index3+1,description:clean(worker.description),profile:clean(worker.profile),status:clean(worker.status),report:clean(worker.report.text),error:worker.error===void 0?void 0:clean(worker.error),truncated:worker.report.truncated})):(view.body=clean(snapshot.output?.text??""),view.truncated=snapshot.output?.truncated??!1),view}function failedWorker(worker){return!!worker.error||worker.status==="failed"||worker.status==="aborted"||worker.status==="cancelled"}function color(status){return status===void 0?"muted":statusMarker(status).color}function statusName(status){return status==="timeout"?"Timed out":status?status[0].toUpperCase()+status.slice(1):"Unknown"}function shortId(id){return id.replace(/^(bash|subagent)-(.{8}).+$/,"$1-$2")}var CompletionCard=class{constructor(view,options,theme2){this.view=view,this.options=options,this.theme=theme2}invalidate(){}render(width){if(width<1)return[];let theme2=this.theme;return new ToolChromeComponent({render:contentWidth=>this.renderContent(contentWidth),invalidate(){}},`${theme2.fg(color(this.view.status),"\u25CF")} `,{continuationPrefix:theme2.fg("dim","\u2502 "),blankLinePrefix:theme2.fg("dim","\u2502")}).render(width).map(line=>truncateToWidth(line,width,""))}renderContent(width){if(!Number.isFinite(width)||width<1)return[];let view=this.view,theme2=this.theme,options=this.options,padding=Math.min(Math.max(0,Math.floor(options.outputPad||0)-1),Math.floor((width-1)/2)),inner=width-padding*2,indent=inner>=3?" ":"",bodyWidth=Math.max(1,inner-indent.length),lines=[],status=view.status?statusName(view.status):"Result received",kind=view.kind==="subagent"?"Subagent":view.kind==="bash"?view.shell==="bash"?"Bash":view.shell||"Shell":"Notification";if(lines.push(`${theme2.fg("toolTitle",theme2.bold(kind))}${theme2.fg("muted",` \xB7 Background ${status.toLowerCase()}`)}${view.id?theme2.fg("dim",` \xB7 ${shortId(view.id)}`):""}`),options.expanded){view.truncated&&lines.push(theme2.fg("warning","The saved result is truncated; this is not the complete original output."));let section=(title,text2,limit,markdown=!1,tail=!1,error=!1)=>{lines.push("",theme2.fg("muted",theme2.bold(title)));let rendered=markdown?new Markdown(text2,0,0,getMarkdownTheme()).render(bodyWidth):wrapTextWithAnsi(text2,bodyWidth).map(line=>theme2.fg(error?"error":"toolOutput",line)),omitted=Math.max(0,rendered.length-limit),selected=tail?rendered.slice(-limit):rendered.slice(0,limit);tail&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} earlier display lines omitted`));for(let line of selected)lines.push(indent+line);!tail&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} more display lines omitted`))};if(view.kind==="subagent"&&view.diagnostic&&section("Group result",view.diagnostic,4,!1,!1,view.status==="failed"),view.kind==="bash")view.command&&section("Command",view.command,8),view.cwd&&section("Directory",view.cwd,2),section(view.status==="failed"||view.status==="timeout"?"Error":"Result",view.diagnostic??status,4,!1,!1,view.status==="failed"),section("Output",view.body.trim()?view.body:"No output.",OUTPUT_ROWS,!1,!0),view.path&&section("Log",view.path,4);else if(view.workers){let reportBudget=Math.min(REPORT_ROWS,Math.max(6,Math.floor(72/view.workers.length)));for(let worker of view.workers){let marker=statusMarker(worker.status);lines.push("",`${theme2.fg(marker.color,`${marker.glyph} #${worker.index} ${statusName(worker.profile)}`)}${theme2.fg("muted",` \xB7 ${statusName(worker.status)}`)}`),lines.push(theme2.fg("muted",`Task: ${worker.description}`)),failedWorker(worker)?(section("Reason",worker.error||statusName(worker.status),2,!1,!1,worker.status==="failed"),worker.report&&section("Partial report",worker.report,Math.max(3,reportBudget-6),!0)):section("Report",worker.report||"No report returned.",reportBudget,!0),worker.truncated&&lines.push(theme2.fg("warning"," Saved report truncated."))}}else section("Details",view.body||"No text result.",36,!0);view.id&&lines.push("",...wrapTextWithAnsi(`Task ID: ${view.id}`,inner).map(line=>theme2.fg("dim",line))),lines.push(theme2.fg("dim","Preview of the saved result \xB7 /bg has task details while retained."))}else{view.command?lines.push(theme2.fg("toolOutput",`$ ${view.command.split(`
1510
1510
  `)[0]}`)):view.workers&&lines.push(theme2.fg("muted",`${view.workers.length} worker${view.workers.length===1?"":"s"} \xB7 reports available`)),view.diagnostic&&lines.push(theme2.fg(color(view.status),view.diagnostic));let problem=view.workers?.find(failedWorker);problem&&lines.push(theme2.fg(color(problem.status),`#${problem.index}: ${(problem.error||statusName(problem.status)).split(`
@@ -1612,11 +1612,11 @@ ${boundText2(reportSectionBody(run),perTaskBudget)}`);return boundText2(sections
1612
1612
  `),49152)}function createRunCancellation(parent){let controller=new AbortController,executions=new Map,current,registrationId=0,disposed=!1,executeHandler=handler=>{if(disposed||!handler)return Promise.resolve();let existing=executions.get(handler);if(existing)return existing;let execution=Promise.resolve().then(handler).catch(()=>{});return executions.set(handler,execution),execution},trigger=()=>disposed?Promise.resolve():(controller.signal.aborted||controller.abort(),executeHandler(current?.handler)),parentListener=()=>{trigger()};return parent&&(parent.aborted?trigger():parent.addEventListener("abort",parentListener,{once:!0})),{signal:controller.signal,get aborted(){return controller.signal.aborted},abort:trigger,onAbort(handler){if(disposed)return()=>{};let registration={id:++registrationId,handler};current=registration,controller.signal.aborted&&executeHandler(handler);let unregistered=!1;return()=>{unregistered||(unregistered=!0,current?.id===registration.id&&(current=void 0))}},throwIfAborted(){if(controller.signal.aborted)throw new Error("Subagent run was aborted.")},dispose(){disposed||(disposed=!0,current=void 0,parent?.removeEventListener("abort",parentListener))}}}function abortableSleep(ms,scope){return new Promise((resolve17,reject)=>{if(scope.signal.aborted){reject(new Error("Aborted"));return}let timer,onAbort=()=>{timer&&clearTimeout(timer),scope.signal.removeEventListener("abort",onAbort),reject(new Error("Aborted"))};timer=setTimeout(()=>{scope.signal.removeEventListener("abort",onAbort),resolve17()},ms),scope.signal.addEventListener("abort",onAbort,{once:!0})})}function workerSystemPrompt(base,task){return[base,`You are Pi subagent "${task.agent.name}", working independently on one delegated task.`,"You cannot see the parent conversation; rely entirely on the task briefing and repository context available in your working directory.","Only your final message is returned to the caller; nothing you write in earlier turns is visible to anyone.","Complete the task fully\u2014do not gold-plate it, but do not leave it half-done.","Stay inside the assigned working directory and delegated scope.","Do not ask the end user questions. If blocked, report the exact blocker and what would resolve it.","Do not spawn subagents or invoke tools outside the configured tool list.","Background execution is not available inside subagents. Do not set `background: true` on bash or other tools, and do not use shell detachment to bypass this restriction. Run commands in the foreground and wait for them to finish before reporting. Only the parent agent or the user can move the entire subagent invocation to the background. If the task requires a long-lived background service, report the requirement to the parent instead of starting it.","When referencing files in the final report, use paths relative to the task's working directory so the caller can locate them unambiguously.","Include code snippets only when the exact text is load-bearing (a bug you found, a signature the caller asked for); do not recap code you merely read.","End with a concise report covering findings or changes, verification performed, blockers, and unresolved risks. The caller will relay it to the user, so include only the essentials.",task.agent.systemPrompt].filter(part=>!!part?.trim()).join(`
1613
1613
 
1614
1614
  `)}function lastAssistantMessage(session){for(let index3=session.messages.length-1;index3>=0;index3--){let message=session.messages[index3];if(message?.role==="assistant")return message}}function assistantError(message){if(!(!message||message.role!=="assistant"))return message.errorMessage}function createThrottledEmitter(onProgress){let timer;return{emit:()=>{!onProgress||timer||(timer=setTimeout(()=>{timer=void 0,onProgress()},80))},cancel:()=>{timer&&clearTimeout(timer),timer=void 0}}}function mapSessionEvent(event,seenAssistantMessages,now=Date.now()){if(event.type==="auto_retry_start")return{runEvent:{type:"auto_retry_start",attempt:event.attempt,maxAttempts:event.maxAttempts,deadline:now+event.delayMs,error:event.errorMessage},immediate:!0};if(event.type==="auto_retry_end")return{runEvent:{type:"auto_retry_end"},immediate:!0};if(event.type==="turn_end")return{runEvent:{type:"turn_end"},immediate:!0};if(event.type==="compaction_start")return{runEvent:{type:"compaction_started",startedAt:now},immediate:!0};if(event.type==="compaction_end")return{runEvent:{type:"compaction_ended",usage:event.result?.usage,tokensBefore:event.result?.tokensBefore,tokensAfter:event.result?.estimatedTokensAfter,error:event.errorMessage,endedAt:now},immediate:!0};if(event.type==="message_end"&&event.message.role==="assistant"){let usage=seenAssistantMessages.has(event.message)?void 0:event.message.usage;return seenAssistantMessages.add(event.message),{runEvent:{type:"assistant_message_settled",usage},immediate:!0}}if(event.type==="tool_execution_start")return{runEvent:{type:"tool_started",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args,startedAt:now},immediate:!0};if(event.type==="tool_execution_update")return{runEvent:{type:"tool_updated",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args},immediate:!1};if(event.type==="tool_execution_end")return{runEvent:{type:"tool_ended",toolCallId:event.toolCallId,result:event.result,isError:event.isError,endedAt:now},immediate:!0}}async function raceInitialization(chain,scope){return new Promise(resolve17=>{let settled=!1,finish=outcome=>{settled||(settled=!0,scope.signal.removeEventListener("abort",onAbort),resolve17(outcome))},onAbort=()=>{finish({kind:"aborted"})};if(scope.signal.aborted){onAbort(),chain.then(()=>{},()=>{});return}scope.signal.addEventListener("abort",onAbort,{once:!0}),chain.then(outcome=>finish(outcome),error=>finish({kind:"error",error}))})}async function runSdkTask(options){let{task,scope,dispatch,modelRuntime,agentDir,projectTrusted,onProgress}=options,throttled=createThrottledEmitter(onProgress),unsubscribe,unregisterAbort,session,seenAssistantMessages=new Set,emitImmediate=()=>onProgress?.(),emitThrottled=throttled.emit;unregisterAbort=scope.onAbort(async()=>{session&&await session.abort()});try{if(scope.aborted){dispatch({type:"settle",verdict:"aborted",report:"",error:"Subagent was aborted before it started.",endedAt:Date.now()});return}let settingsManager=SettingsManager.create(task.cwd,agentDir,{projectTrusted}),resourceLoader=new DefaultResourceLoader({cwd:task.cwd,agentDir,settingsManager,noExtensions:!0,noSkills:!0,noPromptTemplates:!0,noThemes:!0,systemPromptOverride:base=>workerSystemPrompt(base,task)}),initialization=(async()=>(await resourceLoader.reload(),scope.signal.aborted?{kind:"aborted"}:{kind:"created",session:(await createAgentSession({executionRole:"subagent",cwd:task.cwd,agentDir,modelRuntime,model:task.model,thinkingLevel:task.thinking,tools:task.agent.tools,resourceLoader,sessionManager:SessionManager.inMemory(task.cwd),settingsManager})).session}))(),outcome=await raceInitialization(initialization,scope);if(outcome.kind==="error")throw outcome.error;if(outcome.kind==="aborted"){initialization.then(late=>{if(late.kind==="created")try{late.session.dispose()}catch{}},()=>{}),dispatch({type:"settle",verdict:"aborted",report:"",error:"Subagent was aborted during initialization.",endedAt:Date.now()});return}if(session=outcome.session,scope.aborted){await session.abort(),dispatch({type:"settle",verdict:"aborted",report:"",error:"Subagent was aborted during initialization.",endedAt:Date.now()});return}unsubscribe=session.subscribe(event=>{let mapped=mapSessionEvent(event,seenAssistantMessages);mapped&&(dispatch(mapped.runEvent),mapped.immediate?emitImmediate():emitThrottled())}),await session.prompt(task.prompt);let finalMessage=lastAssistantMessage(session),report=finalAssistantText(session.messages),error=assistantError(finalMessage);scope.signal.aborted||finalMessage?.stopReason==="aborted"?dispatch({type:"settle",verdict:"aborted",report,error:error??"Subagent was aborted.",endedAt:Date.now()}):finalMessage?.stopReason==="error"||error?dispatch({type:"settle",verdict:"failed",report,error:error??"Subagent failed.",endedAt:Date.now()}):dispatch({type:"settle",verdict:"completed",report,error:void 0,endedAt:Date.now()})}catch(error){let report=session?finalAssistantText(session.messages):"";scope.signal.aborted?dispatch({type:"settle",verdict:"aborted",report,error:"Subagent was aborted.",endedAt:Date.now()}):dispatch({type:"settle",verdict:"failed",report,error:error instanceof Error?error.message:String(error),endedAt:Date.now()})}finally{throttled.cancel(),unregisterAbort?.(),unsubscribe?.(),session?.dispose(),emitImmediate()}}var ConcurrencyGate=class{constructor(limit=6){this.active=0,this.waiters=[],this.limit=limit}acquire(signal){return signal?.aborted?Promise.reject(new Error("Subagent was aborted while queued.")):this.active<this.limit?(this.active++,Promise.resolve(()=>this.release())):new Promise((resolve17,reject)=>{let waiter={resolve:resolve17,reject,signal,settled:!1};signal&&(waiter.abortListener=()=>{if(waiter.settled)return;waiter.settled=!0;let index3=this.waiters.indexOf(waiter);index3>=0&&this.waiters.splice(index3,1),reject(new Error("Subagent was aborted while queued."))},signal.addEventListener("abort",waiter.abortListener,{once:!0})),this.waiters.push(waiter)})}release(){for(this.active=Math.max(0,this.active-1);this.waiters.length>0;){let waiter=this.waiters.shift();if(!(waiter.settled||waiter.signal?.aborted)){waiter.settled=!0,waiter.signal?.removeEventListener("abort",waiter.abortListener),this.active++,waiter.resolve(()=>this.release());return}}}};function aggregateUsage(runs){let usage=emptyUsage3();for(let run of runs)mergeUsage(usage,run.usage);return usage}function backgroundProjection(runs,tasks,details){return{text:statusSummary(details),workers:runs.map((run,index3)=>({id:run.id,label:run.agent,profile:run.agent,description:run.description,status:run.status,prompt:tasks[index3]?.prompt??run.description,activity:run.currentActivity??run.activities.slice(-3).map(item=>item.summary).join(`
1615
- `),report:{text:run.report,truncated:run.reportTruncated},error:run.error,model:`${run.model} \xB7 ${run.thinking}`,usage:`${run.usage.totalTokens} tokens \xB7 $${run.usage.cost.toFixed(4)} \xB7 ${run.usage.toolUses} tool calls`}))}}function emitDetails(runs,tasks,startedAt,onUpdate){let details={status:statusOf(runs),runs:runs.map(toRunDetails),startedAt,usage:aggregateUsage(runs)};return onUpdate?.(boundSubagentDetails(details),backgroundProjection(runs,tasks,details)),details}function validateTaskCount(tasks){if(tasks.length===0)throw new Error("Subagent task list must not be empty.");if(tasks.length>8)throw new Error(`Subagent task list is limited to ${8} tasks.`)}async function resolveTasks(tasks,options){validateTaskCount(tasks);let config=await loadSubagentConfig(options.agentDir,options.onConfigWarning);return Promise.all(tasks.map((task,index3)=>resolveSubagentTask(task,options.parentCwd,options.parent,options.agentDir,config).catch(error=>{let message=error instanceof Error?error.message:String(error);throw new Error(`Subagent task tasks[${index3}] failed to resolve: ${message}`)})))}function isRetryableRunError(error){return error?isRetryableAssistantError({role:"assistant",content:[],stopReason:"error",errorMessage:error}):!1}function shouldRetryTask(run){return run.status==="failed"&&run.usage.turns===0&&run.usage.toolUses===0&&isRetryableRunError(run.error)}async function runWithGate(task,scope,options,dispatch,getState2,onProgress){let baseDelayMs=options.taskRetryBaseDelayMs??1e3;for(let attempt2=0;;attempt2++){dispatch({type:"retry_started"});let release2,delayMs=0;try{if(release2=await options.gate.acquire(scope.signal),scope.signal.aborted){dispatch({type:"abort_while_queued",endedAt:Date.now()});return}dispatch({type:"slot_acquired",startedAt:Date.now()}),await runSdkTask({task,scope,dispatch,modelRuntime:options.modelRuntime,agentDir:options.agentDir,projectTrusted:task.insideParent?options.projectTrusted:!1,onProgress});let state2=getState2();if(attempt2>=2||scope.signal.aborted||!shouldRetryTask(state2))return;delayMs=baseDelayMs*2**attempt2,dispatch({type:"retry_scheduled",attempt:attempt2+1,maxAttempts:2,deadline:Date.now()+delayMs,error:state2.error})}catch(error){scope.signal.aborted?dispatch({type:"abort_while_queued",endedAt:Date.now()}):dispatch({type:"settle",verdict:"failed",report:"",error:error instanceof Error?error.message:String(error),endedAt:Date.now()});return}finally{release2?.()}try{await abortableSleep(delayMs,scope)}catch{dispatch({type:"abort_while_retrying",endedAt:Date.now()});return}}}async function runSubagentInvocation(options){let invocationScope=createRunCancellation(options.signal),unregisterInvocation=options.registerAbort?.(invocationScope.abort);try{let tasks=options.params.tasks??[],resolved=await resolveTasks(tasks,options),runs=resolved.map((task,index3)=>createRunState(task,index3,options.batchId,options.parentCwd)),startedAt=Date.now(),scopes=runs.map(()=>createRunCancellation(invocationScope.signal)),unregisterChildren=invocationScope.onAbort(async()=>{await Promise.allSettled(scopes.map(scope=>scope.abort()))}),lastVersion=versionSum(runs),progress=()=>{let version2=versionSum(runs);version2!==lastVersion&&(lastVersion=version2,emitDetails(runs,resolved,startedAt,options.onUpdate))},dispatch=(index3,event)=>{runs[index3]=reduceRun(runs[index3],event),progress()},latestDetails=emitDetails(runs,resolved,startedAt,options.onUpdate);try{invocationScope.aborted||options.onAccepted?.(),await Promise.all(resolved.map((task,index3)=>{let dispatchToRun=event=>dispatch(index3,event);return runWithGate(task,scopes[index3],options,dispatchToRun,()=>runs[index3],progress)}))}finally{unregisterChildren();for(let scope of scopes)scope.dispose()}return latestDetails=emitDetails(runs,resolved,startedAt,void 0),latestDetails.endedAt=Date.now(),{content:resultContent(latestDetails),details:boundSubagentDetails(latestDetails),projection:backgroundProjection(runs,resolved,latestDetails),usage:toNestedUsage(latestDetails.usage)}}finally{unregisterInvocation?.(),invocationScope.dispose()}}function nullable(schema,description){return typebox_exports.Optional(typebox_exports.Union([schema,typebox_exports.Null()],{description}))}var TaskSchema=typebox_exports.Object({agent:nullable(StringEnum(SUBAGENT_AGENT_NAMES,{description:"Which built-in profile runs this task"}),"Built-in profile; null or omit for explorer (the default)"),prompt:typebox_exports.String({minLength:1,maxLength:5e4,description:"Complete self-contained briefing; the worker cannot see the parent conversation"}),description:nullable(typebox_exports.String({minLength:1,maxLength:80}),"Short task label (3-5 words) shown in the /bg list, live rows, and report headings; null or omit to derive it from the prompt"),cwd:nullable(typebox_exports.String({minLength:1,maxLength:4096}),"Worker directory; relative paths resolve against the parent directory. A directory outside the parent runs without that project's settings. Null or omit to inherit.")},{additionalProperties:!1}),SubagentParamsSchema=typebox_exports.Object({background:nullable(typebox_exports.Boolean(),"true runs all tasks as one managed background group and returns a group reference immediately; false, null or omit blocks until every worker finishes and returns their reports"),tasks:typebox_exports.Array(TaskSchema,{minItems:1,maxItems:8,description:`Independent tasks run concurrently: at most ${6} active at once, excess tasks queue, and results preserve input order`})},{additionalProperties:!1}),ROOT_FIELDS=new Set(["background","tasks"]),TASK_FIELDS=["agent","prompt","description","cwd"];function normalizeSubagentArguments(raw){if(raw===null||typeof raw!="object"||Array.isArray(raw))return raw;let args={...raw};for(let key of Object.keys(args))args[key]===null&&!ROOT_FIELDS.has(key)&&delete args[key];if(args.tasks===void 0&&typeof args.prompt=="string"){let task={};for(let key of TASK_FIELDS)args[key]!==void 0&&(task[key]=args[key]),delete args[key];args.tasks=[task]}return args}function subagent(pi){let gate=new ConcurrencyGate,workerOrdinal=0,activeAborters=new Set;pi.registerTool({name:SUBAGENT_TOOL_NAME,label:SUBAGENT_TOOL_LABEL,description:subagentToolDescription(),promptSnippet:"Delegate bounded work to isolated explorer or general workers",promptGuidelines:["Use `subagent` for bounded work that benefits from isolated context or concurrent investigation; do not delegate a task you can finish with one or two direct tool calls.","Give every task a short `description` label; it is shown in the /bg list, live rows, and report headings."],parameters:SubagentParamsSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:normalizeSubagentArguments,async execute(toolCallId,params,signal,onUpdate,ctx){let host=ctx.background;if(host?.closed)throw new Error("Background service is closed");let managed=host?.enabled||params.background===!0;if(managed&&!host)throw new Error("Background execution requires an enabled Background host.");let latest={status:"running",runs:[],startedAt:Date.now(),usage:emptyUsage3()},ordinals=new Map,projection=view=>({...view,workers:view.workers?.map(worker=>{let ordinal=ordinals.get(worker.id);return ordinal===void 0&&(ordinal=++workerOrdinal,ordinals.set(worker.id,ordinal)),{...worker,label:`#${ordinal} ${worker.profile}`}})}),run=async control=>{let update=(details,view)=>{latest=details;let result3={content:[{type:"text",text:statusSummary(details)}],details};control?control.publish(result3,view?projection(view):void 0):onUpdate?.(result3)};update(latest);let parent={model:ctx.model,thinking:pi.getThinkingLevel(),modelRegistry:ctx.modelRegistry},execution=await runSubagentInvocation({params,parentCwd:ctx.cwd,parent,modelRuntime:ctx.modelRuntime,agentDir:getAgentDir(),projectTrusted:ctx.isProjectTrusted(),signal:control?.signal??signal,gate,batchId:control?.id??toolCallId,onUpdate:update,onAccepted:control?()=>control.accept():void 0,onConfigWarning:message=>ctx.ui.notify(message,"warning"),registerAbort:control?void 0:abort=>(activeAborters.add(abort),()=>activeAborters.delete(abort))}),result2={content:[{type:"text",text:execution.content}],details:execution.details,usage:execution.usage};return control?.publish(result2,projection(execution.projection)),result2};if(!managed)return run();let outcome=await host.execute({kind:"subagent",title:subagentGroupTitle(params.tasks),toolCallId,background:params.background===!0,signal,onUpdate,run:async control=>{let result2=await run(control),status=result2.details.status;return{result:result2,status:status==="aborted"?"cancelled":status==="running"?"failed":status}}});if(outcome.kind==="result")return outcome.result;let submittedAt=Date.now();return{content:[{type:"text",text:`Subagent group handed to background: ${outcome.task.id}. Completion arrives automatically as a notification \u2014 do not poll or immediately wait on it; continue with other work or hand back to the user. Use bg read to inspect progress, bg wait only when your next step is blocked on the result (prefer foreground next time in that case), or bg kill to stop the whole group.`}],details:{...latest,endedAt:submittedAt,background:{id:outcome.task.id,submittedAt}}}},renderCall(args,theme2){return renderSubagentCall(args,theme2)},renderResult(result2,options,theme2,context){return scheduleLiveRefresh(context,options.isPartial&&!result2.details?.background),renderSubagentResult(result2,options,theme2,context.args,context.isError)}}),pi.registerCommand(SUBAGENT_COMMAND_NAME,{description:"Configure Subagent profiles, models, and thinking levels",handler:async(_args,ctx)=>showAgentsCommand(ctx,pi.getThinkingLevel())}),pi.on("tool_result",async event=>{if(event.toolName!==SUBAGENT_TOOL_NAME)return;let details=event.details;if(details&&!details.background&&isSubagentError(details))return{isError:!0}}),pi.on("session_shutdown",async()=>{await Promise.allSettled([...activeAborters].map(abort=>abort())),activeAborters.clear()})}var TODO_TOOL_NAME="todo",TODO_TOOL_LABEL="Todo",TODOS_COMMAND_NAME="todos";var TODO_TOOL_DESCRIPTION=`Manage the conversation's task list for multi-step coding work. One call applies a patch: create adds tasks (status defaults to pending), update edits tasks by id (blank or omitted fields are kept), delete removes tasks by id. Omit or leave empty any group you do not need; call with {} to list every task with its description. Exactly one task may be in_progress: setting one demotes the others. The list holds 20 tasks; when full, the oldest completed tasks are removed automatically. A call that fails validation leaves the list unchanged.
1615
+ `),report:{text:run.report,truncated:run.reportTruncated},error:run.error,model:`${run.model} \xB7 ${run.thinking}`,usage:`${run.usage.totalTokens} tokens \xB7 $${run.usage.cost.toFixed(4)} \xB7 ${run.usage.toolUses} tool calls`}))}}function emitDetails(runs,tasks,startedAt,onUpdate){let details={status:statusOf(runs),runs:runs.map(toRunDetails),startedAt,usage:aggregateUsage(runs)};return onUpdate?.(boundSubagentDetails(details),backgroundProjection(runs,tasks,details)),details}function validateTaskCount(tasks){if(tasks.length===0)throw new Error("Subagent task list must not be empty.");if(tasks.length>8)throw new Error(`Subagent task list is limited to ${8} tasks.`)}async function resolveTasks(tasks,options){validateTaskCount(tasks);let config=await loadSubagentConfig(options.agentDir,options.onConfigWarning);return Promise.all(tasks.map((task,index3)=>resolveSubagentTask(task,options.parentCwd,options.parent,options.agentDir,config).catch(error=>{let message=error instanceof Error?error.message:String(error);throw new Error(`Subagent task tasks[${index3}] failed to resolve: ${message}`)})))}function isRetryableRunError(error){return error?isRetryableAssistantError({role:"assistant",content:[],stopReason:"error",errorMessage:error}):!1}function shouldRetryTask(run){return run.status==="failed"&&run.usage.turns===0&&run.usage.toolUses===0&&isRetryableRunError(run.error)}async function runWithGate(task,scope,options,dispatch,getState2,onProgress){let baseDelayMs=options.taskRetryBaseDelayMs??1e3;for(let attempt2=0;;attempt2++){dispatch({type:"retry_started"});let release2,delayMs=0;try{if(release2=await options.gate.acquire(scope.signal),scope.signal.aborted){dispatch({type:"abort_while_queued",endedAt:Date.now()});return}dispatch({type:"slot_acquired",startedAt:Date.now()}),await runSdkTask({task,scope,dispatch,modelRuntime:options.modelRuntime,agentDir:options.agentDir,projectTrusted:task.insideParent?options.projectTrusted:!1,onProgress});let state2=getState2();if(attempt2>=2||scope.signal.aborted||!shouldRetryTask(state2))return;delayMs=baseDelayMs*2**attempt2,dispatch({type:"retry_scheduled",attempt:attempt2+1,maxAttempts:2,deadline:Date.now()+delayMs,error:state2.error})}catch(error){scope.signal.aborted?dispatch({type:"abort_while_queued",endedAt:Date.now()}):dispatch({type:"settle",verdict:"failed",report:"",error:error instanceof Error?error.message:String(error),endedAt:Date.now()});return}finally{release2?.()}try{await abortableSleep(delayMs,scope)}catch{dispatch({type:"abort_while_retrying",endedAt:Date.now()});return}}}async function runSubagentInvocation(options){let invocationScope=createRunCancellation(options.signal),unregisterInvocation=options.registerAbort?.(invocationScope.abort);try{let tasks=options.params.tasks??[],resolved=await resolveTasks(tasks,options),runs=resolved.map((task,index3)=>createRunState(task,index3,options.batchId,options.parentCwd)),startedAt=Date.now(),scopes=runs.map(()=>createRunCancellation(invocationScope.signal)),unregisterChildren=invocationScope.onAbort(async()=>{await Promise.allSettled(scopes.map(scope=>scope.abort()))}),lastVersion=versionSum(runs),progress=()=>{let version2=versionSum(runs);version2!==lastVersion&&(lastVersion=version2,emitDetails(runs,resolved,startedAt,options.onUpdate))},dispatch=(index3,event)=>{runs[index3]=reduceRun(runs[index3],event),progress()},latestDetails=emitDetails(runs,resolved,startedAt,options.onUpdate);try{invocationScope.aborted||options.onAccepted?.(),await Promise.all(resolved.map((task,index3)=>{let dispatchToRun=event=>dispatch(index3,event);return runWithGate(task,scopes[index3],options,dispatchToRun,()=>runs[index3],progress)}))}finally{unregisterChildren();for(let scope of scopes)scope.dispose()}return latestDetails=emitDetails(runs,resolved,startedAt,void 0),latestDetails.endedAt=Date.now(),{content:resultContent(latestDetails),details:boundSubagentDetails(latestDetails),projection:backgroundProjection(runs,resolved,latestDetails),usage:toNestedUsage(latestDetails.usage)}}finally{unregisterInvocation?.(),invocationScope.dispose()}}function nullable(schema,description){return typebox_exports.Optional(typebox_exports.Union([schema,typebox_exports.Null()],{description}))}var TaskSchema=typebox_exports.Object({agent:nullable(StringEnum(SUBAGENT_AGENT_NAMES,{description:"Which built-in profile runs this task"}),"Built-in profile; null or omit for explorer (the default)"),prompt:typebox_exports.String({minLength:1,maxLength:5e4,description:"Complete self-contained briefing; the worker cannot see the parent conversation"}),description:nullable(typebox_exports.String({minLength:1,maxLength:80}),"Short task label (3-5 words) shown in the /bg list, live rows, and report headings; null or omit to derive it from the prompt"),cwd:nullable(typebox_exports.String({minLength:1,maxLength:4096}),"Worker directory; relative paths resolve against the parent directory. A directory outside the parent runs without that project's settings. Null or omit to inherit.")},{additionalProperties:!1}),SubagentParamsSchema=typebox_exports.Object({background:nullable(typebox_exports.Boolean(),"true runs all tasks as one managed background group and returns a group reference immediately; false, null or omit blocks until every worker finishes and returns their reports"),tasks:typebox_exports.Array(TaskSchema,{minItems:1,maxItems:8,description:`Independent tasks run concurrently: at most ${6} active at once, excess tasks queue, and results preserve input order`})},{additionalProperties:!1}),ROOT_FIELDS=new Set(["background","tasks"]),TASK_FIELDS=["agent","prompt","description","cwd"];function normalizeSubagentArguments(raw){if(raw===null||typeof raw!="object"||Array.isArray(raw))return raw;let args={...raw};for(let key of Object.keys(args))args[key]===null&&!ROOT_FIELDS.has(key)&&delete args[key];if(args.tasks===void 0&&typeof args.prompt=="string"){let task={};for(let key of TASK_FIELDS)args[key]!==void 0&&(task[key]=args[key]),delete args[key];args.tasks=[task]}return args}function subagent(pi){let gate=new ConcurrencyGate,workerOrdinal=0,activeAborters=new Set;pi.registerTool({name:SUBAGENT_TOOL_NAME,label:SUBAGENT_TOOL_LABEL,description:subagentToolDescription(),promptSnippet:"Delegate bounded work to isolated explorer or general workers",promptGuidelines:["Use `subagent` for bounded work that benefits from isolated context or concurrent investigation; do not delegate a task you can finish with one or two direct tool calls.","Give every task a short `description` label; it is shown in the /bg list, live rows, and report headings."],parameters:SubagentParamsSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:normalizeSubagentArguments,async execute(toolCallId,params,signal,onUpdate,ctx){let host=ctx.background;if(host?.closed)throw new Error("Background service is closed");let managed=host?.enabled||params.background===!0;if(managed&&!host)throw new Error("Background execution requires an enabled Background host.");let latest={status:"running",runs:[],startedAt:Date.now(),usage:emptyUsage3()},ordinals=new Map,projection=view=>({...view,workers:view.workers?.map(worker=>{let ordinal=ordinals.get(worker.id);return ordinal===void 0&&(ordinal=++workerOrdinal,ordinals.set(worker.id,ordinal)),{...worker,label:`#${ordinal} ${worker.profile}`}})}),run=async control=>{let update=(details,view)=>{latest=details;let result3={content:[{type:"text",text:statusSummary(details)}],details};control?control.publish(result3,view?projection(view):void 0):onUpdate?.(result3)};update(latest);let parent={model:ctx.model,thinking:pi.getThinkingLevel(),modelRegistry:ctx.modelRegistry},execution=await runSubagentInvocation({params,parentCwd:ctx.cwd,parent,modelRuntime:ctx.modelRuntime,agentDir:getAgentDir(),projectTrusted:ctx.isProjectTrusted(),signal:control?.signal??signal,gate,batchId:control?.id??toolCallId,onUpdate:update,onAccepted:control?()=>control.accept():void 0,onConfigWarning:message=>ctx.ui.notify(message,"warning"),registerAbort:control?void 0:abort=>(activeAborters.add(abort),()=>activeAborters.delete(abort))}),result2={content:[{type:"text",text:execution.content}],details:execution.details,usage:execution.usage};return control?.publish(result2,projection(execution.projection)),result2};if(!managed)return run();let outcome=await host.execute({kind:"subagent",title:subagentGroupTitle(params.tasks),toolCallId,background:params.background===!0,signal,onUpdate,run:async control=>{let result2=await run(control),status=result2.details.status;return{result:result2,status:status==="aborted"?"cancelled":status==="running"?"failed":status}}});if(outcome.kind==="result")return outcome.result;let submittedAt=Date.now();return{content:[{type:"text",text:`Subagent group handed to background: ${outcome.task.id}. Completion arrives automatically as a notification \u2014 do not poll or immediately wait on it; continue with other work or hand back to the user. Use bg read to inspect progress, bg wait only when your next step is blocked on the result (prefer foreground next time in that case), or bg kill to stop the whole group.`}],details:{...latest,endedAt:submittedAt,background:{id:outcome.task.id,submittedAt}}}},renderCall(args,theme2){return renderSubagentCall(args,theme2)},renderResult(result2,options,theme2,context){return scheduleLiveRefresh(context,options.isPartial&&!result2.details?.background),renderSubagentResult(result2,options,theme2,context.args,context.isError)}}),pi.registerCommand(SUBAGENT_COMMAND_NAME,{description:"Configure Subagent profiles, models, and thinking levels",handler:async(_args,ctx)=>showAgentsCommand(ctx,pi.getThinkingLevel())}),pi.on("tool_result",async event=>{if(event.toolName!==SUBAGENT_TOOL_NAME)return;let details=event.details;if(details&&!details.background&&isSubagentError(details))return{isError:!0}}),pi.on("session_shutdown",async()=>{await Promise.allSettled([...activeAborters].map(abort=>abort())),activeAborters.clear()})}var TODO_TOOL_NAME="todo",TODO_TOOL_LABEL="Todo",TODOS_COMMAND_NAME="todos";var TODO_TOOL_DESCRIPTION=`Manage the conversation's task list for multi-step coding work. One call applies a patch: create adds tasks (status defaults to pending), update edits tasks by id (blank or omitted fields are kept), delete removes tasks by id. Omit or leave empty any group you do not need; call with {} to list every task with its description. At most one task may be in_progress: setting one demotes the others. The list holds 20 tasks; when full, the oldest completed tasks are removed automatically, except tasks created or updated in this call. Delete existing tasks in the same patch to free space; an id cannot be both updated and deleted. A call that fails validation leaves the list unchanged.
1616
1616
 
1617
1617
  {"create": [{"subject": "Wire parser", "description": "Parser handles the config format", "status": "in_progress"}]}
1618
1618
  {"update": [{"id": 1, "status": "completed"}, {"id": 2, "status": "in_progress"}]}
1619
- {"delete": [3]}`,TODO_PROMPT_SNIPPET="Track multi-step coding work with a small outcome-oriented task list",TODO_PROMPT_GUIDELINES=["Use `todo` for work with three or more meaningful steps, for user-provided task lists, and in long sessions where progress can drift; skip it for trivial single-step tasks and simple Q&A.","Keep exactly one `todo` task in_progress: mark it before starting the work, and completed only after its description is satisfied \u2014 never while tests fail or work is partial.","When blocked, leave the `todo` task pending and create a task for the blocker instead of faking completion.","Keep the `todo` list short: list before create to avoid duplicates, work in id order, and delete obsolete tasks promptly."];var TODO_DETAILS_SCHEMA_VERSION=3,StatusSchema=StringEnum(["pending","in_progress","completed"],{description:"Task status: pending for future work, in_progress for the single active task, completed for verified done work. Exactly one task may be in_progress; setting one demotes any other active task to pending."}),TaskIdSchema=typebox_exports.Integer({minimum:1,description:"Positive task id."}),CreateItemSchema=typebox_exports.Object({subject:typebox_exports.String({maxLength:160,description:"Short imperative task subject; a reviewable unit of work."}),description:typebox_exports.String({maxLength:500,description:"What done means for this task: acceptance criteria or verification detail."}),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),UpdateItemSchema=typebox_exports.Object({id:TaskIdSchema,subject:typebox_exports.Optional(typebox_exports.String({maxLength:160,description:"Replacement subject; blank or omitted keeps the current one."})),description:typebox_exports.Optional(typebox_exports.String({maxLength:500,description:"Replacement description (what done means); blank or omitted keeps the current one."})),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),TodoParamsSchema=typebox_exports.Object({create:typebox_exports.Optional(typebox_exports.Array(CreateItemSchema,{maxItems:20,description:"Tasks to add, created atomically in input order; status defaults to pending."})),update:typebox_exports.Optional(typebox_exports.Array(UpdateItemSchema,{maxItems:20,description:"Task edits by id; blank or omitted fields keep their current values."})),delete:typebox_exports.Optional(typebox_exports.Array(TaskIdSchema,{maxItems:20,description:"Ids to remove from the current list; deleting an id that is already absent is a no-op."}))},{additionalProperties:!1}),EMPTY_TODO_STATE={items:[],nextId:1};var TODO_STATUSES=new Set(["pending","in_progress","completed"]),GROUP_FIELDS=new Set(["create","update","delete"]);function isRecord5(value2){return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)}function isPositiveSafeInteger(value2){return typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>=1}function isTodoStatus(value2){return typeof value2=="string"&&TODO_STATUSES.has(value2)}function dedupeIds(ids){let seen=[];for(let id of ids)seen.includes(id)||seen.push(id);return seen}function normalizeText(value2){return value2.trim().replace(/\s+/g," ")}function validateRequiredText(value2,label,maximum){if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(!normalized)throw new Error(`${label} cannot be empty`);if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}function validateOptionalText(value2,label,maximum){if(value2===void 0)return;if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(normalized){if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}}function validateOptionalStatus(value2,label){if(value2!==void 0){if(!isTodoStatus(value2))throw new Error(`${label} is invalid`);return value2}}function readCreateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("create must be an array");if(raw.length>20)throw new Error(`create exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`create[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`create[${index3}].${key} is not a create field; valid fields: subject, description, status`);let entry={subject:validateRequiredText(item.subject,`create[${index3}].subject`,160),description:validateRequiredText(item.description,`create[${index3}].description`,500)},status=validateOptionalStatus(item.status,`create[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readUpdateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("update must be an array");if(raw.length>20)throw new Error(`update exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`update[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="id"&&key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`update[${index3}].${key} is not an update field; valid fields: id, subject, description, status`);if(!isPositiveSafeInteger(item.id))throw new Error(`update[${index3}].id must be a positive integer`);let entry={id:item.id},subject=validateOptionalText(item.subject,`update[${index3}].subject`,160);subject!==void 0&&(entry.subject=subject);let description=validateOptionalText(item.description,`update[${index3}].description`,500);description!==void 0&&(entry.description=description);let status=validateOptionalStatus(item.status,`update[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readDeleteIds(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("delete must be an array");if(raw.length>20)throw new Error(`delete exceeds ${20} ids`);let ids=[];for(let index3=0;index3<raw.length;index3++){if(!isPositiveSafeInteger(raw[index3]))throw new Error(`delete[${index3}] must be a positive integer id`);ids.push(raw[index3])}return ids}function currentIdsLabel(state2){return state2.items.length===0?"the list is empty":`current ids: ${state2.items.map(item=>`#${item.id}`).join(", ")}`}function cloneTodoState(state2){return{items:state2.items.map(item=>({...item})),nextId:state2.nextId}}function applyTodoPatch(before,params){if(!isRecord5(params))throw new Error("todo params must be an object");for(let key of Object.keys(params))if(!GROUP_FIELDS.has(key))throw new Error(`unknown todo field "${key}"; valid fields: create, update, delete`);let createEntries=readCreateEntries(params.create),updateEntries=readUpdateEntries(params.update),deleteIds=readDeleteIds(params.delete),updatedIds=new Set;for(let entry of updateEntries){if(updatedIds.has(entry.id))throw new Error(`#${entry.id} appears more than once in update`);updatedIds.add(entry.id)}let deleteSet=new Set(deleteIds);for(let entry of updateEntries)if(deleteSet.has(entry.id))throw new Error(`#${entry.id} cannot be in both update and delete`);let activations=[];createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&activations.push(`create[${index3}]`)});for(let entry of updateEntries)entry.status==="in_progress"&&activations.push(`#${entry.id}`);if(activations.length>1)throw new Error(`at most one task may be set in_progress per call; got ${activations.join(" and ")}`);let byId=new Map(before.items.map(item=>[item.id,item]));for(let entry of updateEntries)if(!byId.has(entry.id))throw new Error(`#${entry.id} not found; ${currentIdsLabel(before)}`);if(createEntries.length>0){if(!Number.isSafeInteger(before.nextId)||before.nextId<1)throw new Error("next id is invalid");if(before.nextId>Number.MAX_SAFE_INTEGER-createEntries.length)throw new Error("next id is exhausted")}let deleted=[],absent=[];for(let id of dedupeIds(deleteIds)){let item=byId.get(id);item?deleted.push({id:item.id,subject:item.subject}):absent.push(id)}let items=before.items.filter(item=>!deleteSet.has(item.id)),updated=[];if(updateEntries.length>0){let entriesById=new Map(updateEntries.map(entry=>[entry.id,entry]));items=items.map(item=>{let entry=entriesById.get(item.id);if(!entry)return item;let next={id:item.id,subject:entry.subject??item.subject,description:entry.description??item.description,status:entry.status??item.status};return updated.push({id:item.id,from:item.status,to:next.status}),next})}let created=[];if(createEntries.length>0){let newItems=createEntries.map((entry,index3)=>({id:before.nextId+index3,subject:entry.subject,description:entry.description,status:entry.status??"pending"}));for(let item of newItems)created.push(item.id);items=[...items,...newItems]}let demotedId,activatedId;for(let entry of updateEntries)entry.status==="in_progress"&&(activatedId=entry.id);if(activatedId===void 0&&createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&(activatedId=before.nextId+index3)}),activatedId!==void 0){let demoted=items.find(item=>item.id!==activatedId&&item.status==="in_progress");demoted&&(demotedId=demoted.id,items=items.map(item=>item.id===demoted.id?{...item,status:"pending"}:item))}let evicted=[];if(items.length>20){let overflow=items.length-20,evictIds=new Set,completedOldestFirst=items.filter(item=>item.status==="completed").sort((first,second)=>first.id-second.id);for(let item of completedOldestFirst){if(overflow<=0)break;evictIds.add(item.id),evicted.push({id:item.id,subject:item.subject}),overflow--}if(overflow>0)throw new Error(`at most ${20} open tasks; complete or delete some first`);items=items.filter(item=>!evictIds.has(item.id))}let change={created,updated,deleted,absent,evicted};return demotedId!==void 0&&(change.demotedId=demotedId),{state:{items,nextId:before.nextId+created.length},change}}function buildTodoDetails(change,state2){return{schemaVersion:TODO_DETAILS_SCHEMA_VERSION,change,state:cloneTodoState(state2)}}function requireValidState(value2){let state2=normalizeSnapshotState(value2);if(!state2)throw new Error("todo state is invalid");return state2}function createTodoStore(initial){let state2=requireValidState(initial??EMPTY_TODO_STATE);return{getState(){return cloneTodoState(state2)},replaceState(next){state2=requireValidState(next)},execute(params){let patch=applyTodoPatch(state2,params),details=buildTodoDetails(patch.change,patch.state);return state2=patch.state,details}}}function normalizeSnapshotState(value2){if(!isRecord5(value2)||!Array.isArray(value2.items)||!isPositiveSafeInteger(value2.nextId)||value2.items.length>20)return;let items=[],ids=new Set,maxId=0,activeCount=0;for(let rawItem of value2.items){if(!isRecord5(rawItem))return;let id=rawItem.id;if(!isPositiveSafeInteger(id)||ids.has(id))return;let subject=rawItem.subject,description=rawItem.description,status=rawItem.status;if(typeof subject!="string"||typeof description!="string"||subject!==normalizeText(subject)||description!==normalizeText(description)||!subject||subject.length>160||!description||description.length>500||!isTodoStatus(status))return;ids.add(id),id>maxId&&(maxId=id),status==="in_progress"&&activeCount++,items.push({id,subject,description,status})}if(!(activeCount>1)&&!(value2.nextId<=maxId))return{items,nextId:value2.nextId}}function replayTodosFromBranch(ctx){let branch=Array.from(ctx.sessionManager.getBranch());for(let index3=branch.length-1;index3>=0;index3--)try{let entry=branch[index3];if(!isRecord5(entry)||entry.type!=="message")continue;let message=entry.message;if(!isRecord5(message)||message.role!=="toolResult"||message.toolName!==TODO_TOOL_NAME)continue;let details=message.details;if(!isRecord5(details)||details.schemaVersion!==TODO_DETAILS_SCHEMA_VERSION)continue;let state2=normalizeSnapshotState(details.state);if(state2)return state2}catch{}return cloneTodoState(EMPTY_TODO_STATE)}var STATUS_MARK={pending:"[ ]",in_progress:"[>]",completed:"[x]"},STATUS_COLOR={pending:"dim",in_progress:"warning",completed:"success"},STATUS_RANK={in_progress:0,pending:1,completed:2},WIDGET_HEADER_SEPARATOR=" \xB7 ",WIDGET_ITEM_SEPARATOR=" ";function hasOpenTodos(state2){return state2.items.some(item=>item.status==="pending"||item.status==="in_progress")}function widgetCounts(state2){let counts={active:0,pending:0,completed:0};for(let item of state2.items)item.status==="in_progress"?counts.active++:item.status==="pending"?counts.pending++:counts.completed++;return counts}function widgetSegment(item,subject,theme2){return`${theme2.fg(STATUS_COLOR[item.status],STATUS_MARK[item.status])} ${theme2.fg("accent",`#${item.id}`)} ${theme2.fg("text",subject)}`}function widgetLine(header,segments,overflow){let body=[...segments,...overflow?[overflow]:[]].join(WIDGET_ITEM_SEPARATOR);return body?`${header}${WIDGET_HEADER_SEPARATOR}${body}`:header}function widgetOverflowLong(remaining,counts){let parts=[counts.active>0?`${counts.active} active`:"",counts.pending>0?`${counts.pending} pending`:"",counts.completed>0?`${counts.completed} completed`:""].filter(Boolean);return`+${remaining} more${parts.length?` (${parts.join(", ")})`:""}`}function renderWidgetLine(state2,theme2,width){let safeWidth=Math.max(1,width),items=state2.items,candidates=items.filter(item=>item.status!=="completed").sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);if(candidates.length===0)return[];let total=items.length,completed=items.filter(item=>item.status==="completed").length,header=`${theme2.fg("accent","Todos")} ${theme2.fg("dim",`${completed}/${total}`)}`,counts=widgetCounts(state2),shown=[],overflow="",bestOverflow=trial=>{let remaining=total-trial.length,segments2=trial.map(entry=>widgetSegment(entry.item,entry.subject,theme2)),activeShown=trial.some(entry=>entry.item.status==="in_progress")?1:0,hidden={active:counts.active-activeShown,pending:counts.pending-(trial.length-activeShown),completed:counts.completed};if(remaining<=0)return visibleWidth(widgetLine(header,segments2,""))<=safeWidth?"":void 0;let long=theme2.fg("dim",widgetOverflowLong(remaining,hidden));if(visibleWidth(widgetLine(header,segments2,long))<=safeWidth)return long;let short=theme2.fg("dim",`+${remaining} more`);return visibleWidth(widgetLine(header,segments2,short))<=safeWidth?short:void 0},fallback=()=>{let best=bestOverflow([]);return best!==void 0?[widgetLine(header,[],best)]:visibleWidth(header)<=safeWidth?[header]:[truncateToWidth(header,safeWidth,"\u2026")]};for(let candidate of candidates){let best=bestOverflow([...shown,{item:candidate,subject:candidate.subject}]);if(best!==void 0){shown.push({item:candidate,subject:candidate.subject}),overflow=best;continue}if(candidate.status!=="in_progress")break;let remaining=total-shown.length-1,suffix=remaining>0?`${WIDGET_ITEM_SEPARATOR}+${remaining} more`:"",prefix=`${header}${WIDGET_HEADER_SEPARATOR}${widgetSegment(candidate,"",theme2)}${suffix}`,available=safeWidth-visibleWidth(prefix);if(available<1)return fallback();shown.push({item:candidate,subject:truncateToWidth(candidate.subject,available,"\u2026")}),overflow=bestOverflow(shown)??""}if(shown.length===0)return fallback();let segments=shown.map(entry=>widgetSegment(entry.item,entry.subject,theme2)),line=widgetLine(header,segments,overflow);return[visibleWidth(line)<=safeWidth?line:truncateToWidth(line,safeWidth,"\u2026")]}function formatTodoList(state2){if(state2.items.length===0)return"No todos.";let counts=widgetCounts(state2),lines=[`Todos: ${counts.active} in progress, ${counts.pending} pending, ${counts.completed} completed`],items=[...state2.items].sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);for(let item of items)lines.push(`${STATUS_MARK[item.status]} #${item.id} ${item.subject}`),lines.push(` ${item.description}`);return lines.join(`
1619
+ {"delete": [3]}`,TODO_PROMPT_SNIPPET="Track multi-step coding work with a small outcome-oriented task list",TODO_PROMPT_GUIDELINES=["Use `todo` for work with three or more meaningful steps, for user-provided task lists, and in long sessions where progress can drift; skip it for trivial single-step tasks and simple Q&A.","Mark the `todo` task you are working on in_progress before starting, and completed only after its description is satisfied. Leave no task in_progress when waiting or when all work is done.","When blocked, leave the `todo` task pending and create a task for the blocker instead of faking completion.","Keep the `todo` list short: list before create to avoid duplicates, work in id order, and delete obsolete tasks promptly."];var TODO_DETAILS_SCHEMA_VERSION=3,StatusSchema=StringEnum(["pending","in_progress","completed"],{description:"Task status: pending for future work, in_progress for the single active task, completed for verified done work. At most one task may be in_progress; setting one demotes any other active task to pending."}),TaskIdSchema=typebox_exports.Integer({minimum:1,description:"Positive task id."}),CreateItemSchema=typebox_exports.Object({subject:typebox_exports.String({maxLength:160,description:"Short imperative task subject; a reviewable unit of work."}),description:typebox_exports.String({maxLength:500,description:"What done means for this task: acceptance criteria or verification detail."}),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),UpdateItemSchema=typebox_exports.Object({id:TaskIdSchema,subject:typebox_exports.Optional(typebox_exports.String({maxLength:160,description:"Replacement subject; blank or omitted keeps the current one."})),description:typebox_exports.Optional(typebox_exports.String({maxLength:500,description:"Replacement description (what done means); blank or omitted keeps the current one."})),status:typebox_exports.Optional(StatusSchema)},{additionalProperties:!1}),TodoParamsSchema=typebox_exports.Object({create:typebox_exports.Optional(typebox_exports.Array(CreateItemSchema,{maxItems:20,description:"Tasks to add, created atomically in input order; status defaults to pending."})),update:typebox_exports.Optional(typebox_exports.Array(UpdateItemSchema,{maxItems:20,description:"Task edits by id; blank or omitted fields keep their current values."})),delete:typebox_exports.Optional(typebox_exports.Array(TaskIdSchema,{maxItems:20,description:"Ids to remove from the current list; deleting an id that is already absent is a no-op."}))},{additionalProperties:!1}),EMPTY_TODO_STATE={items:[],nextId:1};var TODO_STATUSES=new Set(["pending","in_progress","completed"]),GROUP_FIELDS=new Set(["create","update","delete"]);function isRecord5(value2){return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)}function isPositiveSafeInteger(value2){return typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>=1}function isTodoStatus(value2){return typeof value2=="string"&&TODO_STATUSES.has(value2)}function dedupeIds(ids){let seen=[];for(let id of ids)seen.includes(id)||seen.push(id);return seen}function normalizeText(value2){return value2.trim().replace(/\s+/g," ")}function validateRequiredText(value2,label,maximum){if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(!normalized)throw new Error(`${label} cannot be empty`);if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}function validateOptionalText(value2,label,maximum){if(value2===void 0)return;if(typeof value2!="string")throw new Error(`${label} must be a string`);let normalized=normalizeText(value2);if(normalized){if(normalized.length>maximum)throw new Error(`${label} exceeds ${maximum} characters`);return normalized}}function validateOptionalStatus(value2,label){if(value2!==void 0){if(!isTodoStatus(value2))throw new Error(`${label} is invalid`);return value2}}function readCreateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("create must be an array");if(raw.length>20)throw new Error(`create exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`create[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`create[${index3}].${key} is not a create field; valid fields: subject, description, status`);let entry={subject:validateRequiredText(item.subject,`create[${index3}].subject`,160),description:validateRequiredText(item.description,`create[${index3}].description`,500)},status=validateOptionalStatus(item.status,`create[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readUpdateEntries(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("update must be an array");if(raw.length>20)throw new Error(`update exceeds ${20} tasks`);let entries=[];for(let index3=0;index3<raw.length;index3++){let item=raw[index3];if(!isRecord5(item))throw new Error(`update[${index3}] must be an object`);for(let key of Object.keys(item))if(key!=="id"&&key!=="subject"&&key!=="description"&&key!=="status")throw new Error(`update[${index3}].${key} is not an update field; valid fields: id, subject, description, status`);if(!isPositiveSafeInteger(item.id))throw new Error(`update[${index3}].id must be a positive integer`);let entry={id:item.id},subject=validateOptionalText(item.subject,`update[${index3}].subject`,160);subject!==void 0&&(entry.subject=subject);let description=validateOptionalText(item.description,`update[${index3}].description`,500);description!==void 0&&(entry.description=description);let status=validateOptionalStatus(item.status,`update[${index3}].status`);status!==void 0&&(entry.status=status),entries.push(entry)}return entries}function readDeleteIds(raw){if(raw===void 0)return[];if(!Array.isArray(raw))throw new Error("delete must be an array");if(raw.length>20)throw new Error(`delete exceeds ${20} ids`);let ids=[];for(let index3=0;index3<raw.length;index3++){if(!isPositiveSafeInteger(raw[index3]))throw new Error(`delete[${index3}] must be a positive integer id`);ids.push(raw[index3])}return ids}function currentIdsLabel(state2){return state2.items.length===0?"the list is empty":`current ids: ${state2.items.map(item=>`#${item.id}`).join(", ")}`}function cloneTodoState(state2){return{items:state2.items.map(item=>({...item})),nextId:state2.nextId}}function applyTodoPatch(before,params){if(!isRecord5(params))throw new Error("todo params must be an object");for(let key of Object.keys(params))if(!GROUP_FIELDS.has(key))throw new Error(`unknown todo field "${key}"; valid fields: create, update, delete`);let createEntries=readCreateEntries(params.create),updateEntries=readUpdateEntries(params.update),deleteIds=readDeleteIds(params.delete),updatedIds=new Set;for(let entry of updateEntries){if(updatedIds.has(entry.id))throw new Error(`#${entry.id} appears more than once in update`);updatedIds.add(entry.id)}let deleteSet=new Set(deleteIds);for(let entry of updateEntries)if(deleteSet.has(entry.id))throw new Error(`#${entry.id} cannot be in both update and delete`);let activations=[];createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&activations.push(`create[${index3}]`)});for(let entry of updateEntries)entry.status==="in_progress"&&activations.push(`#${entry.id}`);if(activations.length>1)throw new Error(`at most one task may be set in_progress per call; got ${activations.join(" and ")}`);let byId=new Map(before.items.map(item=>[item.id,item]));for(let entry of updateEntries)if(!byId.has(entry.id))throw new Error(`#${entry.id} not found; ${currentIdsLabel(before)}`);if(createEntries.length>0){if(!Number.isSafeInteger(before.nextId)||before.nextId<1)throw new Error("next id is invalid");if(before.nextId>Number.MAX_SAFE_INTEGER-createEntries.length)throw new Error("next id is exhausted")}let deleted=[],absent=[];for(let id of dedupeIds(deleteIds)){let item=byId.get(id);item?deleted.push({id:item.id,subject:item.subject}):absent.push(id)}let items=before.items.filter(item=>!deleteSet.has(item.id));if(updateEntries.length>0){let entriesById=new Map(updateEntries.map(entry=>[entry.id,entry]));items=items.map(item=>{let entry=entriesById.get(item.id);return entry?{id:item.id,subject:entry.subject??item.subject,description:entry.description??item.description,status:entry.status??item.status}:item})}let created=[];if(createEntries.length>0){let newItems=createEntries.map((entry,index3)=>({id:before.nextId+index3,subject:entry.subject,description:entry.description,status:entry.status??"pending"}));for(let item of newItems)created.push(item.id);items=[...items,...newItems]}let demotedId,activatedId;for(let entry of updateEntries)entry.status==="in_progress"&&(activatedId=entry.id);if(activatedId===void 0&&createEntries.forEach((entry,index3)=>{entry.status==="in_progress"&&(activatedId=before.nextId+index3)}),activatedId!==void 0){let demoted=items.find(item=>item.id!==activatedId&&item.status==="in_progress");demoted&&(demotedId=demoted.id,items=items.map(item=>item.id===demoted.id?{...item,status:"pending"}:item))}let evicted=[];if(items.length>20){let overflow=items.length-20,evictIds=new Set,touched=new Set([...created,...updatedIds]),completedOldestFirst=items.filter(item=>item.status==="completed"&&!touched.has(item.id)).sort((first,second)=>first.id-second.id);for(let item of completedOldestFirst){if(overflow<=0)break;evictIds.add(item.id),evicted.push({id:item.id,subject:item.subject}),overflow--}if(overflow>0){let completedIds=before.items.filter(item=>item.status==="completed").map(item=>`#${item.id}`);throw new Error(`at most ${20} tasks; complete or delete some first. Patch not applied. Tasks created or updated in this call are not reclaimed. Delete existing tasks in the same patch to free space (remove those ids from update), or complete tasks in a separate call before creating more. Completed ids before this call: ${completedIds.join(", ")||"none"}.`)}items=items.filter(item=>!evictIds.has(item.id))}let updated=items.filter(item=>updatedIds.has(item.id)).map(item=>({id:item.id,from:byId.get(item.id).status,to:item.status})),change={created,updated,deleted,absent,evicted};return demotedId!==void 0&&(change.demotedId=demotedId),{state:{items,nextId:before.nextId+created.length},change}}function buildTodoDetails(change,state2){return{schemaVersion:TODO_DETAILS_SCHEMA_VERSION,change,state:cloneTodoState(state2)}}function requireValidState(value2){let state2=normalizeSnapshotState(value2);if(!state2)throw new Error("todo state is invalid");return state2}function createTodoStore(initial){let state2=requireValidState(initial??EMPTY_TODO_STATE);return{getState(){return cloneTodoState(state2)},replaceState(next){state2=requireValidState(next)},execute(params){let patch=applyTodoPatch(state2,params),details=buildTodoDetails(patch.change,patch.state);return state2=patch.state,details}}}function normalizeSnapshotState(value2){if(!isRecord5(value2)||!Array.isArray(value2.items)||!isPositiveSafeInteger(value2.nextId)||value2.items.length>20)return;let items=[],ids=new Set,maxId=0,activeCount=0;for(let rawItem of value2.items){if(!isRecord5(rawItem))return;let id=rawItem.id;if(!isPositiveSafeInteger(id)||ids.has(id))return;let subject=rawItem.subject,description=rawItem.description,status=rawItem.status;if(typeof subject!="string"||typeof description!="string"||subject!==normalizeText(subject)||description!==normalizeText(description)||!subject||subject.length>160||!description||description.length>500||!isTodoStatus(status))return;ids.add(id),id>maxId&&(maxId=id),status==="in_progress"&&activeCount++,items.push({id,subject,description,status})}if(!(activeCount>1)&&!(value2.nextId<=maxId))return{items,nextId:value2.nextId}}function replayTodosFromBranch(ctx){let branch=Array.from(ctx.sessionManager.getBranch());for(let index3=branch.length-1;index3>=0;index3--)try{let entry=branch[index3];if(!isRecord5(entry)||entry.type!=="message")continue;let message=entry.message;if(!isRecord5(message)||message.role!=="toolResult"||message.toolName!==TODO_TOOL_NAME)continue;let details=message.details;if(!isRecord5(details)||details.schemaVersion!==TODO_DETAILS_SCHEMA_VERSION)continue;let state2=normalizeSnapshotState(details.state);if(state2)return state2}catch{}return cloneTodoState(EMPTY_TODO_STATE)}var STATUS_MARK={pending:"[ ]",in_progress:"[>]",completed:"[x]"},STATUS_COLOR={pending:"dim",in_progress:"warning",completed:"success"},STATUS_RANK={in_progress:0,pending:1,completed:2},WIDGET_HEADER_SEPARATOR=" \xB7 ",WIDGET_ITEM_SEPARATOR=" ";function hasOpenTodos(state2){return state2.items.some(item=>item.status==="pending"||item.status==="in_progress")}function widgetCounts(state2){let counts={active:0,pending:0,completed:0};for(let item of state2.items)item.status==="in_progress"?counts.active++:item.status==="pending"?counts.pending++:counts.completed++;return counts}function widgetSegment(item,subject,theme2){return`${theme2.fg(STATUS_COLOR[item.status],STATUS_MARK[item.status])} ${theme2.fg("accent",`#${item.id}`)} ${theme2.fg("text",subject)}`}function widgetLine(header,segments,overflow){let body=[...segments,...overflow?[overflow]:[]].join(WIDGET_ITEM_SEPARATOR);return body?`${header}${WIDGET_HEADER_SEPARATOR}${body}`:header}function renderWidgetLine(state2,theme2,width){let safeWidth=Math.max(1,width),items=state2.items,candidates=items.filter(item=>item.status!=="completed").sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);if(candidates.length===0)return[];let total=items.length,completed=items.filter(item=>item.status==="completed").length,header=`${theme2.fg("accent","Todos")} ${theme2.fg("dim",`${completed}/${total}`)}`,shown=[],overflow="",bestOverflow=trial=>{let remaining=candidates.length-trial.length,segments2=trial.map(entry=>widgetSegment(entry.item,entry.subject,theme2));if(remaining<=0)return visibleWidth(widgetLine(header,segments2,""))<=safeWidth?"":void 0;let short=theme2.fg("dim",`+${remaining} more`);return visibleWidth(widgetLine(header,segments2,short))<=safeWidth?short:void 0},fallback=()=>{let best=bestOverflow([]);return best!==void 0?[widgetLine(header,[],best)]:visibleWidth(header)<=safeWidth?[header]:[truncateToWidth(header,safeWidth,"\u2026")]};for(let candidate of candidates){let best=bestOverflow([...shown,{item:candidate,subject:candidate.subject}]);if(best!==void 0){shown.push({item:candidate,subject:candidate.subject}),overflow=best;continue}if(candidate.status!=="in_progress")break;let remaining=candidates.length-shown.length-1,suffix=remaining>0?`${WIDGET_ITEM_SEPARATOR}+${remaining} more`:"",prefix=`${header}${WIDGET_HEADER_SEPARATOR}${widgetSegment(candidate,"",theme2)}${suffix}`,available=safeWidth-visibleWidth(prefix);if(available<1)return fallback();shown.push({item:candidate,subject:truncateToWidth(candidate.subject,available,"\u2026")}),overflow=bestOverflow(shown)??""}if(shown.length===0)return fallback();let segments=shown.map(entry=>widgetSegment(entry.item,entry.subject,theme2)),line=widgetLine(header,segments,overflow);return[visibleWidth(line)<=safeWidth?line:truncateToWidth(line,safeWidth,"\u2026")]}function formatTodoList(state2){if(state2.items.length===0)return"No todos.";let counts=widgetCounts(state2),lines=[`Todos: ${counts.active} in progress, ${counts.pending} pending, ${counts.completed} completed`],items=[...state2.items].sort((first,second)=>STATUS_RANK[first.status]-STATUS_RANK[second.status]||first.id-second.id);for(let item of items)lines.push(`${STATUS_MARK[item.status]} #${item.id} ${item.subject}`),lines.push(` ${item.description}`);return lines.join(`
1620
1620
  `)}var formatCommandList=formatTodoList;function formatIdRange(ids){return ids.length>1&&ids.every((id,index3)=>id===ids[0]+index3)?`#${ids[0]}\u2013#${ids[ids.length-1]}`:ids.map(id=>`#${id}`).join(", ")}function formatTodoContent(change,state2){let parts=[];if(change.created.length>0){let labels=change.created.map(id=>{let item=state2.items.find(entry=>entry.id===id);if(!item)return`#${id}`;let suffix=item.status==="pending"?"":` (${item.status})`;return`#${id}: ${item.subject}${suffix}`}),noun=change.created.length===1?"task":"tasks";parts.push(`Created ${change.created.length} ${noun}: ${labels.join("; ")}`)}for(let entry of change.updated){let item=state2.items.find(candidate=>candidate.id===entry.id),subject=item?`: ${item.subject}`:"",transition=entry.from===entry.to?"":` (${entry.from} -> ${entry.to})`;parts.push(`Updated #${entry.id}${transition}${subject}`)}if(change.demotedId!==void 0&&parts.push(`demoted #${change.demotedId} to pending`),change.deleted.length>0){let noun=change.deleted.length===1?"task":"tasks",labels=change.deleted.map(entry=>`#${entry.id}: ${entry.subject}`);parts.push(`Deleted ${change.deleted.length} ${noun}: ${labels.join("; ")}`)}for(let id of change.absent)parts.push(`#${id} already absent`);if(change.evicted.length>0){let ids=change.evicted.map(entry=>entry.id);parts.push(`auto-removed completed ${formatIdRange(ids)} to stay within ${20}`)}return parts.length===0?formatTodoList(state2):parts.join("; ")}var CALL_ITEMS_MAX=20,CALL_SUBJECT_PREVIEW_COUNT=2,CALL_SUBJECT_PREVIEW_WIDTH=72,CALL_DESCRIPTION_PREVIEW_LENGTH=120,GROUP_FAILURE_MAX_LENGTH=120;function safeRecord2(value2){try{return value2!==null&&typeof value2=="object"&&!Array.isArray(value2)?value2:void 0}catch{return}}function safeValue2(record,key){try{return record?.[key]}catch{return}}function safeString(value2){return typeof value2=="string"?value2:void 0}function clipText(value2,max){return safeString(value2)?.trim().replace(/\s+/g," ").slice(0,max)??""}var safeSubject=value2=>clipText(value2,160),safeDescription=value2=>clipText(value2,500);function safeId(value2){return typeof value2=="number"&&Number.isSafeInteger(value2)&&value2>=1?value2:void 0}function safeStatus(value2){let status=safeString(value2);if(status==="pending"||status==="in_progress"||status==="completed")return status}function readArray(value2,limit=CALL_ITEMS_MAX){try{if(!Array.isArray(value2))return;let length=value2.length,values=[];for(let index3=0;index3<Math.min(length,limit);index3++)try{values.push(value2[index3])}catch{values.push(void 0)}return{values,length}}catch{return}}function readIds(value2){let array=readArray(value2);if(!array)return;let ids=[];for(let entry of array.values){let id=safeId(entry);id!==void 0&&ids.push(id)}return ids}function batchCreateItems(value2){let result2=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw);if(!item)continue;let entry={subject:safeSubject(safeValue2(item,"subject")),description:safeDescription(safeValue2(item,"description"))},status=safeStatus(safeValue2(item,"status"));status&&(entry.status=status),result2.push(entry)}return result2}function batchUpdateItems(value2){let result2=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw);if(!item)continue;let entry={subject:safeSubject(safeValue2(item,"subject")),description:safeDescription(safeValue2(item,"description"))},id=safeId(safeValue2(item,"id"));id!==void 0&&(entry.id=id);let status=safeStatus(safeValue2(item,"status"));status&&(entry.status=status),result2.push(entry)}return result2}function descriptionPreview(value2){let text2=value2.replace(/\s+/g," ");return text2.length>CALL_DESCRIPTION_PREVIEW_LENGTH?`${text2.slice(0,CALL_DESCRIPTION_PREVIEW_LENGTH-1)}\u2026`:text2}function formatSubjectPreview(subjects,total){let shown=subjects.filter(Boolean).slice(0,CALL_SUBJECT_PREVIEW_COUNT).map(subject=>truncateToWidth(subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"));if(!shown.length)return"";let hidden=Math.max(0,total-shown.length);return`${shown.join(", ")}${hidden?`, +${hidden} more`:""}`}function todoDetails(value2){let details=safeRecord2(value2);if(!details||safeValue2(details,"schemaVersion")!==TODO_DETAILS_SCHEMA_VERSION)return;let change=safeRecord2(safeValue2(details,"change")),state2=safeRecord2(safeValue2(details,"state"));if(!(!change||!state2))return{change,state:state2}}function createResultIds(result2,count){let details=todoDetails(result2?.details);if(!details)return;let ids=readIds(safeValue2(details.change,"created"));return ids&&ids.length===count&&count>0?ids:void 0}function deleteResultRemoved(result2){let details=todoDetails(result2?.details);return details?idSubjectEntries(safeValue2(details.change,"deleted")):[]}function deleteResultAbsent(result2){let details=todoDetails(result2?.details);return details?readIds(safeValue2(details.change,"absent"))??[]:[]}function formatCallParts(args,theme2,result2){let details=[],segments=[],pushSegment=(verb,body)=>{let title=segments.length===0?`todo ${verb}`:verb;segments.push(body?`${theme2.fg("toolTitle",theme2.bold(title))} ${body}`:theme2.fg("toolTitle",theme2.bold(title)))},hasCreate=args?.create!==void 0,hasUpdate=args?.update!==void 0,hasDelete=args?.delete!==void 0;if(hasCreate){let items=batchCreateItems(args?.create),rawCount=readArray(args?.create)?.length;if(rawCount!==0){let body=[];if(rawCount!==void 0){let count=Math.min(rawCount,CALL_ITEMS_MAX);body.push(theme2.fg("dim",`${count} ${count===1?"task":"tasks"}`));let preview=formatSubjectPreview(items.map(item=>item.subject),count);preview&&body.push(theme2.fg("dim","\xB7"),theme2.fg("text",preview))}pushSegment("create",body.join(" "))}let ids=createResultIds(result2,items.length);for(let[index3,item]of items.entries()){let marker=ids?theme2.fg("accent",`#${ids[index3]}`):theme2.fg("accent",`${index3+1}.`),status=item.status&&item.status!=="pending"?` ${theme2.fg(STATUS_COLOR[item.status],`(${item.status})`)}`:"";details.push(item.subject?`${marker} ${theme2.fg("text",item.subject)}${status}`:marker),item.description&&details.push(` ${theme2.fg("dim",descriptionPreview(item.description))}`)}}if(hasUpdate){let items=batchUpdateItems(args?.update);if(readArray(args?.update)?.length!==0){let entries=[];for(let item of items){let parts=[];item.id!==void 0&&parts.push(theme2.fg("accent",`#${item.id}`)),item.status&&parts.push(theme2.fg(STATUS_COLOR[item.status],item.status)),item.subject&&parts.push(theme2.fg("text",truncateToWidth(item.subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"))),parts.length>0&&entries.push(parts.join(" "))}pushSegment("update",entries.join(theme2.fg("dim",", ")))}for(let item of items)item.description&&details.push(` ${theme2.fg("dim",descriptionPreview(item.description))}`)}if(hasDelete){if(readArray(args?.delete)?.length!==0){let ids=readIds(args?.delete)??[];pushSegment("delete",ids.length>0?theme2.fg("accent",ids.map(id=>`#${id}`).join(", ")):"")}for(let entry of deleteResultRemoved(result2))details.push(`${theme2.fg("accent",`#${entry.id}`)} ${theme2.fg("text",entry.subject)}`);for(let id of deleteResultAbsent(result2))details.push(theme2.fg("dim",`#${id} already absent`))}return segments.length===0&&segments.push(theme2.fg("toolTitle",theme2.bold("todo list"))),{headline:segments.join(theme2.fg("dim"," ; ")),details}}function formatTodoCall(args,theme2,expanded,result2){let{headline,details}=formatCallParts(args,theme2,result2);return!expanded||details.length===0?headline:[headline,...details].join(`
1621
1621
  `)}function stateIndex(state2){let array=readArray(safeValue2(state2,"items"),20);if(!array||array.length>20)return;let byId=new Map,counts={inProgress:0,pending:0,completed:0};for(let raw of array.values){let item=safeRecord2(raw);if(!item)continue;let id=safeId(safeValue2(item,"id"));id!==void 0&&!byId.has(id)&&byId.set(id,item);let status=safeStatus(safeValue2(item,"status"));status==="in_progress"?counts.inProgress++:status==="pending"?counts.pending++:status==="completed"&&counts.completed++}return{byId,counts}}function stateSubject(map,id){let item=map.get(id);return item?safeSubject(safeValue2(item,"subject")):""}function idSubjectEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id")),subject=safeSubject(safeValue2(item,"subject"));id===void 0||!subject||entries.push({id,subject})}return entries}function updatedEntries(value2){let entries=[];for(let raw of readArray(value2)?.values??[]){let item=safeRecord2(raw),id=safeId(safeValue2(item,"id"));if(id===void 0)continue;let entry={id},from=safeStatus(safeValue2(item,"from"));from&&(entry.from=from);let to=safeStatus(safeValue2(item,"to"));to&&(entry.to=to),entries.push(entry)}return entries}function formatTodoGroupSuccess(args,theme2,result2){let parsed=todoDetails(result2.details);if(!parsed)return;let{change,state:state2}=parsed,index3=stateIndex(state2),segments=[],pushVerb=(word,body)=>{let title=segments.length===0?`todo ${word}`:word;segments.push(body?`${theme2.fg("toolTitle",title)} ${body}`:theme2.fg("toolTitle",title))},withPreview=(word,ids,subjects)=>{let text2=formatSubjectPreview(subjects,subjects.length),base=theme2.fg("accent",formatIdRange(ids));pushVerb(word,text2?`${base}${theme2.fg("dim"," \xB7 ")}${theme2.fg("text",text2)}`:base)},created=readIds(safeValue2(change,"created"))??[];created.length>0&&index3&&withPreview("created",created,created.map(id=>stateSubject(index3.byId,id)));for(let entry of updatedEntries(safeValue2(change,"updated"))){let parts=[theme2.fg("accent",`#${entry.id}`)];entry.to&&parts.push(theme2.fg(STATUS_COLOR[entry.to],entry.to));let subject=index3?stateSubject(index3.byId,entry.id):"";subject&&parts.push(theme2.fg("text",truncateToWidth(subject,CALL_SUBJECT_PREVIEW_WIDTH,"\u2026"))),pushVerb("updated",parts.join(" "))}let demotedId=safeId(safeValue2(change,"demotedId"));demotedId!==void 0&&segments.push(theme2.fg("dim",`demoted #${demotedId}`));let deleted=idSubjectEntries(safeValue2(change,"deleted"));deleted.length>0&&withPreview("deleted",deleted.map(entry=>entry.id),deleted.map(entry=>entry.subject));for(let id of readIds(safeValue2(change,"absent"))??[])segments.push(theme2.fg("dim",`#${id} already absent`));let evicted=idSubjectEntries(safeValue2(change,"evicted"));if(evicted.length>0&&segments.push(theme2.fg("dim",`auto-removed ${evicted.map(entry=>`#${entry.id}`).join(", ")}`)),segments.length===0){if(!index3)return;let parts=[];return index3.counts.inProgress>0&&parts.push(`${index3.counts.inProgress} in progress`),index3.counts.pending>0&&parts.push(`${index3.counts.pending} pending`),index3.counts.completed>0&&parts.push(`${index3.counts.completed} completed`),`${theme2.fg("toolTitle","todo list")}: ${theme2.fg("dim",parts.length?parts.join(", "):"no tasks")}`}return segments.join(theme2.fg("dim"," ; "))}function formatTodoGroupCall(args,theme2,context){if(context.isError){let reason="tool failed";try{for(let block of context.result?.content.slice(0,8)??[]){if(block.type!=="text"||typeof block.text!="string")continue;let text2=block.text.replace(/[\u0000-\u001f\u007f-\u009f]/g," ").replace(/\s+/g," ").trim();if(text2){reason=text2.length>GROUP_FAILURE_MAX_LENGTH?`${text2.slice(0,GROUP_FAILURE_MAX_LENGTH-1)}\u2026`:text2;break}}}catch{}return`${formatTodoCall(args,theme2,!1)} ${theme2.fg("error",`failed: ${reason}`)}`}if(!context.isPartial&&context.result){let summary=formatTodoGroupSuccess(args,theme2,context.result);if(summary)return summary}return formatTodoCall(args,theme2,!1)}var WIDGET_KEY="todos",TodoWidget=class{constructor(getState2){this.registered=!1,this.getState=getState2}setUI(ui){this.ui!==ui&&(this.dispose(),this.ui=ui)}update(){if(this.ui){if(!hasOpenTodos(this.getState())){this.unregister();return}if(this.registered){this.tui?.requestRender();return}this.ui.setWidget(WIDGET_KEY,(tui,theme2)=>(this.tui=tui,{render:width=>renderWidgetLine(this.getState(),theme2,width),invalidate:()=>{}}),{placement:"aboveEditor"}),this.registered=!0}}unregister(){this.registered&&(this.ui?.setWidget(WIDGET_KEY,void 0),this.registered=!1,this.tui=void 0)}dispose(){this.unregister(),this.ui=void 0}};function safeReplay(ctx,store){try{store.replaceState(replayTodosFromBranch(ctx))}catch(error){if(!isStaleExtensionContextError(error))throw error}}function todo(pi){let store=createTodoStore(),widget;pi.registerTool({name:TODO_TOOL_NAME,label:TODO_TOOL_LABEL,description:TODO_TOOL_DESCRIPTION,promptSnippet:TODO_PROMPT_SNIPPET,promptGuidelines:TODO_PROMPT_GUIDELINES,parameters:TodoParamsSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},executionMode:"sequential",toolGroup:TODO_TOOL_NAME,async execute(_toolCallId,params,_signal,_onUpdate){let details=store.execute(params);return{content:[{type:"text",text:formatTodoContent(details.change,details.state)}],details}},renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(context.toolGroupSummary?formatTodoGroupCall(args,theme2,context):formatTodoCall(args,theme2,context.expanded,context.result)),text2}}),pi.registerCommand(TODOS_COMMAND_NAME,{description:"Show the complete todo list for the current conversation branch",handler:async(_args,ctx)=>{if(!ctx.hasUI){ctx.ui.notify("/todos requires an interactive UI.","warning");return}ctx.ui.notify(formatCommandList(store.getState()),"info")}}),pi.on("session_start",async(_event,ctx)=>{safeReplay(ctx,store),ctx.hasUI&&(widget??=new TodoWidget(()=>store.getState()),widget.setUI(ctx.ui),widget.update())}),pi.on("session_tree",async(_event,ctx)=>{safeReplay(ctx,store),widget?.update()}),pi.on("session_shutdown",async(_event,_ctx)=>{widget?.dispose(),widget=void 0}),pi.on("tool_execution_end",async event=>{event.toolName!==TODO_TOOL_NAME||event.isError||widget?.update()})}var MINIMAX_CN_HOST="https://api.minimaxi.com",MINIMAX_GLOBAL_HOST="https://api.minimax.io";function trimValue(value2){return value2?.trim()||void 0}async function runtimeApiKey(modelRuntime,providerId){if(modelRuntime)try{return trimValue((await modelRuntime.getAuth(providerId))?.auth.apiKey)}catch{return}}function storedApiKey(providerId,authPath){let credential=readStoredCredential(providerId,authPath);if(!credential||credential.type!=="api_key"||typeof credential.key!="string")return;let key=isCommandConfigValue(credential.key)?resolveConfigValue(credential.key,credential.env):credential.key;return trimValue(key)}async function resolveProviderKey(modelRuntime,authPath,providerId,envVar){return await runtimeApiKey(modelRuntime,providerId)??storedApiKey(providerId,authPath)??trimValue(process.env[envVar])}async function resolveMiniMaxCredential(modelRuntime,authPath){let cnKey=await resolveProviderKey(modelRuntime,authPath,"minimax-cn","MINIMAX_CN_API_KEY");if(cnKey)return{key:cnKey,host:MINIMAX_CN_HOST};let globalKey=await resolveProviderKey(modelRuntime,authPath,"minimax","MINIMAX_API_KEY");if(globalKey)return{key:globalKey,host:trimValue(process.env.MINIMAX_API_HOST)??MINIMAX_GLOBAL_HOST}}async function resolveDeepSeekCredential(modelRuntime,authPath){let key=await resolveProviderKey(modelRuntime,authPath,"deepseek","DEEPSEEK_API_KEY");return key?{key}:void 0}function configuredEngine(credentials){return credentials.minimax&&credentials.deepseek?"dual":credentials.minimax?"minimax":credentials.deepseek?"deepseek":"none"}async function resolveSearchCredentials(modelRuntime,authPath=getAuthPath()){let[minimax,deepseek]=await Promise.all([resolveMiniMaxCredential(modelRuntime,authPath),resolveDeepSeekCredential(modelRuntime,authPath)]);return{minimax,deepseek}}var WEB_SEARCH_TOOL_NAME="web_search",WEB_SEARCH_LABEL="Web Search",WEB_SEARCH_DESCRIPTION="Search the live web through configured MiniMax and DeepSeek providers. When both are available, searches run concurrently and results are deduplicated and fused. Returns up to 12 source URLs with bounded titles and snippets, plus related searches and optional synthesis; partial provider failures still return successful results.",WEB_SEARCH_PROMPT_SNIPPET="Search the live web for current information",WEB_SEARCH_DISABLED_MESSAGE="Web search is disabled: Neither MiniMax nor DeepSeek API Key was found in auth.json or environment variables. Please add credentials via auth.json or environment variables (MINIMAX_API_KEY, DEEPSEEK_API_KEY).";function getEngineLabel(engine){return engine==="dual"?"MiniMax & DeepSeek":engine==="minimax"?"MiniMax":engine==="deepseek"?"DeepSeek":""}function getWebSearchPromptGuidelines(){return["Use `web_search` for current information, recent releases, live documentation, and other freshness-sensitive facts beyond your training cutoff.",`When using \`web_search\` for freshness-sensitive topics, account for the current date (${new Date().toISOString().slice(0,7)}) and include the year in the query when useful.`]}var TRACKING_PARAMS=new Set(["utm_source","utm_medium","utm_campaign","utm_term","utm_content","ref","fbclid","gclid","trk","gi"]);function truncateText2(text2,maxLength){return text2.length<=maxLength?text2:maxLength<=3?text2.slice(0,maxLength):`${text2.slice(0,maxLength-3).trimEnd()}...`}function boundSingleLineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.replace(/\s+/g," ").trim();return normalized?truncateText2(normalized,maxLength):void 0}function boundMultilineText(value2,maxLength){if(typeof value2!="string")return;let normalized=value2.trim();return normalized?truncateText2(normalized,maxLength):void 0}function normalizeUrl(rawUrl){if(typeof rawUrl!="string")return;let trimmed=rawUrl.trim();if(!(!trimmed||trimmed.length>2048))try{let url=new URL(trimmed);if(url.protocol!=="http:"&&url.protocol!=="https:")return;url.hash="";for(let parameter of TRACKING_PARAMS)url.searchParams.has(parameter)&&url.searchParams.delete(parameter);url.pathname.length>1&&url.pathname.endsWith("/")&&(url.pathname=url.pathname.replace(/\/+$/,""));let normalized=url.toString();return normalized.length<=2048?normalized:void 0}catch{return}}function normalizeHit(hit,source){let url=normalizeUrl(hit.url);if(url)return{title:boundSingleLineText(hit.title,200)??url,url,snippet:boundSingleLineText(hit.snippet,200),date:boundSingleLineText(hit.date,100),sources:[...new Set([...hit.sources,source])]}}function isUrlFallbackTitle(title,url){let normalizedTitle=normalizeUrl(title);return normalizedTitle!==void 0&&normalizedTitle===normalizeUrl(url)}function reciprocalRankScore(candidate){let score=0;for(let rank of candidate.ranks.values())score+=1/(60+rank);return score}function bestRank(candidate){return Math.min(...candidate.ranks.values())}function fuseSearchHits(results){let candidates=new Map,relatedSearches=new Set,deepseekSynthesis;for(let result2 of results){let providerRelated=Array.isArray(result2.relatedSearches)?result2.relatedSearches:[],relatedScanLimit=Math.min(providerRelated.length,64);for(let index3=0;index3<relatedScanLimit&&relatedSearches.size<8;index3++){let normalized=boundSingleLineText(providerRelated[index3],200);normalized&&relatedSearches.add(normalized)}let synthesis=boundMultilineText(result2.synthesisText,6e3);synthesis&&(deepseekSynthesis=synthesis);let providerHits=Array.isArray(result2.hits)?result2.hits:[],hitScanLimit=Math.min(providerHits.length,200);for(let index3=0;index3<hitScanLimit;index3++){let rawHit=providerHits[index3];if(!rawHit)continue;let hit=normalizeHit(rawHit,result2.source);if(!hit)continue;let rank=index3+1,existing=candidates.get(hit.url);if(!existing){candidates.set(hit.url,{hit,ranks:new Map([[result2.source,rank]])});continue}let previousRank=existing.ranks.get(result2.source);(previousRank===void 0||rank<previousRank)&&existing.ranks.set(result2.source,rank);for(let source of hit.sources)existing.hit.sources.includes(source)||existing.hit.sources.push(source);isUrlFallbackTitle(existing.hit.title,existing.hit.url)&&!isUrlFallbackTitle(hit.title,hit.url)&&(existing.hit.title=hit.title),(!existing.hit.snippet||existing.hit.snippet.length<(hit.snippet?.length??0))&&hit.snippet&&(existing.hit.snippet=hit.snippet),!existing.hit.date&&hit.date&&(existing.hit.date=hit.date)}}return{hits:[...candidates.entries()].sort(([leftUrl,left],[rightUrl,right])=>{let scoreDifference=reciprocalRankScore(right)-reciprocalRankScore(left);if(scoreDifference!==0)return scoreDifference;let rankDifference=bestRank(left)-bestRank(right);return rankDifference!==0?rankDifference:leftUrl.localeCompare(rightUrl)}).map(([,candidate])=>candidate.hit).slice(0,12),relatedSearches:relatedSearches.size>0?[...relatedSearches]:void 0,deepseekSynthesis}}function escapeMarkdownText(text2){return text2.replace(/\\/g,"\\\\").replace(/\[/g,"\\[").replace(/\]/g,"\\]").replace(/</g,"\\<").replace(/>/g,"\\>")}function canonicalSources(value2){if(!Array.isArray(value2))return[];let sources=[],scanLimit=Math.min(value2.length,32);for(let index3=0;index3<scanLimit&&sources.length<2;index3++){let source=value2[index3];(source==="MiniMax"||source==="DeepSeek")&&!sources.includes(source)&&sources.push(source)}return sources}function formatHit(value2){if(!value2||typeof value2!="object")return;let hit=value2,url=normalizeUrl(hit.url);if(url)return{title:escapeMarkdownText(boundSingleLineText(hit.title,200)??url),url,snippet:boundSingleLineText(hit.snippet,200),sources:canonicalSources(hit.sources)}}function usableHits(details){let hits=Array.isArray(details.hits)?details.hits:[],formatted=[],scanLimit=Math.min(hits.length,240);for(let index3=0;index3<scanLimit&&formatted.length<12;index3++){let hit=formatHit(hits[index3]);hit&&formatted.push(hit)}return formatted}function formatResultsMarkdown(details){let parts=[],hits=usableHits(details);hits.length>0&&(parts.push(`## Web Sources (${hits.length} found via ${getEngineLabel(details.engine)})
1622
1622
  `),hits.forEach((hit,index3)=>{let sourceTag=hit.sources.length>1?` \u2014 *(found by ${hit.sources.join(" & ")})*`:"";parts.push(`${index3+1}. **[${hit.title}](<${hit.url}>)**${sourceTag}`),hit.snippet&&parts.push(` - ${escapeMarkdownText(hit.snippet)}`)}),parts.push(""));let synthesis=boundMultilineText(details.deepseekSynthesis,6e3);synthesis&&(parts.push(`## DeepSeek Search Synthesis
@@ -1,2 +1,2 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{dist_exports as dist_exports3}from"./chunk-MJ45I4SM.js";import{DISTRIBUTION_PACKAGE_NAME,all_exports,build_exports,compat_exports,compile_exports,dist_exports,dist_exports2,value_exports}from"./chunk-TYOQD6VQ.js";import"./chunk-JEIV47WR.js";import"./chunk-5FDOJRDS.js";import"./chunk-5B3S5DVL.js";import"./chunk-2IO5GDBS.js";import"./chunk-JI4WGISU.js";import"./chunk-4L3WN2XY.js";var oauth_exports={};var VIRTUAL_MODULES={typebox:build_exports,"typebox/compile":compile_exports,"typebox/value":value_exports,"@sinclair/typebox":build_exports,"@sinclair/typebox/compile":compile_exports,"@sinclair/typebox/value":value_exports,"@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,[DISTRIBUTION_PACKAGE_NAME]: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};export{VIRTUAL_MODULES};
2
+ import{dist_exports as dist_exports3}from"./chunk-APQ4ACY3.js";import{DISTRIBUTION_PACKAGE_NAME,all_exports,build_exports,compat_exports,compile_exports,dist_exports,dist_exports2,value_exports}from"./chunk-EWLAVDVN.js";import"./chunk-JEIV47WR.js";import"./chunk-5FDOJRDS.js";import"./chunk-5B3S5DVL.js";import"./chunk-2IO5GDBS.js";import"./chunk-JI4WGISU.js";import"./chunk-4L3WN2XY.js";var oauth_exports={};var VIRTUAL_MODULES={typebox:build_exports,"typebox/compile":compile_exports,"typebox/value":value_exports,"@sinclair/typebox":build_exports,"@sinclair/typebox/compile":compile_exports,"@sinclair/typebox/value":value_exports,"@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,[DISTRIBUTION_PACKAGE_NAME]: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};export{VIRTUAL_MODULES};
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
3
- import{APP_NAME,configureHttpDispatcher,main}from"./chunks/chunk-TYOQD6VQ.js";import"./chunks/chunk-JEIV47WR.js";import"./chunks/chunk-5FDOJRDS.js";import"./chunks/chunk-5B3S5DVL.js";import"./chunks/chunk-2IO5GDBS.js";import"./chunks/chunk-JI4WGISU.js";import"./chunks/chunk-4L3WN2XY.js";function setupCli(){process.title=APP_NAME,process.env.PI_CODING_AGENT="true",process.env.AI_AGENT="pi",process.emitWarning=(()=>{}),configureHttpDispatcher()}setupCli();main(process.argv.slice(2));
3
+ import{APP_NAME,configureHttpDispatcher,main}from"./chunks/chunk-EWLAVDVN.js";import"./chunks/chunk-JEIV47WR.js";import"./chunks/chunk-5FDOJRDS.js";import"./chunks/chunk-5B3S5DVL.js";import"./chunks/chunk-2IO5GDBS.js";import"./chunks/chunk-JI4WGISU.js";import"./chunks/chunk-4L3WN2XY.js";function setupCli(){process.title=APP_NAME,process.env.PI_CODING_AGENT="true",process.env.AI_AGENT="pi",process.emitWarning=(()=>{}),configureHttpDispatcher()}setupCli();main(process.argv.slice(2));