@astralyn/pi 1.4.1 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/bundle/chunks/{chunk-N77PYEXG.js → chunk-ISXCH6TG.js} +1 -1
- package/dist/bundle/chunks/{chunk-KSKBY3VV.js → chunk-Z2YN4E74.js} +117 -111
- package/dist/bundle/chunks/{virtual-modules-XNEYDLXF.js → virtual-modules-QX6D3D7X.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +15 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1 -8
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/distribution-api.d.ts +1 -1
- package/dist/core/extensions/distribution-api.d.ts.map +1 -1
- package/dist/core/extensions/distribution-api.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +29 -2
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybinding-registry.d.ts +16 -1
- package/dist/core/keybinding-registry.d.ts.map +1 -1
- package/dist/core/keybinding-registry.js +20 -0
- package/dist/core/keybinding-registry.js.map +1 -1
- package/dist/core/keybindings-schema.d.ts.map +1 -1
- package/dist/core/keybindings-schema.js +2 -1
- package/dist/core/keybindings-schema.js.map +1 -1
- package/dist/core/keybindings.d.ts +4 -106
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +0 -13
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tasks/format.d.ts.map +1 -1
- package/dist/core/tasks/format.js +10 -4
- package/dist/core/tasks/format.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +5 -0
- package/dist/core/tasks/limits.d.ts.map +1 -0
- package/dist/core/tasks/limits.js +5 -0
- package/dist/core/tasks/limits.js.map +1 -0
- package/dist/core/tasks/runtime.d.ts +1 -0
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +7 -3
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/session.d.ts +1 -1
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +10 -2
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/types.d.ts +13 -0
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tools/bash.d.ts +98 -9
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +308 -11
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +5 -4
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +3 -11
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/powershell.d.ts +2 -1
- package/dist/core/tools/powershell.d.ts.map +1 -1
- package/dist/core/tools/powershell.js +2 -1
- package/dist/core/tools/powershell.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/index.d.ts.map +1 -1
- package/dist/core/tools/renderers/index.js +7 -5
- package/dist/core/tools/renderers/index.js.map +1 -1
- package/dist/core/tools/shell-execution.d.ts +2 -2
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +0 -21
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-operations.d.ts +12 -0
- package/dist/core/tools/shell-operations.d.ts.map +1 -0
- package/dist/core/tools/shell-operations.js +38 -0
- package/dist/core/tools/shell-operations.js.map +1 -0
- package/dist/core/tools/shell-tool.d.ts +8 -64
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +27 -125
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/extensions/index.d.ts +1 -0
- package/dist/extensions/index.d.ts.map +1 -1
- package/dist/extensions/index.js +5 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/keybindings.d.ts +6 -0
- package/dist/extensions/keybindings.d.ts.map +1 -0
- package/dist/extensions/keybindings.js +6 -0
- package/dist/extensions/keybindings.js.map +1 -0
- package/dist/extensions/tasks/index.d.ts +5 -0
- package/dist/extensions/tasks/index.d.ts.map +1 -0
- package/dist/extensions/tasks/index.js +42 -0
- package/dist/extensions/tasks/index.js.map +1 -0
- package/dist/extensions/tasks/keybindings.d.ts +19 -0
- package/dist/extensions/tasks/keybindings.d.ts.map +1 -0
- package/dist/extensions/tasks/keybindings.js +30 -0
- package/dist/extensions/tasks/keybindings.js.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/actions.d.ts +2 -2
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/actions.js +4 -4
- package/dist/extensions/tasks/tool/actions.js.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/constants.d.ts +1 -3
- package/dist/extensions/tasks/tool/constants.d.ts.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/constants.js +1 -3
- package/dist/extensions/tasks/tool/constants.js.map +1 -0
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/schema.js +5 -4
- package/dist/extensions/tasks/tool/schema.js.map +1 -0
- package/dist/{core/tools/tasks → extensions/tasks/tool}/types.d.ts +1 -1
- package/dist/extensions/tasks/tool/types.d.ts.map +1 -0
- package/dist/extensions/tasks/tool/types.js.map +1 -0
- package/dist/extensions/tasks/tool.d.ts +6 -0
- package/dist/extensions/tasks/tool.d.ts.map +1 -0
- package/dist/{core/tools/tasks.js → extensions/tasks/tool.js} +6 -10
- package/dist/extensions/tasks/tool.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/completion-render.d.ts +1 -1
- package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/completion-render.js +2 -2
- package/dist/extensions/tasks/ui/completion-render.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/index.d.ts +1 -1
- package/dist/extensions/tasks/ui/index.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/index.js +4 -4
- package/dist/extensions/tasks/ui/index.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/inspector.d.ts +1 -1
- package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/inspector.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/layout.d.ts +1 -1
- package/dist/extensions/tasks/ui/layout.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/layout.js +1 -1
- package/dist/extensions/tasks/ui/layout.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/list.d.ts +1 -1
- package/dist/extensions/tasks/ui/list.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/list.js +1 -1
- package/dist/extensions/tasks/ui/list.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/manager.d.ts +2 -1
- package/dist/extensions/tasks/ui/manager.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/manager.js +2 -1
- package/dist/extensions/tasks/ui/manager.js.map +1 -0
- package/dist/extensions/tasks/ui/model.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/model.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/render.d.ts +3 -3
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/render.js +2 -2
- package/dist/extensions/tasks/ui/render.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/task-view.d.ts +1 -1
- package/dist/extensions/tasks/ui/task-view.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/task-view.js +1 -1
- package/dist/extensions/tasks/ui/task-view.js.map +1 -0
- package/dist/extensions/tasks/ui/text.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/text.js.map +1 -0
- package/dist/extensions/tasks/ui/tree.d.ts +7 -0
- package/dist/extensions/tasks/ui/tree.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks/host-hooks.js → extensions/tasks/ui/tree.js} +1 -18
- package/dist/extensions/tasks/ui/tree.js.map +1 -0
- package/dist/extensions/tasks/ui/viewport.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/viewport.js.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/views.d.ts +1 -1
- package/dist/extensions/tasks/ui/views.d.ts.map +1 -0
- package/dist/{modes/interactive/tasks → extensions/tasks/ui}/views.js +1 -1
- package/dist/extensions/tasks/ui/views.js.map +1 -0
- package/dist/extensions/tool-presentation/index.d.ts +7 -0
- package/dist/extensions/tool-presentation/index.d.ts.map +1 -0
- package/dist/extensions/tool-presentation/index.js +9 -0
- package/dist/extensions/tool-presentation/index.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +65 -18
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -3
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +85 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +362 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +5 -3
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +14 -29
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts +1 -1
- package/dist/modes/interactive/tool-view/chat.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/chat.js +2 -3
- package/dist/modes/interactive/tool-view/chat.js.map +1 -1
- package/dist/modes/interactive/tool-view/shell.d.ts +15 -0
- package/dist/modes/interactive/tool-view/shell.d.ts.map +1 -0
- package/dist/modes/interactive/tool-view/shell.js +51 -0
- package/dist/modes/interactive/tool-view/shell.js.map +1 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +10 -79
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +7 -298
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
- package/docs/bundled/README.md +1 -4
- package/docs/bundled/tasks.md +3 -3
- package/docs/bundled/tool-presentation.md +9 -7
- package/docs/extensions.md +9 -4
- package/docs/settings.md +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/schemas/keybindings.schema.json +84 -52
- package/dist/core/tools/tasks/actions.d.ts.map +0 -1
- package/dist/core/tools/tasks/actions.js.map +0 -1
- package/dist/core/tools/tasks/constants.d.ts.map +0 -1
- package/dist/core/tools/tasks/constants.js.map +0 -1
- package/dist/core/tools/tasks/schema.d.ts.map +0 -1
- package/dist/core/tools/tasks/schema.js.map +0 -1
- package/dist/core/tools/tasks/types.d.ts.map +0 -1
- package/dist/core/tools/tasks/types.js.map +0 -1
- package/dist/core/tools/tasks.d.ts +0 -14
- package/dist/core/tools/tasks.d.ts.map +0 -1
- package/dist/core/tools/tasks.js.map +0 -1
- package/dist/modes/interactive/tasks/completion-render.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/completion-render.js.map +0 -1
- package/dist/modes/interactive/tasks/host-hooks.d.ts +0 -14
- package/dist/modes/interactive/tasks/host-hooks.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/host-hooks.js.map +0 -1
- package/dist/modes/interactive/tasks/index.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/index.js.map +0 -1
- package/dist/modes/interactive/tasks/inspector.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/inspector.js.map +0 -1
- package/dist/modes/interactive/tasks/layout.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/layout.js.map +0 -1
- package/dist/modes/interactive/tasks/list.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/list.js.map +0 -1
- package/dist/modes/interactive/tasks/manager.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/manager.js.map +0 -1
- package/dist/modes/interactive/tasks/model.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/model.js.map +0 -1
- package/dist/modes/interactive/tasks/render.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/render.js.map +0 -1
- package/dist/modes/interactive/tasks/task-view.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/task-view.js.map +0 -1
- package/dist/modes/interactive/tasks/text.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/text.js.map +0 -1
- package/dist/modes/interactive/tasks/viewport.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/viewport.js.map +0 -1
- package/dist/modes/interactive/tasks/views.d.ts.map +0 -1
- package/dist/modes/interactive/tasks/views.js.map +0 -1
- /package/dist/{core/tools/tasks → extensions/tasks/tool}/schema.d.ts +0 -0
- /package/dist/{core/tools/tasks → extensions/tasks/tool}/types.js +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/inspector.js +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/model.d.ts +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/model.js +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/text.d.ts +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/text.js +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/viewport.d.ts +0 -0
- /package/dist/{modes/interactive/tasks → extensions/tasks/ui}/viewport.js +0 -0
|
@@ -654,16 +654,16 @@ File: ${path14}`)}let providers=new Map;for(let[providerId,provider]of Object.en
|
|
|
654
654
|
`)}catch{return code.split(`
|
|
655
655
|
`).map(line=>theme.fg("mdCodeBlock",line))}}}}function getSelectListTheme(){return{selectedPrefix:text2=>theme.fg("accent",text2),selectedText:text2=>theme.fg("accent",text2),description:text2=>theme.fg("muted",text2),scrollInfo:text2=>theme.fg("muted",text2),noMatch:text2=>theme.fg("muted",text2)}}function getEditorTheme(){return{borderColor:text2=>theme.fg("borderMuted",text2),selectList:getSelectListTheme()}}function getSettingsListTheme(){return{label:(text2,selected)=>selected?theme.fg("accent",text2):text2,value:(text2,selected)=>selected?theme.fg("accent",text2):theme.fg("muted",text2),description:text2=>theme.fg("dim",text2),cursor:theme.fg("accent","\u2192 "),hint:text2=>theme.fg("dim",text2)}}var DynamicBorder=class{constructor(color2=str2=>theme.fg("border",str2)){this.color=color2}invalidate(){}render(width){return[this.color("\u2500".repeat(Math.max(1,width)))]}};function formatKeyPart(part,options){let displayPart=process.platform==="darwin"&&part.toLowerCase()==="alt"?"option":part;return options.capitalize?displayPart.charAt(0).toUpperCase()+displayPart.slice(1):displayPart}function formatKeyText(key,options={}){return key.split("/").map(k2=>k2.split("+").map(part=>formatKeyPart(part,options)).join("+")).join("/")}function formatKeys(keys,options={}){return keys.length===0?"":formatKeyText(keys.join("/"),options)}function formatKeyLabelPart(part){switch(part.toLowerCase()){case"alt":return process.platform==="darwin"?"Option":"Alt";case"ctrl":return"Ctrl";case"shift":return"Shift";case"escape":case"esc":return"Esc";case"enter":case"return":return"Enter";case"space":return"Space";case"tab":return"Tab";case"left":return"\u2190";case"right":return"\u2192";case"up":return"\u2191";case"down":return"\u2193";case"pageup":return"PgUp";case"pagedown":return"PgDn";default:return part.length===1?part.toUpperCase():part.charAt(0).toUpperCase()+part.slice(1)}}function formatKeyLabel(key){if(!key)return"";let modifiers2=[],remaining=key;for(;;){let match2=/^(ctrl|shift|alt)\+/i.exec(remaining);if(!match2)break;modifiers2.push(formatKeyLabelPart(match2[1])),remaining=remaining.slice(match2[0].length)}let keyPart=formatKeyLabelPart(remaining||"+");return[...modifiers2,keyPart].join("+")}function keyLabel(keybinding,options={}){let key=(options.keybindings??getKeybindings()).getKeys(keybinding)[0];return key!==void 0?formatKeyLabel(key):options.fallback?formatKeyLabel(options.fallback):""}function keyText(keybinding){return formatKeys(getKeybindings().getKeys(keybinding))}function keyDisplayText(keybinding){return formatKeys(getKeybindings().getKeys(keybinding),{capitalize:!0})}function keyHint(keybinding,description){return theme.fg("dim",keyText(keybinding))+theme.fg("muted",` ${description}`)}function rawKeyHint(key,description){return theme.fg("dim",formatKeyText(key))+theme.fg("muted",` ${description}`)}var CountdownTimer=class{constructor(timeoutMs,tui,onTick,onExpire){this.tui=tui,this.onTick=onTick,this.onExpire=onExpire,this.remainingSeconds=Math.ceil(timeoutMs/1e3),this.onTick(this.remainingSeconds),this.intervalId=setInterval(()=>{this.remainingSeconds--,this.onTick(this.remainingSeconds),this.tui?.requestRender(),this.remainingSeconds<=0&&(this.dispose(),this.onExpire())},1e3)}dispose(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0)}};var ExtensionInputComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(title,_placeholder,onSubmit,onCancel,opts){super(),this._focused=!1,this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",title),1,0),this.addChild(this.titleText),opts?.description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",opts.description),1,0))),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",`${this.baseTitle} (${s}s)`)),()=>this.onCancelCallback())),this.input=new Input,opts?.initialValue&&this.input.setValue(opts.initialValue),this.addChild(this.input),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyHint("tui.select.confirm","submit")} ${keyHint("tui.select.cancel","cancel")}`,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
656
656
|
`?this.onSubmitCallback(this.input.getValue()):kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():this.input.handleInput(keyData)}dispose(){this.countdown?.dispose()}};var ExtensionSelectorComponent=class extends Container{constructor(title,options,onSelect,onCancel,opts){super(),this.selectedIndex=0,this.options=options,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.onToggleToolsExpanded=opts?.onToggleToolsExpanded,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",theme.bold(title)),1,0),this.addChild(this.titleText),opts?.description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",opts.description),1,0))),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",theme.bold(`${this.baseTitle} (${s}s)`))),()=>this.onCancelCallback())),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1));let navigationKeys=[keyLabel("tui.select.up"),keyLabel("tui.select.down")].filter(Boolean).join("/"),confirmKey=keyLabel("tui.select.confirm"),cancelKey=keyLabel("tui.select.cancel"),hints=[navigationKeys?rawKeyHint(navigationKeys,"navigate"):"",confirmKey?rawKeyHint(confirmKey,"select"):"",cancelKey?rawKeyHint(cancelKey,"cancel"):""].filter(Boolean);this.addChild(new Text(hints.join(theme.fg("muted"," \u2022 ")),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}updateList(){this.listContainer.clear();for(let i=0;i<this.options.length;i++){let text2=i===this.selectedIndex?theme.fg("accent","\u2192 ")+theme.fg("accent",this.options[i]):` ${theme.fg("text",this.options[i])}`;this.listContainer.addChild(new Text(text2,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.tools.expand"))this.onToggleToolsExpanded?.();else if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.options.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
657
|
-
`){let selected=this.options[this.selectedIndex];selected&&this.onSelectCallback(selected)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}dispose(){this.countdown?.dispose()}};import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync7}from"node:fs";import{unlink}from"node:fs/promises";import*as os3 from"node:os";import{existsSync as existsSync6,readFileSync as readFileSync7}from"fs";import{join as join16}from"path";var modifiers=["ctrl","shift","alt","super"],baseKeyPattern=`(?:[a-z0-9]|${Object.values(Key).flatMap(value=>typeof value=="string"?[value.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&")]:[]).join("|")})`,duplicateModifierPattern=modifiers.map(modifier=>`${modifier}\\+.*${modifier}\\+`).join("|"),KeyIdSchema=typebox_exports.Unsafe(typebox_exports.String({pattern:`^(?!.*(?:${duplicateModifierPattern}))(?:(?:${modifiers.join("|")})\\+){0,4}${baseKeyPattern}$`,description:"Key identifier with optional ctrl, shift, alt, or super modifiers."}));function keybindingValueSchema(options){return typebox_exports.Union([KeyIdSchema,typebox_exports.Array(KeyIdSchema)],options)}var KeybindingValueSchema=keybindingValueSchema();var registered={};function sameDefinition(left,right){return JSON.stringify(left)===JSON.stringify(right)}function registerKeybindings(definitions){for(let[id,definition]of Object.entries(definitions)){let existing=registered[id];if(existing&&!sameDefinition(existing,definition))throw new Error(`Keybinding ${id} is already registered with a different definition`);registered[id]=definition}}function getRegisteredKeybindings(){return{...registered}}function useWindowsKeybindings(platform3=process.platform,env2=process.env){return platform3==="win32"||platform3==="linux"&&!!(env2.WSL_DISTRO_NAME||env2.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),APP_KEYBINDINGS={"app.tasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground tasks to the background"},"app.tasks.previousTab":{defaultKeys:"left",description:"Show Output in the focused task inspector"},"app.tasks.nextTab":{defaultKeys:"right",description:"Show Details in the focused task inspector"},"app.tasks.kill":{defaultKeys:"k",description:"Stop the selected task"},"app.tasks.confirmStop":{defaultKeys:"enter",description:"Confirm stopping the selected task"},"app.tasks.detachSelected":{defaultKeys:"b",description:"Move the selected task to the background"},"app.tasks.search":{defaultKeys:"/",description:"Search retained task identities and labels"},"app.tasks.follow":{defaultKeys:"f",description:"Follow the selected task's output"},"app.tasks.top":{defaultKeys:"home",description:"Go to the top of the task list or preview"},"app.tasks.bottom":{defaultKeys:"end",description:"Go to the bottom of the task list or preview"},"app.tasks.nextFocus":{defaultKeys:"tab",description:"Switch between task list and inspector"},"app.tasks.previousFocus":{defaultKeys:"shift+tab",description:"Switch between task inspector and list"},"app.tasks.help":{defaultKeys:"?",description:"Show task controls"},"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.question.pageUp":{defaultKeys:"alt+up",description:"Page up in question details"},"app.question.pageDown":{defaultKeys:"alt+down",description:"Page down in question details"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.clipboard.pasteImage":{defaultKeys:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste files on macOS, images, or text from clipboard"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"},"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},...APP_KEYBINDINGS},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}var validateKeybindingValue=Compile(KeybindingValueSchema);function toKeybindingsConfig(value){let config={};for(let[key,binding]of Object.entries(value))key!=="$schema"&&validateKeybindingValue.Check(binding)&&(config[key]=binding);return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&Object.hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))Object.hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!Object.hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path14){if(existsSync6(path14))try{let parsed=JSON.parse(stripBom(readFileSync7(path14,"utf-8")));return typeof parsed!="object"||parsed===null?void 0:parsed}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super({...KEYBINDINGS,...getRegisteredKeybindings()},userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join16(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path14){let rawConfig=loadRawConfig(path14);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};function normalizeWhitespaceLower(text2){return text2.toLowerCase().replace(/\s+/g," ").trim()}function getSessionSearchText(session){return`${session.id} ${session.name??""} ${session.allMessagesText} ${session.cwd}`}function hasSessionName(session){return!!session.name?.trim()}function matchesNameFilter(session,filter2){return filter2==="all"?!0:hasSessionName(session)}function parseSearchQuery(query){let trimmed=query.trim();if(!trimmed)return{mode:"tokens",tokens:[],regex:null};if(trimmed.startsWith("re:")){let pattern=trimmed.slice(3).trim();if(!pattern)return{mode:"regex",tokens:[],regex:null,error:"Empty regex"};try{return{mode:"regex",tokens:[],regex:new RegExp(pattern,"i")}}catch(err){let msg=err instanceof Error?err.message:String(err);return{mode:"regex",tokens:[],regex:null,error:msg}}}let tokens2=[],buf="",inQuote=!1,hadUnclosedQuote=!1,flush=kind=>{let v2=buf.trim();buf="",v2&&tokens2.push({kind,value:v2})};for(let i=0;i<trimmed.length;i++){let ch=trimmed[i];if(ch==='"'){inQuote?(flush("phrase"),inQuote=!1):(flush("fuzzy"),inQuote=!0);continue}if(!inQuote&&/\s/.test(ch)){flush("fuzzy");continue}buf+=ch}return inQuote&&(hadUnclosedQuote=!0),hadUnclosedQuote?{mode:"tokens",tokens:trimmed.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0).map(t=>({kind:"fuzzy",value:t})),regex:null}:(flush(inQuote?"phrase":"fuzzy"),{mode:"tokens",tokens:tokens2,regex:null})}function matchSession(session,parsed){let text2=getSessionSearchText(session);if(parsed.mode==="regex"){if(!parsed.regex)return{matches:!1,score:0};let idx=text2.search(parsed.regex);return idx<0?{matches:!1,score:0}:{matches:!0,score:idx*.1}}if(parsed.tokens.length===0)return{matches:!0,score:0};let totalScore=0,normalizedText=null;for(let token of parsed.tokens){if(token.kind==="phrase"){normalizedText===null&&(normalizedText=normalizeWhitespaceLower(text2));let phrase=normalizeWhitespaceLower(token.value);if(!phrase)continue;let idx=normalizedText.indexOf(phrase);if(idx<0)return{matches:!1,score:0};totalScore+=idx*.1;continue}let m2=fuzzyMatch(token.value,text2);if(!m2.matches)return{matches:!1,score:0};totalScore+=m2.score}return{matches:!0,score:totalScore}}function filterAndSortSessions(sessions,query,sortMode,nameFilter="all"){let nameFiltered=nameFilter==="all"?sessions:sessions.filter(session=>matchesNameFilter(session,nameFilter));if(!query.trim())return nameFiltered;let parsed=parseSearchQuery(query);if(parsed.error)return[];if(sortMode==="recent"){let filtered=[];for(let s of nameFiltered)matchSession(s,parsed).matches&&filtered.push(s);return filtered}let scored=[];for(let s of nameFiltered){let res=matchSession(s,parsed);res.matches&&scored.push({session:s,score:res.score})}return scored.sort((a,b2)=>a.score!==b2.score?a.score-b2.score:b2.session.modified.getTime()-a.session.modified.getTime()),scored.map(r=>r.session)}function shortenPath(path14){let home=os3.homedir();return path14&&(path14.startsWith(home)?`~${path14.slice(home.length)}`:path14)}function formatSessionDate(date){let diffMs=new Date().getTime()-date.getTime(),diffMins=Math.floor(diffMs/6e4),diffHours=Math.floor(diffMs/36e5),diffDays=Math.floor(diffMs/864e5);return diffMins<1?"now":diffMins<60?`${diffMins}m`:diffHours<24?`${diffHours}h`:diffDays<7?`${diffDays}d`:diffDays<30?`${Math.floor(diffDays/7)}w`:diffDays<365?`${Math.floor(diffDays/30)}mo`:`${Math.floor(diffDays/365)}y`}function canonicalizePath2(path14){return path14&&canonicalizePath(path14)}var SessionSelectorHeader=class{constructor(scope,sortMode,nameFilter,requestRender){this.loading=!1,this.loadProgress=null,this.showPath=!1,this.confirmingDeletePath=null,this.statusMessage=null,this.statusTimeout=null,this.showRenameHint=!1,this.scope=scope,this.sortMode=sortMode,this.nameFilter=nameFilter,this.requestRender=requestRender}setScope(scope){this.scope=scope}setSortMode(sortMode){this.sortMode=sortMode}setNameFilter(nameFilter){this.nameFilter=nameFilter}setLoading(loading){this.loading=loading,this.loadProgress=null}setProgress(loaded,total){this.loadProgress={loaded,total}}setShowPath(showPath){this.showPath=showPath}setShowRenameHint(show){this.showRenameHint=show}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14}clearStatusTimeout(){this.statusTimeout&&(clearTimeout(this.statusTimeout),this.statusTimeout=null)}setStatusMessage(msg,autoHideMs){this.clearStatusTimeout(),this.statusMessage=msg,!(!msg||!autoHideMs)&&(this.statusTimeout=setTimeout(()=>{this.statusMessage=null,this.statusTimeout=null,this.requestRender()},autoHideMs))}invalidate(){}render(width){let title=this.scope==="current"?"Resume Session (Current Folder)":"Resume Session (All)",leftText=theme.bold(title),sortLabel=this.sortMode==="threaded"?"Threaded":this.sortMode==="recent"?"Recent":"Fuzzy",sortText=theme.fg("muted","Sort: ")+theme.fg("accent",sortLabel),nameLabel=this.nameFilter==="all"?"All":"Named",nameText=theme.fg("muted","Name: ")+theme.fg("accent",nameLabel),scopeText;if(this.loading){let progressText=this.loadProgress?`${this.loadProgress.loaded}/${this.loadProgress.total}`:"...";scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent",`Loading ${progressText}`)}`}else this.scope==="current"?scopeText=`${theme.fg("accent","\u25C9 Current Folder")}${theme.fg("muted"," | \u25CB All")}`:scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent","\u25C9 All")}`;let rightText=truncateToWidth(`${scopeText} ${nameText} ${sortText}`,width,""),availableLeft=Math.max(0,width-visibleWidth(rightText)-1),left=truncateToWidth(leftText,availableLeft,""),spacing=Math.max(0,width-visibleWidth(left)-visibleWidth(rightText)),hintLine1,hintLine2;if(this.confirmingDeletePath!==null){let confirmHint=`Delete session? ${keyHint("tui.select.confirm","confirm")} \xB7 ${keyHint("tui.select.cancel","cancel")}`;hintLine1=theme.fg("error",truncateToWidth(confirmHint,width,"\u2026")),hintLine2=""}else if(this.statusMessage){let color2=this.statusMessage.type==="error"?"error":"accent";hintLine1=theme.fg(color2,truncateToWidth(this.statusMessage.message,width,"\u2026")),hintLine2=""}else{let pathState=this.showPath?"(on)":"(off)",sep13=theme.fg("muted"," \xB7 "),hint1=keyHint("tui.input.tab","scope")+sep13+theme.fg("muted",'re:<pattern> regex \xB7 "phrase" exact'),hint2Parts=[keyHint("app.session.toggleSort","sort"),keyHint("app.session.toggleNamedFilter","named"),keyHint("app.session.delete","delete"),keyHint("app.session.togglePath",`path ${pathState}`)];this.showRenameHint&&hint2Parts.push(keyHint("app.session.rename","rename"));let hint2=hint2Parts.join(sep13);hintLine1=truncateToWidth(hint1,width,"\u2026"),hintLine2=truncateToWidth(hint2,width,"\u2026")}return[`${left}${" ".repeat(spacing)}${rightText}`,hintLine1,hintLine2]}};function buildSessionTree(sessions){let byPath=new Map;for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path;byPath.set(sessionPath,{session,children:[],latestActivity:session.modified.getTime()})}let roots=[];for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path,node=byPath.get(sessionPath),parentPath=canonicalizePath2(session.parentSessionPath);parentPath&&byPath.has(parentPath)?byPath.get(parentPath).children.push(node):roots.push(node)}let updateLatestActivity=node=>{let latestActivity=node.session.modified.getTime();for(let child of node.children)latestActivity=Math.max(latestActivity,updateLatestActivity(child));return node.latestActivity=latestActivity,latestActivity};for(let root of roots)updateLatestActivity(root);let sortNodes=nodes=>{nodes.sort((a,b2)=>b2.latestActivity-a.latestActivity);for(let node of nodes)sortNodes(node.children)};return sortNodes(roots),roots}function flattenSessionTree(roots){let result2=[],walk=(node,depth,ancestorContinues,isLast)=>{result2.push({session:node.session,depth,isLast,ancestorContinues});for(let i=0;i<node.children.length;i++){let childIsLast=i===node.children.length-1,continues=depth>0?!isLast:!1;walk(node.children[i],depth+1,[...ancestorContinues,continues],childIsLast)}};for(let i=0;i<roots.length;i++)walk(roots[i],0,[],i===roots.length-1);return result2}var SessionList=class{getSelectedSessionPath(){return this.filteredSessions[this.selectedIndex]?.session.path}get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(sessions,showCwd,sortMode,nameFilter,keybindings,currentSessionFilePath){this.allSessions=[],this.filteredSessions=[],this.selectedIndex=0,this.selectionTouched=!1,this.showCwd=!1,this.sortMode="threaded",this.nameFilter="all",this.showPath=!1,this.confirmingDeletePath=null,this.onExit=()=>{},this.maxVisible=10,this._focused=!1,this.allSessions=sessions,this.filteredSessions=[],this.searchInput=new Input,this.showCwd=showCwd,this.sortMode=sortMode,this.nameFilter=nameFilter,this.keybindings=keybindings,this.currentSessionCanonicalPath=canonicalizePath2(currentSessionFilePath),this.filterSessions(""),this.searchInput.onSubmit=()=>{if(this.filteredSessions[this.selectedIndex]){let selected=this.filteredSessions[this.selectedIndex];this.onSelect&&this.onSelect(selected.session.path)}}}setSortMode(sortMode){this.sortMode=sortMode,this.filterSessions(this.searchInput.getValue())}setNameFilter(nameFilter){this.nameFilter=nameFilter,this.filterSessions(this.searchInput.getValue())}setSessions(sessions,showCwd){let selectedPath=this.selectionTouched?this.getSelectedSessionPath():void 0;if(this.allSessions=sessions,this.showCwd=showCwd,this.filterSessions(this.searchInput.getValue()),!this.selectionTouched)this.selectedIndex=0;else if(selectedPath){let selectedIndex=this.filteredSessions.findIndex(node=>node.session.path===selectedPath);selectedIndex>=0&&(this.selectedIndex=selectedIndex)}}filterSessions(query){let trimmed=query.trim(),nameFiltered=this.nameFilter==="all"?this.allSessions:this.allSessions.filter(session=>hasSessionName(session));if(this.sortMode==="threaded"&&!trimmed){let roots=buildSessionTree(nameFiltered);this.filteredSessions=flattenSessionTree(roots)}else{let filtered=filterAndSortSessions(nameFiltered,query,this.sortMode,"all");this.filteredSessions=filtered.map(session=>({session,depth:0,isLast:!0,ancestorContinues:[]}))}this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredSessions.length-1))}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14,this.onDeleteConfirmationChange?.(path14)}startDeleteConfirmationForSelectedSession(){let selected=this.filteredSessions[this.selectedIndex];if(selected){if(this.isCurrentSessionPath(selected.session.path)){this.onError?.("Cannot delete the currently active session");return}this.setConfirmingDeletePath(selected.session.path)}}isCurrentSessionPath(path14){return this.currentSessionCanonicalPath?(canonicalizePath2(path14)??path14)===this.currentSessionCanonicalPath:!1}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredSessions.length===0){let emptyMessage;if(this.nameFilter==="named"){let toggleKey=keyText("app.session.toggleNamedFilter");this.showCwd?emptyMessage=` No named sessions found. Press ${toggleKey} to show all.`:emptyMessage=` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`}else this.showCwd?emptyMessage=" No sessions found":emptyMessage=" No sessions in current folder. Press Tab to view all.";return lines.push(theme.fg("muted",truncateToWidth(emptyMessage,width,"\u2026"))),lines}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredSessions.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredSessions.length);for(let i=startIndex;i<endIndex;i++){let node=this.filteredSessions[i],session=node.session,isSelected2=i===this.selectedIndex,isConfirmingDelete=session.path===this.confirmingDeletePath,isCurrent=this.isCurrentSessionPath(session.path),prefix=this.buildTreePrefix(node),hasName=!!session.name,normalizedMessage=(session.name??session.firstMessage).replace(/[\x00-\x1f\x7f]/g," ").trim(),age=formatSessionDate(session.modified),rightPart=`${String(session.messageCount)} ${age}`;this.showCwd&&session.cwd&&(rightPart=`${shortenPath(session.cwd)} ${rightPart}`),this.showPath&&(rightPart=`${shortenPath(session.path)} ${rightPart}`);let cursor=isSelected2?theme.fg("accent","\u203A "):" ",prefixWidth=visibleWidth(prefix),rightWidth=visibleWidth(rightPart)+2,availableForMsg=width-2-prefixWidth-rightWidth,truncatedMsg=truncateToWidth(normalizedMessage,Math.max(10,availableForMsg),"\u2026"),messageColor=null;isConfirmingDelete?messageColor="error":isCurrent?messageColor="accent":hasName&&(messageColor="warning");let styledMsg=messageColor?theme.fg(messageColor,truncatedMsg):truncatedMsg;isSelected2&&(styledMsg=theme.bold(styledMsg));let leftPart=cursor+theme.fg("dim",prefix)+styledMsg,leftWidth=visibleWidth(leftPart),spacing=Math.max(1,width-leftWidth-visibleWidth(rightPart)),styledRight=theme.fg(isConfirmingDelete?"error":"dim",rightPart),line=leftPart+" ".repeat(spacing)+styledRight;isSelected2&&(line=theme.bg("selectedBg",line)),lines.push(truncateToWidth(line,width))}if(startIndex>0||endIndex<this.filteredSessions.length){let scrollText=` (${this.selectedIndex+1}/${this.filteredSessions.length})`,scrollInfo=theme.fg("muted",truncateToWidth(scrollText,width,""));lines.push(scrollInfo)}return lines}buildTreePrefix(node){if(node.depth===0)return"";let parts=node.ancestorContinues.map(continues=>continues?"\u2502 ":" "),branch=node.isLast?"\u2514\u2500 ":"\u251C\u2500 ";return parts.join("")+branch}handleInput(keyData){let kb=getKeybindings();if(this.confirmingDeletePath!==null){if(kb.matches(keyData,"tui.select.confirm")){let pathToDelete=this.confirmingDeletePath;this.setConfirmingDeletePath(null),this.onDeleteSession?.(pathToDelete);return}if(kb.matches(keyData,"tui.select.cancel")){this.setConfirmingDeletePath(null);return}return}if(kb.matches(keyData,"tui.input.tab")){this.onToggleScope&&this.onToggleScope();return}if(kb.matches(keyData,"app.session.toggleSort")){this.onToggleSort?.();return}if(this.keybindings.matches(keyData,"app.session.toggleNamedFilter")){this.onToggleNameFilter?.();return}if(kb.matches(keyData,"app.session.togglePath")){this.showPath=!this.showPath,this.onTogglePath?.(this.showPath);return}if(kb.matches(keyData,"app.session.delete")){this.startDeleteConfirmationForSelectedSession();return}if(kb.matches(keyData,"app.session.rename")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onRenameSession?.(selected.session.path);return}if(kb.matches(keyData,"app.session.deleteNoninvasive")){if(this.searchInput.getValue().length>0){this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue());return}this.startDeleteConfirmationForSelectedSession();return}if(this.selectionTouched=!0,kb.matches(keyData,"tui.select.up"))this.selectedIndex=Math.max(0,this.selectedIndex-1);else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+1);else if(kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisible);else if(kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+this.maxVisible);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.session.path)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel&&this.onCancel():(this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue()))}};async function deleteSessionFile(sessionPath){let trashArgs=sessionPath.startsWith("-")?["--",sessionPath]:[sessionPath],trashResult=spawnSync3("trash",trashArgs,{encoding:"utf-8"}),getTrashErrorHint=()=>{let parts=[];trashResult.error&&parts.push(trashResult.error.message);let stderr=trashResult.stderr?.trim();return stderr&&parts.push(stderr.split(`
|
|
657
|
+
`){let selected=this.options[this.selectedIndex];selected&&this.onSelectCallback(selected)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}dispose(){this.countdown?.dispose()}};import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync7}from"node:fs";import{unlink}from"node:fs/promises";import*as os3 from"node:os";import{existsSync as existsSync6,readFileSync as readFileSync7}from"fs";import{join as join16}from"path";var modifiers=["ctrl","shift","alt","super"],baseKeyPattern=`(?:[a-z0-9]|${Object.values(Key).flatMap(value=>typeof value=="string"?[value.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&")]:[]).join("|")})`,duplicateModifierPattern=modifiers.map(modifier=>`${modifier}\\+.*${modifier}\\+`).join("|"),KeyIdSchema=typebox_exports.Unsafe(typebox_exports.String({pattern:`^(?!.*(?:${duplicateModifierPattern}))(?:(?:${modifiers.join("|")})\\+){0,4}${baseKeyPattern}$`,description:"Key identifier with optional ctrl, shift, alt, or super modifiers."}));function keybindingValueSchema(options){return typebox_exports.Union([KeyIdSchema,typebox_exports.Array(KeyIdSchema)],options)}var KeybindingValueSchema=keybindingValueSchema();var registered={},reserved=new Set,helpSections=new Map;function sameDefinition(left,right){return JSON.stringify(left)===JSON.stringify(right)}function registerKeybindings(definitions){for(let[id,definition]of Object.entries(definitions)){let existing=registered[id];if(existing&&!sameDefinition(existing,definition))throw new Error(`Keybinding ${id} is already registered with a different definition`);registered[id]=definition}}function getRegisteredKeybindings(){return{...registered}}function registerReservedKeybindings(...actions2){for(let action of actions2)reserved.add(action)}function getReservedKeybindings(){return reserved}function registerKeybindingHelpSection(section){let existing=helpSections.get(section.id);if(existing&&JSON.stringify(existing)!==JSON.stringify(section))throw new Error(`Keybinding help section ${section.id} is already registered with different content`);helpSections.set(section.id,section)}function getRegisteredKeybindingHelpSections(){return[...helpSections.values()]}function useWindowsKeybindings(platform3=process.platform,env2=process.env){return platform3==="win32"||platform3==="linux"&&!!(env2.WSL_DISTRO_NAME||env2.WSL_INTEROP)}var windowsKeybindings=useWindowsKeybindings(),APP_KEYBINDINGS={"app.interrupt":{defaultKeys:"escape",description:"Cancel or abort"},"app.clear":{defaultKeys:"ctrl+c",description:"Clear editor"},"app.exit":{defaultKeys:"ctrl+d",description:"Exit when editor is empty"},"app.suspend":{defaultKeys:process.platform==="win32"?[]:"ctrl+z",description:"Suspend to background"},"app.thinking.cycle":{defaultKeys:"shift+tab",description:"Cycle thinking level"},"app.thinking.save":{defaultKeys:"ctrl+s",description:"Save thinking level"},"app.model.cycleForward":{defaultKeys:"ctrl+p",description:"Cycle to next model"},"app.model.cycleBackward":{defaultKeys:windowsKeybindings?"alt+p":"shift+ctrl+p",description:"Cycle to previous model"},"app.model.select":{defaultKeys:"ctrl+l",description:"Open model selector"},"app.tools.expand":{defaultKeys:"ctrl+o",description:"Toggle tool output"},"app.question.pageUp":{defaultKeys:"alt+up",description:"Page up in question details"},"app.question.pageDown":{defaultKeys:"alt+down",description:"Page down in question details"},"app.thinking.toggle":{defaultKeys:"ctrl+t",description:"Toggle thinking blocks"},"app.session.toggleNamedFilter":{defaultKeys:"ctrl+n",description:"Toggle named session filter"},"app.editor.external":{defaultKeys:"ctrl+g",description:"Open external editor"},"app.message.copy":{defaultKeys:"ctrl+x",description:"Copy selection or last assistant message"},"app.message.followUp":{defaultKeys:windowsKeybindings?"ctrl+q":"alt+enter",description:"Queue follow-up message"},"app.message.dequeue":{defaultKeys:windowsKeybindings?"alt+q":"alt+up",description:"Restore queued messages"},"app.clipboard.pasteImage":{defaultKeys:windowsKeybindings?"alt+v":"ctrl+v",description:"Paste files on macOS, images, or text from clipboard"},"app.session.new":{defaultKeys:[],description:"Start a new session"},"app.session.tree":{defaultKeys:[],description:"Open session tree"},"app.session.fork":{defaultKeys:[],description:"Fork current session"},"app.session.resume":{defaultKeys:[],description:"Resume a session"},"app.tree.foldOrUp":{defaultKeys:process.platform==="darwin"?["alt+left","ctrl+left"]:["ctrl+left","alt+left"],description:"Fold tree branch or move up"},"app.tree.unfoldOrDown":{defaultKeys:process.platform==="darwin"?["alt+right","ctrl+right"]:["ctrl+right","alt+right"],description:"Unfold tree branch or move down"},"app.tree.editLabel":{defaultKeys:"shift+l",description:"Edit tree label"},"app.tree.toggleLabelTimestamp":{defaultKeys:"shift+t",description:"Toggle tree label timestamps"},"app.session.togglePath":{defaultKeys:"ctrl+p",description:"Toggle session path display"},"app.session.toggleSort":{defaultKeys:"ctrl+s",description:"Toggle session sort mode"},"app.session.rename":{defaultKeys:"ctrl+r",description:"Rename session"},"app.session.delete":{defaultKeys:"ctrl+d",description:"Delete session"},"app.session.deleteNoninvasive":{defaultKeys:"ctrl+backspace",description:"Delete session when query is empty"},"app.models.save":{defaultKeys:"ctrl+s",description:"Save model selection"},"app.models.enableAll":{defaultKeys:"ctrl+a",description:"Enable all models"},"app.models.clearAll":{defaultKeys:"ctrl+x",description:"Clear all models"},"app.models.toggleProvider":{defaultKeys:"ctrl+p",description:"Toggle all models for provider"},"app.models.reorderUp":{defaultKeys:"alt+up",description:"Move model up in order"},"app.models.reorderDown":{defaultKeys:"alt+down",description:"Move model down in order"},"app.tree.filter.default":{defaultKeys:"ctrl+d",description:"Tree filter: default view"},"app.tree.filter.noTools":{defaultKeys:"ctrl+t",description:"Tree filter: hide tool results"},"app.tree.filter.userOnly":{defaultKeys:"ctrl+u",description:"Tree filter: user messages only"},"app.tree.filter.labeledOnly":{defaultKeys:"ctrl+l",description:"Tree filter: labeled entries only"},"app.tree.filter.all":{defaultKeys:"ctrl+a",description:"Tree filter: show all entries"},"app.tree.filter.cycleForward":{defaultKeys:"ctrl+o",description:"Tree filter: cycle forward"},"app.tree.filter.cycleBackward":{defaultKeys:"shift+ctrl+o",description:"Tree filter: cycle backward"}},KEYBINDINGS={...TUI_KEYBINDINGS,"tui.editor.cursorLeft":{...TUI_KEYBINDINGS["tui.editor.cursorLeft"],defaultKeys:"left"},"tui.editor.undo":{...TUI_KEYBINDINGS["tui.editor.undo"],defaultKeys:process.platform==="win32"?"ctrl+z":windowsKeybindings?"alt+z":"ctrl+-"},"tui.altScreen.previousPrompt":{...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],defaultKeys:windowsKeybindings?"ctrl+up":["ctrl+shift+up","ctrl+up"]},"tui.altScreen.nextPrompt":{...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],defaultKeys:windowsKeybindings?"ctrl+down":["ctrl+shift+down","ctrl+down"]},"tui.altScreen.search":{...TUI_KEYBINDINGS["tui.altScreen.search"],defaultKeys:windowsKeybindings?"ctrl+f":"ctrl+shift+f"},...APP_KEYBINDINGS},KEYBINDING_NAME_MIGRATIONS={cursorUp:"tui.editor.cursorUp",cursorDown:"tui.editor.cursorDown",cursorLeft:"tui.editor.cursorLeft",cursorRight:"tui.editor.cursorRight",cursorWordLeft:"tui.editor.cursorWordLeft",cursorWordRight:"tui.editor.cursorWordRight",cursorLineStart:"tui.editor.cursorLineStart",cursorLineEnd:"tui.editor.cursorLineEnd",jumpForward:"tui.editor.jumpForward",jumpBackward:"tui.editor.jumpBackward",pageUp:"tui.editor.pageUp",pageDown:"tui.editor.pageDown",deleteCharBackward:"tui.editor.deleteCharBackward",deleteCharForward:"tui.editor.deleteCharForward",deleteWordBackward:"tui.editor.deleteWordBackward",deleteWordForward:"tui.editor.deleteWordForward",deleteToLineStart:"tui.editor.deleteToLineStart",deleteToLineEnd:"tui.editor.deleteToLineEnd",yank:"tui.editor.yank",yankPop:"tui.editor.yankPop",undo:"tui.editor.undo",newLine:"tui.input.newLine",submit:"tui.input.submit",tab:"tui.input.tab",copy:"tui.input.copy",selectUp:"tui.select.up",selectDown:"tui.select.down",selectPageUp:"tui.select.pageUp",selectPageDown:"tui.select.pageDown",selectConfirm:"tui.select.confirm",selectCancel:"tui.select.cancel",interrupt:"app.interrupt",clear:"app.clear",exit:"app.exit",suspend:"app.suspend",cycleThinkingLevel:"app.thinking.cycle",cycleModelForward:"app.model.cycleForward",cycleModelBackward:"app.model.cycleBackward",selectModel:"app.model.select",expandTools:"app.tools.expand",toggleThinking:"app.thinking.toggle",toggleSessionNamedFilter:"app.session.toggleNamedFilter",externalEditor:"app.editor.external",followUp:"app.message.followUp",dequeue:"app.message.dequeue",pasteImage:"app.clipboard.pasteImage",newSession:"app.session.new",tree:"app.session.tree",fork:"app.session.fork",resume:"app.session.resume",treeFoldOrUp:"app.tree.foldOrUp",treeUnfoldOrDown:"app.tree.unfoldOrDown",treeEditLabel:"app.tree.editLabel",treeToggleLabelTimestamp:"app.tree.toggleLabelTimestamp",toggleSessionPath:"app.session.togglePath",toggleSessionSort:"app.session.toggleSort",renameSession:"app.session.rename",deleteSession:"app.session.delete",deleteSessionNoninvasive:"app.session.deleteNoninvasive"};function isLegacyKeybindingName(key){return key in KEYBINDING_NAME_MIGRATIONS}var validateKeybindingValue=Compile(KeybindingValueSchema);function toKeybindingsConfig(value){let config={};for(let[key,binding]of Object.entries(value))key!=="$schema"&&validateKeybindingValue.Check(binding)&&(config[key]=binding);return config}function migrateKeybindingsConfig(rawConfig){let config={},migrated=!1;for(let[key,value]of Object.entries(rawConfig)){let nextKey=isLegacyKeybindingName(key)?KEYBINDING_NAME_MIGRATIONS[key]:key;if(nextKey!==key&&(migrated=!0),key!==nextKey&&Object.hasOwn(rawConfig,nextKey)){migrated=!0;continue}config[nextKey]=value}return{config:orderKeybindingsConfig(config),migrated}}function orderKeybindingsConfig(config){let ordered={};for(let keybinding of Object.keys(KEYBINDINGS))Object.hasOwn(config,keybinding)&&(ordered[keybinding]=config[keybinding]);let extras=Object.keys(config).filter(key=>!Object.hasOwn(ordered,key)).sort();for(let key of extras)ordered[key]=config[key];return ordered}function loadRawConfig(path14){if(existsSync6(path14))try{let parsed=JSON.parse(stripBom(readFileSync7(path14,"utf-8")));return typeof parsed!="object"||parsed===null?void 0:parsed}catch{return}}var KeybindingsManager2=class _KeybindingsManager extends KeybindingsManager{constructor(userBindings={},configPath){super({...KEYBINDINGS,...getRegisteredKeybindings()},userBindings),this.configPath=configPath}static create(agentDir=getAgentDir()){let configPath=join16(agentDir,"keybindings.json"),userBindings=_KeybindingsManager.loadFromFile(configPath);return new _KeybindingsManager(userBindings,configPath)}reload(){this.configPath&&this.setUserBindings(_KeybindingsManager.loadFromFile(this.configPath))}getEffectiveConfig(){return this.getResolvedBindings()}static loadFromFile(path14){let rawConfig=loadRawConfig(path14);return rawConfig?toKeybindingsConfig(migrateKeybindingsConfig(rawConfig).config):{}}};function normalizeWhitespaceLower(text2){return text2.toLowerCase().replace(/\s+/g," ").trim()}function getSessionSearchText(session){return`${session.id} ${session.name??""} ${session.allMessagesText} ${session.cwd}`}function hasSessionName(session){return!!session.name?.trim()}function matchesNameFilter(session,filter2){return filter2==="all"?!0:hasSessionName(session)}function parseSearchQuery(query){let trimmed=query.trim();if(!trimmed)return{mode:"tokens",tokens:[],regex:null};if(trimmed.startsWith("re:")){let pattern=trimmed.slice(3).trim();if(!pattern)return{mode:"regex",tokens:[],regex:null,error:"Empty regex"};try{return{mode:"regex",tokens:[],regex:new RegExp(pattern,"i")}}catch(err){let msg=err instanceof Error?err.message:String(err);return{mode:"regex",tokens:[],regex:null,error:msg}}}let tokens2=[],buf="",inQuote=!1,hadUnclosedQuote=!1,flush=kind=>{let v2=buf.trim();buf="",v2&&tokens2.push({kind,value:v2})};for(let i=0;i<trimmed.length;i++){let ch=trimmed[i];if(ch==='"'){inQuote?(flush("phrase"),inQuote=!1):(flush("fuzzy"),inQuote=!0);continue}if(!inQuote&&/\s/.test(ch)){flush("fuzzy");continue}buf+=ch}return inQuote&&(hadUnclosedQuote=!0),hadUnclosedQuote?{mode:"tokens",tokens:trimmed.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0).map(t=>({kind:"fuzzy",value:t})),regex:null}:(flush(inQuote?"phrase":"fuzzy"),{mode:"tokens",tokens:tokens2,regex:null})}function matchSession(session,parsed){let text2=getSessionSearchText(session);if(parsed.mode==="regex"){if(!parsed.regex)return{matches:!1,score:0};let idx=text2.search(parsed.regex);return idx<0?{matches:!1,score:0}:{matches:!0,score:idx*.1}}if(parsed.tokens.length===0)return{matches:!0,score:0};let totalScore=0,normalizedText=null;for(let token of parsed.tokens){if(token.kind==="phrase"){normalizedText===null&&(normalizedText=normalizeWhitespaceLower(text2));let phrase=normalizeWhitespaceLower(token.value);if(!phrase)continue;let idx=normalizedText.indexOf(phrase);if(idx<0)return{matches:!1,score:0};totalScore+=idx*.1;continue}let m2=fuzzyMatch(token.value,text2);if(!m2.matches)return{matches:!1,score:0};totalScore+=m2.score}return{matches:!0,score:totalScore}}function filterAndSortSessions(sessions,query,sortMode,nameFilter="all"){let nameFiltered=nameFilter==="all"?sessions:sessions.filter(session=>matchesNameFilter(session,nameFilter));if(!query.trim())return nameFiltered;let parsed=parseSearchQuery(query);if(parsed.error)return[];if(sortMode==="recent"){let filtered=[];for(let s of nameFiltered)matchSession(s,parsed).matches&&filtered.push(s);return filtered}let scored=[];for(let s of nameFiltered){let res=matchSession(s,parsed);res.matches&&scored.push({session:s,score:res.score})}return scored.sort((a,b2)=>a.score!==b2.score?a.score-b2.score:b2.session.modified.getTime()-a.session.modified.getTime()),scored.map(r=>r.session)}function shortenPath(path14){let home=os3.homedir();return path14&&(path14.startsWith(home)?`~${path14.slice(home.length)}`:path14)}function formatSessionDate(date){let diffMs=new Date().getTime()-date.getTime(),diffMins=Math.floor(diffMs/6e4),diffHours=Math.floor(diffMs/36e5),diffDays=Math.floor(diffMs/864e5);return diffMins<1?"now":diffMins<60?`${diffMins}m`:diffHours<24?`${diffHours}h`:diffDays<7?`${diffDays}d`:diffDays<30?`${Math.floor(diffDays/7)}w`:diffDays<365?`${Math.floor(diffDays/30)}mo`:`${Math.floor(diffDays/365)}y`}function canonicalizePath2(path14){return path14&&canonicalizePath(path14)}var SessionSelectorHeader=class{constructor(scope,sortMode,nameFilter,requestRender){this.loading=!1,this.loadProgress=null,this.showPath=!1,this.confirmingDeletePath=null,this.statusMessage=null,this.statusTimeout=null,this.showRenameHint=!1,this.scope=scope,this.sortMode=sortMode,this.nameFilter=nameFilter,this.requestRender=requestRender}setScope(scope){this.scope=scope}setSortMode(sortMode){this.sortMode=sortMode}setNameFilter(nameFilter){this.nameFilter=nameFilter}setLoading(loading){this.loading=loading,this.loadProgress=null}setProgress(loaded,total){this.loadProgress={loaded,total}}setShowPath(showPath){this.showPath=showPath}setShowRenameHint(show){this.showRenameHint=show}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14}clearStatusTimeout(){this.statusTimeout&&(clearTimeout(this.statusTimeout),this.statusTimeout=null)}setStatusMessage(msg,autoHideMs){this.clearStatusTimeout(),this.statusMessage=msg,!(!msg||!autoHideMs)&&(this.statusTimeout=setTimeout(()=>{this.statusMessage=null,this.statusTimeout=null,this.requestRender()},autoHideMs))}invalidate(){}render(width){let title=this.scope==="current"?"Resume Session (Current Folder)":"Resume Session (All)",leftText=theme.bold(title),sortLabel=this.sortMode==="threaded"?"Threaded":this.sortMode==="recent"?"Recent":"Fuzzy",sortText=theme.fg("muted","Sort: ")+theme.fg("accent",sortLabel),nameLabel=this.nameFilter==="all"?"All":"Named",nameText=theme.fg("muted","Name: ")+theme.fg("accent",nameLabel),scopeText;if(this.loading){let progressText=this.loadProgress?`${this.loadProgress.loaded}/${this.loadProgress.total}`:"...";scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent",`Loading ${progressText}`)}`}else this.scope==="current"?scopeText=`${theme.fg("accent","\u25C9 Current Folder")}${theme.fg("muted"," | \u25CB All")}`:scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent","\u25C9 All")}`;let rightText=truncateToWidth(`${scopeText} ${nameText} ${sortText}`,width,""),availableLeft=Math.max(0,width-visibleWidth(rightText)-1),left=truncateToWidth(leftText,availableLeft,""),spacing=Math.max(0,width-visibleWidth(left)-visibleWidth(rightText)),hintLine1,hintLine2;if(this.confirmingDeletePath!==null){let confirmHint=`Delete session? ${keyHint("tui.select.confirm","confirm")} \xB7 ${keyHint("tui.select.cancel","cancel")}`;hintLine1=theme.fg("error",truncateToWidth(confirmHint,width,"\u2026")),hintLine2=""}else if(this.statusMessage){let color2=this.statusMessage.type==="error"?"error":"accent";hintLine1=theme.fg(color2,truncateToWidth(this.statusMessage.message,width,"\u2026")),hintLine2=""}else{let pathState=this.showPath?"(on)":"(off)",sep13=theme.fg("muted"," \xB7 "),hint1=keyHint("tui.input.tab","scope")+sep13+theme.fg("muted",'re:<pattern> regex \xB7 "phrase" exact'),hint2Parts=[keyHint("app.session.toggleSort","sort"),keyHint("app.session.toggleNamedFilter","named"),keyHint("app.session.delete","delete"),keyHint("app.session.togglePath",`path ${pathState}`)];this.showRenameHint&&hint2Parts.push(keyHint("app.session.rename","rename"));let hint2=hint2Parts.join(sep13);hintLine1=truncateToWidth(hint1,width,"\u2026"),hintLine2=truncateToWidth(hint2,width,"\u2026")}return[`${left}${" ".repeat(spacing)}${rightText}`,hintLine1,hintLine2]}};function buildSessionTree(sessions){let byPath=new Map;for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path;byPath.set(sessionPath,{session,children:[],latestActivity:session.modified.getTime()})}let roots=[];for(let session of sessions){let sessionPath=canonicalizePath2(session.path)??session.path,node=byPath.get(sessionPath),parentPath=canonicalizePath2(session.parentSessionPath);parentPath&&byPath.has(parentPath)?byPath.get(parentPath).children.push(node):roots.push(node)}let updateLatestActivity=node=>{let latestActivity=node.session.modified.getTime();for(let child of node.children)latestActivity=Math.max(latestActivity,updateLatestActivity(child));return node.latestActivity=latestActivity,latestActivity};for(let root of roots)updateLatestActivity(root);let sortNodes=nodes=>{nodes.sort((a,b2)=>b2.latestActivity-a.latestActivity);for(let node of nodes)sortNodes(node.children)};return sortNodes(roots),roots}function flattenSessionTree(roots){let result2=[],walk=(node,depth,ancestorContinues,isLast)=>{result2.push({session:node.session,depth,isLast,ancestorContinues});for(let i=0;i<node.children.length;i++){let childIsLast=i===node.children.length-1,continues=depth>0?!isLast:!1;walk(node.children[i],depth+1,[...ancestorContinues,continues],childIsLast)}};for(let i=0;i<roots.length;i++)walk(roots[i],0,[],i===roots.length-1);return result2}var SessionList=class{getSelectedSessionPath(){return this.filteredSessions[this.selectedIndex]?.session.path}get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(sessions,showCwd,sortMode,nameFilter,keybindings,currentSessionFilePath){this.allSessions=[],this.filteredSessions=[],this.selectedIndex=0,this.selectionTouched=!1,this.showCwd=!1,this.sortMode="threaded",this.nameFilter="all",this.showPath=!1,this.confirmingDeletePath=null,this.onExit=()=>{},this.maxVisible=10,this._focused=!1,this.allSessions=sessions,this.filteredSessions=[],this.searchInput=new Input,this.showCwd=showCwd,this.sortMode=sortMode,this.nameFilter=nameFilter,this.keybindings=keybindings,this.currentSessionCanonicalPath=canonicalizePath2(currentSessionFilePath),this.filterSessions(""),this.searchInput.onSubmit=()=>{if(this.filteredSessions[this.selectedIndex]){let selected=this.filteredSessions[this.selectedIndex];this.onSelect&&this.onSelect(selected.session.path)}}}setSortMode(sortMode){this.sortMode=sortMode,this.filterSessions(this.searchInput.getValue())}setNameFilter(nameFilter){this.nameFilter=nameFilter,this.filterSessions(this.searchInput.getValue())}setSessions(sessions,showCwd){let selectedPath=this.selectionTouched?this.getSelectedSessionPath():void 0;if(this.allSessions=sessions,this.showCwd=showCwd,this.filterSessions(this.searchInput.getValue()),!this.selectionTouched)this.selectedIndex=0;else if(selectedPath){let selectedIndex=this.filteredSessions.findIndex(node=>node.session.path===selectedPath);selectedIndex>=0&&(this.selectedIndex=selectedIndex)}}filterSessions(query){let trimmed=query.trim(),nameFiltered=this.nameFilter==="all"?this.allSessions:this.allSessions.filter(session=>hasSessionName(session));if(this.sortMode==="threaded"&&!trimmed){let roots=buildSessionTree(nameFiltered);this.filteredSessions=flattenSessionTree(roots)}else{let filtered=filterAndSortSessions(nameFiltered,query,this.sortMode,"all");this.filteredSessions=filtered.map(session=>({session,depth:0,isLast:!0,ancestorContinues:[]}))}this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredSessions.length-1))}setConfirmingDeletePath(path14){this.confirmingDeletePath=path14,this.onDeleteConfirmationChange?.(path14)}startDeleteConfirmationForSelectedSession(){let selected=this.filteredSessions[this.selectedIndex];if(selected){if(this.isCurrentSessionPath(selected.session.path)){this.onError?.("Cannot delete the currently active session");return}this.setConfirmingDeletePath(selected.session.path)}}isCurrentSessionPath(path14){return this.currentSessionCanonicalPath?(canonicalizePath2(path14)??path14)===this.currentSessionCanonicalPath:!1}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredSessions.length===0){let emptyMessage;if(this.nameFilter==="named"){let toggleKey=keyText("app.session.toggleNamedFilter");this.showCwd?emptyMessage=` No named sessions found. Press ${toggleKey} to show all.`:emptyMessage=` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`}else this.showCwd?emptyMessage=" No sessions found":emptyMessage=" No sessions in current folder. Press Tab to view all.";return lines.push(theme.fg("muted",truncateToWidth(emptyMessage,width,"\u2026"))),lines}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredSessions.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredSessions.length);for(let i=startIndex;i<endIndex;i++){let node=this.filteredSessions[i],session=node.session,isSelected2=i===this.selectedIndex,isConfirmingDelete=session.path===this.confirmingDeletePath,isCurrent=this.isCurrentSessionPath(session.path),prefix=this.buildTreePrefix(node),hasName=!!session.name,normalizedMessage=(session.name??session.firstMessage).replace(/[\x00-\x1f\x7f]/g," ").trim(),age=formatSessionDate(session.modified),rightPart=`${String(session.messageCount)} ${age}`;this.showCwd&&session.cwd&&(rightPart=`${shortenPath(session.cwd)} ${rightPart}`),this.showPath&&(rightPart=`${shortenPath(session.path)} ${rightPart}`);let cursor=isSelected2?theme.fg("accent","\u203A "):" ",prefixWidth=visibleWidth(prefix),rightWidth=visibleWidth(rightPart)+2,availableForMsg=width-2-prefixWidth-rightWidth,truncatedMsg=truncateToWidth(normalizedMessage,Math.max(10,availableForMsg),"\u2026"),messageColor=null;isConfirmingDelete?messageColor="error":isCurrent?messageColor="accent":hasName&&(messageColor="warning");let styledMsg=messageColor?theme.fg(messageColor,truncatedMsg):truncatedMsg;isSelected2&&(styledMsg=theme.bold(styledMsg));let leftPart=cursor+theme.fg("dim",prefix)+styledMsg,leftWidth=visibleWidth(leftPart),spacing=Math.max(1,width-leftWidth-visibleWidth(rightPart)),styledRight=theme.fg(isConfirmingDelete?"error":"dim",rightPart),line=leftPart+" ".repeat(spacing)+styledRight;isSelected2&&(line=theme.bg("selectedBg",line)),lines.push(truncateToWidth(line,width))}if(startIndex>0||endIndex<this.filteredSessions.length){let scrollText=` (${this.selectedIndex+1}/${this.filteredSessions.length})`,scrollInfo=theme.fg("muted",truncateToWidth(scrollText,width,""));lines.push(scrollInfo)}return lines}buildTreePrefix(node){if(node.depth===0)return"";let parts=node.ancestorContinues.map(continues=>continues?"\u2502 ":" "),branch=node.isLast?"\u2514\u2500 ":"\u251C\u2500 ";return parts.join("")+branch}handleInput(keyData){let kb=getKeybindings();if(this.confirmingDeletePath!==null){if(kb.matches(keyData,"tui.select.confirm")){let pathToDelete=this.confirmingDeletePath;this.setConfirmingDeletePath(null),this.onDeleteSession?.(pathToDelete);return}if(kb.matches(keyData,"tui.select.cancel")){this.setConfirmingDeletePath(null);return}return}if(kb.matches(keyData,"tui.input.tab")){this.onToggleScope&&this.onToggleScope();return}if(kb.matches(keyData,"app.session.toggleSort")){this.onToggleSort?.();return}if(this.keybindings.matches(keyData,"app.session.toggleNamedFilter")){this.onToggleNameFilter?.();return}if(kb.matches(keyData,"app.session.togglePath")){this.showPath=!this.showPath,this.onTogglePath?.(this.showPath);return}if(kb.matches(keyData,"app.session.delete")){this.startDeleteConfirmationForSelectedSession();return}if(kb.matches(keyData,"app.session.rename")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onRenameSession?.(selected.session.path);return}if(kb.matches(keyData,"app.session.deleteNoninvasive")){if(this.searchInput.getValue().length>0){this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue());return}this.startDeleteConfirmationForSelectedSession();return}if(this.selectionTouched=!0,kb.matches(keyData,"tui.select.up"))this.selectedIndex=Math.max(0,this.selectedIndex-1);else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+1);else if(kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisible);else if(kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+this.maxVisible);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.session.path)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel&&this.onCancel():(this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue()))}};async function deleteSessionFile(sessionPath){let trashArgs=sessionPath.startsWith("-")?["--",sessionPath]:[sessionPath],trashResult=spawnSync3("trash",trashArgs,{encoding:"utf-8"}),getTrashErrorHint=()=>{let parts=[];trashResult.error&&parts.push(trashResult.error.message);let stderr=trashResult.stderr?.trim();return stderr&&parts.push(stderr.split(`
|
|
658
658
|
`)[0]??stderr),parts.length===0?null:`trash: ${parts.join(" \xB7 ").slice(0,200)}`};if(trashResult.status===0||!existsSync7(sessionPath))return{ok:!0,method:"trash"};try{return await unlink(sessionPath),{ok:!0,method:"unlink"}}catch(err){let unlinkError=err instanceof Error?err.message:String(err),trashErrorHint=getTrashErrorHint();return{ok:!1,method:"unlink",error:trashErrorHint?`${unlinkError} (${trashErrorHint})`:unlinkError}}}var SessionSelectorComponent=class extends Container{handleInput(data){if(this.mode==="rename"){if(getKeybindings().matches(data,"tui.select.cancel")){this.exitRenameMode();return}this.renameInput.handleInput(data);return}this.sessionList.handleInput(data)}get focused(){return this._focused}set focused(value){this._focused=value,this.sessionList.focused=value,this.renameInput.focused=value,value&&this.mode==="rename"&&(this.renameInput.focused=!0)}buildBaseLayout(content,options){this.clear(),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s))),this.addChild(new Spacer(1)),(options?.showHeader??!0)&&(this.addChild(this.header),this.addChild(new Spacer(1))),this.addChild(content),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s)))}constructor(currentSessionsLoader,allSessionsLoader,onSelect,onCancel,onExit,requestRender,options,currentSessionFilePath){super(),this.canRename=!0,this.scope="current",this.sortMode="threaded",this.nameFilter="all",this.currentSessions=null,this.allSessions=null,this.currentLoad=null,this.allLoad=null,this.mode="list",this.renameInput=new Input,this.renameTargetPath=null,this._focused=!1,this.keybindings=options?.keybindings??KeybindingsManager2.create(),this.currentSessionsLoader=currentSessionsLoader,this.allSessionsLoader=allSessionsLoader,this.requestRender=requestRender,this.header=new SessionSelectorHeader(this.scope,this.sortMode,this.nameFilter,this.requestRender);let renameSession=options?.renameSession;this.renameSession=renameSession,this.canRename=!!renameSession,this.header.setShowRenameHint(options?.showRenameHint??this.canRename),this.sessionList=new SessionList([],!1,this.sortMode,this.nameFilter,this.keybindings,currentSessionFilePath),this.buildBaseLayout(this.sessionList),this.renameInput.onSubmit=value=>{this.confirmRename(value)};let clearStatusMessage=()=>this.header.setStatusMessage(null);this.sessionList.onSelect=sessionPath=>{clearStatusMessage(),this.cancelLoads(),onSelect(sessionPath)},this.sessionList.onCancel=()=>{clearStatusMessage(),this.cancelLoads(),onCancel()},this.sessionList.onExit=()=>{clearStatusMessage(),this.cancelLoads(),onExit()},this.sessionList.onToggleScope=()=>this.toggleScope(),this.sessionList.onToggleSort=()=>this.toggleSortMode(),this.sessionList.onToggleNameFilter=()=>this.toggleNameFilter(),this.sessionList.onRenameSession=sessionPath=>{if(!renameSession||(this.scope==="current"?this.currentLoad:this.allLoad))return;let session=(this.scope==="all"?this.allSessions??[]:this.currentSessions??[]).find(s=>s.path===sessionPath);this.enterRenameMode(sessionPath,session?.name)},this.sessionList.onTogglePath=showPath=>{this.header.setShowPath(showPath),this.requestRender()},this.sessionList.onDeleteConfirmationChange=path14=>{this.header.setConfirmingDeletePath(path14),this.requestRender()},this.sessionList.onError=msg=>{this.header.setStatusMessage({type:"error",message:msg},3e3),this.requestRender()},this.sessionList.onDeleteSession=async sessionPath=>{let result2=await deleteSessionFile(sessionPath);if(result2.ok){this.currentSessions&&(this.currentSessions=this.currentSessions.filter(s=>s.path!==sessionPath)),this.allSessions&&(this.allSessions=this.allSessions.filter(s=>s.path!==sessionPath));let sessions=this.scope==="all"?this.allSessions??[]:this.currentSessions??[],showCwd=this.scope==="all";this.sessionList.setSessions(sessions,showCwd);let msg=result2.method==="trash"?"Session moved to trash":"Session deleted";this.header.setStatusMessage({type:"info",message:msg},2e3),await this.refreshSessionsAfterMutation()}else{let errorMessage9=result2.error??"Unknown error";this.header.setStatusMessage({type:"error",message:`Failed to delete: ${errorMessage9}`},3e3)}this.requestRender()},this.loadScope("current")}cancelLoads(){this.currentLoad&&(this.currentLoad.abort(),this.currentLoad=null,this.currentSessions=null),this.allLoad&&(this.allLoad.abort(),this.allLoad=null,this.allSessions=null)}enterRenameMode(sessionPath,currentName){this.mode="rename",this.renameTargetPath=sessionPath,this.renameInput.setValue(currentName??""),this.renameInput.focused=!0;let panel=new Container;panel.addChild(new Text(theme.bold("Rename Session"),1,0)),panel.addChild(new Spacer(1)),panel.addChild(this.renameInput),panel.addChild(new Spacer(1)),panel.addChild(new Text(theme.fg("muted",`${keyText("tui.select.confirm")} to save \xB7 ${keyText("tui.select.cancel")} to cancel`),1,0)),this.buildBaseLayout(panel,{showHeader:!1}),this.requestRender()}exitRenameMode(){this.mode="list",this.renameTargetPath=null,this.buildBaseLayout(this.sessionList),this.requestRender()}async confirmRename(value){let next=value.trim();if(!next)return;let target=this.renameTargetPath;if(!target){this.exitRenameMode();return}let renameSession=this.renameSession;if(!renameSession){this.exitRenameMode();return}try{await renameSession(target,next),await this.refreshSessionsAfterMutation()}finally{this.exitRenameMode()}}async loadScope(scope){if(scope==="current"?this.currentLoad:this.allLoad)return;let showCwd=scope==="all",controller=new AbortController;scope==="current"?this.currentLoad=controller:this.allLoad=controller,this.header.setScope(scope),this.header.setLoading(!0),this.requestRender();let isActive=()=>(scope==="current"?this.currentLoad:this.allLoad)===controller,onProgress=(loaded,total,partialSessions)=>{if(isActive()){if(partialSessions){let sessions=[...partialSessions];scope==="current"?this.currentSessions=sessions:this.allSessions=sessions,scope===this.scope&&this.sessionList.setSessions(sessions,showCwd)}scope===this.scope&&(this.header.setProgress(loaded,total),this.requestRender())}};try{let sessions=await(scope==="current"?this.currentSessionsLoader(onProgress,controller.signal):this.allSessionsLoader(onProgress,controller.signal));if(!isActive()||(scope==="current"?(this.currentSessions=sessions,this.currentLoad=null):(this.allSessions=sessions,this.allLoad=null),scope!==this.scope))return;this.header.setLoading(!1),this.sessionList.setSessions(sessions,showCwd),this.requestRender()}catch(err){if(!isActive()||(scope==="current"?(this.currentLoad=null,this.currentSessions=null):(this.allLoad=null,this.allSessions=null),scope!==this.scope))return;let message=err instanceof Error?err.message:String(err);this.header.setLoading(!1),this.header.setStatusMessage({type:"error",message:`Failed to load sessions: ${message}`},4e3),this.sessionList.setSessions([],showCwd),this.requestRender()}}toggleSortMode(){this.sortMode=this.sortMode==="threaded"?"recent":this.sortMode==="recent"?"relevance":"threaded",this.header.setSortMode(this.sortMode),this.sessionList.setSortMode(this.sortMode),this.requestRender()}toggleNameFilter(){this.nameFilter=this.nameFilter==="all"?"named":"all",this.header.setNameFilter(this.nameFilter),this.sessionList.setNameFilter(this.nameFilter),this.requestRender()}async refreshSessionsAfterMutation(){this.cancelLoads(),this.currentSessions=null,this.allSessions=null,await this.loadScope(this.scope)}toggleScope(){this.scope=this.scope==="current"?"all":"current";let sessions=this.scope==="current"?this.currentSessions:this.allSessions,loading=(this.scope==="current"?this.currentLoad:this.allLoad)!==null;this.header.setScope(this.scope),this.header.setLoading(loading),this.sessionList.setSessions(sessions??[],this.scope==="all"),this.requestRender(),sessions===null&&!loading&&this.loadScope(this.scope)}getSessionList(){return this.sessionList}};var import_yaml=__toESM(require_dist(),1);var normalizeNewlines=value=>value.replace(/\r\n/g,`
|
|
659
659
|
`).replace(/\r/g,`
|
|
660
660
|
`),extractFrontmatter=content=>{let normalized=normalizeNewlines(stripBom(content));if(!normalized.startsWith("---"))return{yamlString:null,body:normalized};let endIndex=normalized.indexOf(`
|
|
661
661
|
---`,3);return endIndex===-1?{yamlString:null,body:normalized}:{yamlString:normalized.slice(4,endIndex),body:normalized.slice(endIndex+4).trim()}},parseFrontmatter=content=>{let{yamlString,body:body2}=extractFrontmatter(content);return yamlString?{frontmatter:(0,import_yaml.parse)(yamlString)??{},body:body2}:{frontmatter:{},body:body2}},stripFrontmatter=content=>parseFrontmatter(content).body;var import_ignore2=__toESM(require_ignore(),1);import{existsSync as existsSync8,readdirSync as readdirSync4,readFileSync as readFileSync8,statSync as statSync5}from"fs";import{basename as basename4,dirname as dirname10,join as join17,relative as relative3,resolve as resolve3,sep as sep5}from"path";var MAX_NAME_LENGTH=64,MAX_DESCRIPTION_LENGTH=1024,IGNORE_FILE_NAMES2=[".gitignore",".ignore",".fdignore"];function toPosixPath2(p){return p.split(sep5).join("/")}function prefixIgnorePattern2(line,prefix){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#")&&!trimmed.startsWith("\\#"))return null;let pattern=line,negated=!1;pattern.startsWith("!")?(negated=!0,pattern=pattern.slice(1)):pattern.startsWith("\\!")&&(pattern=pattern.slice(1)),pattern.startsWith("/")&&(pattern=pattern.slice(1));let prefixed=prefix?`${prefix}${pattern}`:pattern;return negated?`!${prefixed}`:prefixed}function addIgnoreRules2(ig,dir,rootDir){let relativeDir=relative3(rootDir,dir),prefix=relativeDir?`${toPosixPath2(relativeDir)}/`:"";for(let filename of IGNORE_FILE_NAMES2){let ignorePath=join17(dir,filename);if(existsSync8(ignorePath))try{let patterns=readFileSync8(ignorePath,"utf-8").split(/\r?\n/).map(line=>prefixIgnorePattern2(line,prefix)).filter(line=>!!line);patterns.length>0&&ig.add(patterns)}catch{}}}function validateName(name){let errors=[];return name.length>MAX_NAME_LENGTH&&errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`),/^[a-z0-9-]+$/.test(name)||errors.push("name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)"),(name.startsWith("-")||name.endsWith("-"))&&errors.push("name must not start or end with a hyphen"),name.includes("--")&&errors.push("name must not contain consecutive hyphens"),errors}function validateDescription(description){let errors=[];return typeof description!="string"||description.trim()===""?errors.push("description is required"):description.length>MAX_DESCRIPTION_LENGTH&&errors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`),errors}function createSkillSourceInfo(filePath,baseDir,source){switch(source){case"user":return createSyntheticSourceInfo(filePath,{source:"local",scope:"user",baseDir});case"project":return createSyntheticSourceInfo(filePath,{source:"local",scope:"project",baseDir});case"path":return createSyntheticSourceInfo(filePath,{source:"local",baseDir});default:return createSyntheticSourceInfo(filePath,{source,baseDir})}}function loadSkillsFromDir(options){let{dir,source}=options;return loadSkillsFromDirInternal(dir,source,!0)}function loadSkillsFromDirInternal(dir,source,includeRootFiles,ignoreMatcher,rootDir){let skills=[],diagnostics=[];if(!existsSync8(dir))return{skills,diagnostics};let root=rootDir??dir,ig=ignoreMatcher??(0,import_ignore2.default)();addIgnoreRules2(ig,dir,root);try{let entries=readdirSync4(dir,{withFileTypes:!0});for(let entry of entries){if(entry.name!=="SKILL.md")continue;let fullPath=join17(dir,entry.name),isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync5(fullPath).isFile()}catch{continue}let relPath=toPosixPath2(relative3(root,fullPath));if(!isFile||ig.ignores(relPath))continue;let result2=loadSkillFromFile(fullPath,source);return result2.skill&&skills.push(result2.skill),diagnostics.push(...result2.diagnostics),{skills,diagnostics}}for(let entry of entries){if(entry.name.startsWith(".")||entry.name==="node_modules")continue;let fullPath=join17(dir,entry.name),isDirectory=entry.isDirectory(),isFile=entry.isFile();if(entry.isSymbolicLink())try{let stats=statSync5(fullPath);isDirectory=stats.isDirectory(),isFile=stats.isFile()}catch{continue}let relPath=toPosixPath2(relative3(root,fullPath)),ignorePath=isDirectory?`${relPath}/`:relPath;if(ig.ignores(ignorePath))continue;if(isDirectory){let subResult=loadSkillsFromDirInternal(fullPath,source,!1,ig,root);skills.push(...subResult.skills),diagnostics.push(...subResult.diagnostics);continue}if(!isFile||!includeRootFiles||!entry.name.endsWith(".md"))continue;let result2=loadSkillFromFile(fullPath,source);result2.skill&&skills.push(result2.skill),diagnostics.push(...result2.diagnostics)}}catch{}return{skills,diagnostics}}function loadSkillFromFile(filePath,source){let diagnostics=[],isDeclaredSkill=basename4(filePath)==="SKILL.md",rawContent;try{rawContent=readFileSync8(filePath,"utf-8")}catch(error){let message=error instanceof Error?error.message:"failed to read skill file";return diagnostics.push({type:"warning",message,path:filePath}),{skill:null,diagnostics}}let frontmatter;try{({frontmatter}=parseFrontmatter(rawContent))}catch(error){if(isDeclaredSkill){let message=error instanceof Error?error.message:"failed to parse skill file";diagnostics.push({type:"warning",message,path:filePath})}return{skill:null,diagnostics}}let description=frontmatter.description,hasDescription=typeof description=="string"&&description.trim()!=="";if(!isDeclaredSkill&&!hasDescription)return{skill:null,diagnostics};let skillDir=dirname10(filePath),parentDirName=basename4(skillDir),descErrors=validateDescription(description);for(let error of descErrors)diagnostics.push({type:"warning",message:error,path:filePath});let name=(typeof frontmatter.name=="string"?frontmatter.name:void 0)||parentDirName,nameErrors=validateName(name);for(let error of nameErrors)diagnostics.push({type:"warning",message:error,path:filePath});return hasDescription?{skill:{name,description,filePath,baseDir:skillDir,sourceInfo:createSkillSourceInfo(filePath,skillDir,source),disableModelInvocation:frontmatter["disable-model-invocation"]===!0},diagnostics}:{skill:null,diagnostics}}function formatSkillsForPrompt(skills,fileReadTool="read"){let visibleSkills=skills.filter(s=>!s.disableModelInvocation);if(visibleSkills.length===0)return"";let lines=[`
|
|
662
662
|
|
|
663
663
|
The following skills provide specialized instructions for specific tasks.`,fileReadTool==="read"?"Use the read tool to load a skill's file when the task matches its description.":fileReadTool==="bash"?"Use bash to load a skill's file when the task matches its description.":"Load a skill's file when the task matches its description.","When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.","","<available_skills>"];for(let skill of visibleSkills)lines.push(" <skill>"),lines.push(` <name>${escapeXml(skill.name)}</name>`),lines.push(` <description>${escapeXml(skill.description)}</description>`),lines.push(` <location>${escapeXml(skill.filePath)}</location>`),lines.push(" </skill>");return lines.push("</available_skills>"),lines.join(`
|
|
664
|
-
`)}function escapeXml(str2){return str2.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function loadSkills(options){let{agentDir,skillPaths,includeDefaults}=options,resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(agentDir??getAgentDir()),skillMap=new Map,realPathSet=new Set,allDiagnostics=[],collisionDiagnostics=[];function addSkills(result2){allDiagnostics.push(...result2.diagnostics);for(let skill of result2.skills){let realPath=canonicalizePath(skill.filePath);if(realPathSet.has(realPath))continue;let existing=skillMap.get(skill.name);existing?collisionDiagnostics.push({type:"collision",message:`name "${skill.name}" collision`,path:skill.filePath,collision:{resourceType:"skill",name:skill.name,winnerPath:existing.filePath,loserPath:skill.filePath}}):(skillMap.set(skill.name,skill),realPathSet.add(realPath))}}includeDefaults&&(addSkills(loadSkillsFromDirInternal(join17(resolvedAgentDir,"skills"),"user",!0)),addSkills(loadSkillsFromDirInternal(resolve3(resolvedCwd,CONFIG_DIR_NAME,"skills"),"project",!0)));let userSkillsDir=join17(resolvedAgentDir,"skills"),projectSkillsDir=resolve3(resolvedCwd,CONFIG_DIR_NAME,"skills"),isUnderPath=(target,root)=>{let normalizedRoot=resolve3(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep5)?normalizedRoot:`${normalizedRoot}${sep5}`;return target.startsWith(prefix)},getSource=resolvedPath=>{if(!includeDefaults){if(isUnderPath(resolvedPath,userSkillsDir))return"user";if(isUnderPath(resolvedPath,projectSkillsDir))return"project"}return"path"};for(let rawPath of skillPaths){let resolvedPath=resolvePath(rawPath,resolvedCwd,{trim:!0});if(!existsSync8(resolvedPath)){allDiagnostics.push({type:"warning",message:"skill path does not exist",path:resolvedPath});continue}try{let stats=statSync5(resolvedPath),source=getSource(resolvedPath);if(stats.isDirectory())addSkills(loadSkillsFromDirInternal(resolvedPath,source,!0));else if(stats.isFile()&&resolvedPath.endsWith(".md")){let result2=loadSkillFromFile(resolvedPath,source);result2.skill?addSkills({skills:[result2.skill],diagnostics:result2.diagnostics}):allDiagnostics.push(...result2.diagnostics)}else allDiagnostics.push({type:"warning",message:"skill path is not a markdown file",path:resolvedPath})}catch(error){let message=error instanceof Error?error.message:"failed to read skill path";allDiagnostics.push({type:"warning",message,path:resolvedPath})}}return{skills:Array.from(skillMap.values()),diagnostics:[...allDiagnostics,...collisionDiagnostics]}}import{randomUUID as randomUUID2}from"node:crypto";import{open as open2}from"node:fs/promises";var TASK_RESULT_BYTES=48*1024,TASK_DETAILS_BYTES=120*1024,TASK_READ_BYTES=8*1024,TASK_TITLE_BYTES=1024;function finiteLimit(value,fallback,ceiling){return value===void 0||!Number.isFinite(value)?fallback:Math.max(0,Math.min(ceiling,Math.floor(value)))}function alignedSlice(buffer,start,end){for(;start<end&&(buffer[start]&192)===128;)start++;if(end<buffer.length)for(;end>start&&(buffer[end]&192)===128;)end--;let lead=end-1;for(;lead>=start&&(buffer[lead]&192)===128;)lead--;if(lead>=start){let byte=buffer[lead],width=byte>=240?4:byte>=224?3:byte>=192?2:1;end-lead<width&&(end=lead)}return buffer.subarray(start,end)}function boundText(text2,bytes=TASK_RESULT_BYTES){let limit=finiteLimit(bytes,TASK_RESULT_BYTES,TASK_RESULT_BYTES),prefix=text2.slice(0,limit+1),buffer=Buffer.from(prefix);return alignedSlice(buffer,0,Math.min(limit,buffer.length)).toString("utf8")}function boundTail(text2,bytes){let buffer=Buffer.from(text2);return buffer.length<=bytes?{text:text2,truncated:!1}:{text:alignedSlice(buffer,buffer.length-bytes,buffer.length).toString("utf8"),truncated:!0}}function boundedResult(result2){let remaining=TASK_RESULT_BYTES,content=[];for(let block of result2.content){if(remaining<=0)break;let text2=boundText(block.type==="text"?block.text:"[Image omitted from background history]",remaining);content.push({type:"text",text:text2}),remaining-=Math.max(1,Buffer.byteLength(text2))}let details;try{let budget=TASK_DETAILS_BYTES,json=JSON.stringify(result2.details,(key,value)=>{if(budget-=Buffer.byteLength(key)+3,budget-=typeof value=="string"?Buffer.byteLength(value)+2:8,budget<0)throw new Error("Background details exceed the storage budget");return value});json!==void 0&&Buffer.byteLength(json)<=TASK_DETAILS_BYTES&&(details=JSON.parse(json))}catch{}return{content,details}}function retainResult(task,result2,truncated=!1){let bounded=boundedResult({content:result2.content,details:void 0});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})}async function readOutputSlice(path14,options={}){let bytes=finiteLimit(options.bytes,TASK_READ_BYTES,TASK_RESULT_BYTES),file=await open2(path14,"r");try{let{size}=await file.stat(),since=finiteLimit(options.sinceBytes,0,Number.MAX_SAFE_INTEGER),floor=since>size?0:since,start=options.sinceBytes!==void 0?Math.max(floor,size-bytes):options.mode==="head"?0:Math.max(0,size-bytes),length=Math.min(bytes,size-start),buffer=Buffer.alloc(Math.min(length+1,size-start)),{bytesRead}=await file.read(buffer,0,buffer.length,start),slice=alignedSlice(buffer.subarray(0,bytesRead),0,Math.min(length,bytesRead));return{text:slice.toString("utf8"),totalBytes:size,truncated:options.sinceBytes!==void 0?start>floor||slice.length<length:slice.length<size,fromByte:start+slice.byteOffset-buffer.byteOffset}}finally{await file.close()}}function sliceText(text2,options={}){let buffer=Buffer.from(text2),bytes=finiteLimit(options.bytes,TASK_READ_BYTES,TASK_RESULT_BYTES),since=finiteLimit(options.sinceBytes,0,Number.MAX_SAFE_INTEGER),floor=since>buffer.length?0:since,start=options.sinceBytes!==void 0?Math.max(floor,buffer.length-bytes):options.mode==="head"?0:Math.max(0,buffer.length-bytes),slice=alignedSlice(buffer,start,Math.min(buffer.length,start+bytes));return{text:slice.toString("utf8"),totalBytes:buffer.length,truncated:slice.length<buffer.length-floor,fromByte:slice.byteOffset-buffer.byteOffset}}var TASK_HISTORY_VERSION=2;function dataObject(value){if(value===null||typeof value!="object"||Array.isArray(value))throw new Error("Expected object");let prototype=Object.getPrototypeOf(value);if(prototype!==Object.prototype&&prototype!==null)throw new Error("Expected plain object");return value}function field(object3,key){let descriptor=Object.getOwnPropertyDescriptor(object3,key);if(descriptor&&!("value"in descriptor))throw new Error("Unexpected accessor");return descriptor?.value}function historyString(value,bytes,exact=!1){if(typeof value!="string")throw new Error("Expected string");if(exact&&(!value||value.length>bytes||Buffer.byteLength(value)>bytes||value.includes("\0")))throw new Error("Invalid identity or path");return boundText(value,bytes)}function parseTaskHistory(record){try{let envelope=dataObject(record);if(field(envelope,"version")!==TASK_HISTORY_VERSION)return;let source=dataObject(field(envelope,"task")),kind=field(source,"kind"),mode=field(source,"mode"),status=field(source,"status");if(typeof kind!="string"||!/^[a-z][a-z0-9-]{0,63}$/.test(kind)||mode!=="foreground"&&mode!=="background"||status!=="completed"&&status!=="partial"&&status!=="failed"&&status!=="cancelled"&&status!=="timeout")return;let startedAt=field(source,"startedAt"),endedAt=field(source,"endedAt");if(typeof startedAt!="number"||!Number.isSafeInteger(startedAt)||startedAt<0||typeof endedAt!="number"||!Number.isSafeInteger(endedAt)||endedAt<startedAt)return;let anchor=field(source,"anchorId"),task={id:historyString(field(source,"id"),512,!0),kind,mode,status,startedAt,endedAt,title:historyString(field(source,"title"),TASK_TITLE_BYTES),toolCallId:historyString(field(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 value=field(source,key);value!==void 0&&(task[key]=historyString(value,bytes,key==="outputPath"))}for(let key of["commandTruncated","resultTruncated"]){let value=field(source,key);if(value!==void 0&&typeof value!="boolean")return;task[key]=value}let exitCode=field(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!==field(source,"command")&&(task.commandTruncated=!0);let result2=field(source,"result");if(result2!==void 0){let object3=dataObject(result2),blocks=field(object3,"content");if(!Array.isArray(blocks))return;let content=[],remaining=TASK_RESULT_BYTES;for(let index3=0;index3<blocks.length&&remaining>0;index3++){let block=dataObject(field(blocks,String(index3))),type=field(block,"type");if(type!=="text"&&type!=="image")return;let original=type==="text"?field(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:void 0})}return task}catch{return}}var EXPIRED_OUTPUT="Output has expired: the managed log was released; showing the stored result.";function freeze(value){if(value!==null&&typeof value=="object"&&!Object.isFrozen(value)){for(let child of Object.values(value))freeze(child);Object.freeze(value)}return value}function snapshotOf(record){return record.snapshot??=freeze(structuredClone(record.task)),record.snapshot}function changed(record){record.snapshot=void 0}function errorText(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Task cleanup failed"}}function oldestTask(tasks){let oldest;for(let task of tasks)(!oldest||task.endedAt<oldest.endedAt)&&(oldest=task);return oldest}var isForeground=task=>task.mode==="foreground",TaskStore=class{constructor(maxHistory,maxRetained,isClosed,onCleanupError){this.records=new Map,this.cleanups=new Set,this.maxHistory=maxHistory,this.maxRetained=maxRetained,this.isClosed=isClosed,this.onCleanupError=onCleanupError}get closed(){return this.isClosed()}restoreHistory(records,toolResults=new Map){if(this.closed)return;let history=this.historyRecords(),foreground=history.filter(record=>isForeground(record.task)).length,foregroundCapacity=Math.max(0,this.maxHistory-foreground),backgroundCapacity=Math.max(0,this.maxHistory-(history.length-foreground)),capacity=Math.max(0,Math.min(foregroundCapacity+backgroundCapacity,this.maxRetained-this.records.size-this.cleanups.size)),newest=new Map;for(let value of records){let task=parseTaskHistory(value);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 inline=isForeground(task),limit=inline?foregroundCapacity:backgroundCapacity;if(limit===0)continue;newest.set(task.id,task);let group=[...newest.values()].filter(candidate=>isForeground(candidate)===inline);if(group.length>limit&&newest.delete(oldestTask(group).id),newest.size>capacity){let inlineTasks=[...newest.values()].filter(isForeground);newest.delete(oldestTask(inlineTasks.length?inlineTasks:newest.values()).id)}}for(let task of[...newest.values()].sort((a,b2)=>a.endedAt-b2.endedAt)){let content=toolResults.get(task.toolCallId);!task.result&&content&&retainResult(task,{content,details:void 0});let expired=task.outputPath!==void 0;task.outputPath=void 0,this.records.set(task.id,{task,settled:!0,visible:!0,delivery:"delivered",pins:0,deliveryHolds:0,waiters:new Set,readError:expired?EXPIRED_OUTPUT:void 0})}}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,changed(record),record.readError=EXPIRED_OUTPUT;let pending=Promise.resolve().then(cleanup).catch(error=>{try{this.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 inline of[!1,!0]){let group=history.filter(record=>record.visible&&isForeground(record.task)===inline);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)}};var TASK_BACKGROUND_REJECTION="Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";function isTaskTerminal(status){return status!=="queued"&&status!=="running"&&status!=="stopping"}var TaskExecutionError=class extends Error{constructor(message,status){super(message),this.name="TaskExecutionError",this.status=status}},TaskLookupError=class extends Error{constructor(kind,matches){super(kind==="ambiguous"?"Ambiguous task ID":"Unknown task ID"),this.name="TaskLookupError",this.kind=kind,this.matches=matches}};function errorText2(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Task execution failed (unprintable error)"}}var TaskRuntime=class{get closed(){return this._closed}constructor(options={}){this.executions=new Map,this.listeners=new Set,this._closed=!1,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,this.store=new TaskStore(this.maxHistory,this.maxRetained,()=>this.closed,options.onCleanupError)}restoreHistory(records,toolResults){this.store.restoreHistory(records,toolResults)}get enabled(){return this.configuredEnabled&&!this.closed&&this.options.backgroundAllowed!==!1}setEnabled(enabled){this.configuredEnabled=enabled,this.emit()}backgroundActive(){let count=0;for(let record of this.store.records.values())!record.settled&&record.task.mode==="background"&&count++;return count}limitError(){return new Error(`Background task limit reached (${this.maxActive}); stop or wait for a background task, or run in the foreground.`)}async execute(execution){if(execution.background&&this.options.backgroundAllowed===!1)throw new Error(TASK_BACKGROUND_REJECTION);if(this.closed)throw new Error("Task service is closed");if(execution.background){if(!this.enabled)throw new Error("Background execution is not available in this host");if(this.backgroundActive()>=this.maxActive)throw this.limitError();if(this.store.records.size+this.store.cleanups.size>=this.maxRetained)throw new Error("Task history retention limit reached; deliver pending notifications or release pinned or claimed records")}if(execution.signal?.aborted)throw execution.signal.reason??new Error("Execution aborted");if(!/^[a-z][a-z0-9-]{0,63}$/.test(execution.kind))throw new Error("Invalid task source");let anchorId=this.options.anchor?.()??null;if(anchorId!==null&&Buffer.byteLength(anchorId)>8192)throw new Error("Task branch anchor is too large");let task={id:`${execution.kind}-${randomUUID2()}`,kind:execution.kind,title:boundText(execution.title,TASK_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((resolve20,reject)=>{resolveCaller=resolve20,rejectCaller=reject}),resolveDone,record={task,settled:!1,visible:!0,delivery:"none",pins:0,deliveryHolds:0,waiters:new Set},active={controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:execution.background??!1,modeListeners:new Set,removeParent:()=>{},handoff:()=>{!active.accepted||!active.detachRequested||record.settled||active.handedOff||this.closed||!record.visible||active.controller.signal.aborted||(active.handedOff=!0,task.mode="background",changed(record),active.removeParent(),resolveCaller({kind:"background",task:snapshotOf(record)}),this.emit())},done:new Promise(resolve20=>{resolveDone=resolve20})},parentSignal=execution.signal,onUpdate=execution.background?void 0:execution.onUpdate,parentAbort=()=>{(!active.detachRequested||!active.accepted)&&this.cancel(record)};parentSignal?.addEventListener("abort",parentAbort,{once:!0}),active.removeParent=()=>{parentSignal?.removeEventListener("abort",parentAbort),onUpdate=void 0},this.store.records.set(task.id,record),this.executions.set(task.id,active);let control={id:task.id,signal:active.controller.signal,get mode(){return task.mode},onModeChange:listener=>record.settled||this.closed?()=>{}:(active.modeListeners.add(listener),()=>{active.modeListeners.delete(listener)}),requestCancel:()=>this.cancel(record),accept:()=>{record.settled||active.accepted||this.closed||active.controller.signal.aborted||(active.accepted=!0,task.status==="queued"&&(task.status="running"),changed(record),active.detachRequested&&active.removeParent(),queueMicrotask(()=>queueMicrotask(active.handoff)),this.emit())},publish:result2=>{if(!(record.settled||this.closed)){if(retainResult(task,result2),changed(record),result2.usage!==void 0&&(active.publishedUsage=structuredClone(result2.usage)),!active.detachRequested&&!active.handedOff)try{onUpdate?.(result2)}catch{}this.emit()}},setOutputPath:(path14,cleanup)=>{if(record.settled){if(cleanup)throw new Error("Task execution has settled");return}if(record.cleanup)throw new Error("Managed output is already registered");if(Buffer.byteLength(path14)>8192)throw new Error("Task output path is too large");record.cleanup=cleanup,task.outputPath=path14,changed(record),this.emit()}},finish=(completion,error)=>{if(record.settled)return;record.settled=!0,active.modeListeners.clear(),active.removeParent(),task.endedAt=Date.now();let failed=completion===void 0;task.status=completion?.status??(error instanceof TaskExecutionError?error.status:active.controller.signal.aborted?"cancelled":failed?"failed":"completed"),completion&&(retainResult(task,completion.result),completion.error!==void 0&&(task.error=boundText(completion.error,4096)),completion.exitCode!==void 0&&(task.exitCode=completion.exitCode)),failed&&(task.error=errorText2(error),retainResult(task,{content:[{type:"text",text:task.error},...task.result?.content??[]],details:void 0},task.resultTruncated)),changed(record);let settlementWarning;try{this.options.onSettled?.(snapshotOf(record),completion?.usage??completion?.result.usage??active.publishedUsage)}catch(accountingError){let warning=`Usage settlement failed: ${errorText2(accountingError)}`;settlementWarning=warning,task.error=boundText([task.error,warning].filter(Boolean).join(`
|
|
664
|
+
`)}function escapeXml(str2){return str2.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function loadSkills(options){let{agentDir,skillPaths,includeDefaults}=options,resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(agentDir??getAgentDir()),skillMap=new Map,realPathSet=new Set,allDiagnostics=[],collisionDiagnostics=[];function addSkills(result2){allDiagnostics.push(...result2.diagnostics);for(let skill of result2.skills){let realPath=canonicalizePath(skill.filePath);if(realPathSet.has(realPath))continue;let existing=skillMap.get(skill.name);existing?collisionDiagnostics.push({type:"collision",message:`name "${skill.name}" collision`,path:skill.filePath,collision:{resourceType:"skill",name:skill.name,winnerPath:existing.filePath,loserPath:skill.filePath}}):(skillMap.set(skill.name,skill),realPathSet.add(realPath))}}includeDefaults&&(addSkills(loadSkillsFromDirInternal(join17(resolvedAgentDir,"skills"),"user",!0)),addSkills(loadSkillsFromDirInternal(resolve3(resolvedCwd,CONFIG_DIR_NAME,"skills"),"project",!0)));let userSkillsDir=join17(resolvedAgentDir,"skills"),projectSkillsDir=resolve3(resolvedCwd,CONFIG_DIR_NAME,"skills"),isUnderPath=(target,root)=>{let normalizedRoot=resolve3(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep5)?normalizedRoot:`${normalizedRoot}${sep5}`;return target.startsWith(prefix)},getSource=resolvedPath=>{if(!includeDefaults){if(isUnderPath(resolvedPath,userSkillsDir))return"user";if(isUnderPath(resolvedPath,projectSkillsDir))return"project"}return"path"};for(let rawPath of skillPaths){let resolvedPath=resolvePath(rawPath,resolvedCwd,{trim:!0});if(!existsSync8(resolvedPath)){allDiagnostics.push({type:"warning",message:"skill path does not exist",path:resolvedPath});continue}try{let stats=statSync5(resolvedPath),source=getSource(resolvedPath);if(stats.isDirectory())addSkills(loadSkillsFromDirInternal(resolvedPath,source,!0));else if(stats.isFile()&&resolvedPath.endsWith(".md")){let result2=loadSkillFromFile(resolvedPath,source);result2.skill?addSkills({skills:[result2.skill],diagnostics:result2.diagnostics}):allDiagnostics.push(...result2.diagnostics)}else allDiagnostics.push({type:"warning",message:"skill path is not a markdown file",path:resolvedPath})}catch(error){let message=error instanceof Error?error.message:"failed to read skill path";allDiagnostics.push({type:"warning",message,path:resolvedPath})}}return{skills:Array.from(skillMap.values()),diagnostics:[...allDiagnostics,...collisionDiagnostics]}}import{randomUUID as randomUUID2}from"node:crypto";import{open as open2}from"node:fs/promises";var TASK_RESULT_BYTES=48*1024,TASK_DETAILS_BYTES=120*1024,TASK_READ_BYTES=8*1024,TASK_TITLE_BYTES=1024;function finiteLimit(value,fallback,ceiling){return value===void 0||!Number.isFinite(value)?fallback:Math.max(0,Math.min(ceiling,Math.floor(value)))}function alignedSlice(buffer,start,end){for(;start<end&&(buffer[start]&192)===128;)start++;if(end<buffer.length)for(;end>start&&(buffer[end]&192)===128;)end--;let lead=end-1;for(;lead>=start&&(buffer[lead]&192)===128;)lead--;if(lead>=start){let byte=buffer[lead],width=byte>=240?4:byte>=224?3:byte>=192?2:1;end-lead<width&&(end=lead)}return buffer.subarray(start,end)}function boundText(text2,bytes=TASK_RESULT_BYTES){let limit=finiteLimit(bytes,TASK_RESULT_BYTES,TASK_RESULT_BYTES),prefix=text2.slice(0,limit+1),buffer=Buffer.from(prefix);return alignedSlice(buffer,0,Math.min(limit,buffer.length)).toString("utf8")}function boundTail(text2,bytes){let buffer=Buffer.from(text2);return buffer.length<=bytes?{text:text2,truncated:!1}:{text:alignedSlice(buffer,buffer.length-bytes,buffer.length).toString("utf8"),truncated:!0}}function boundedResult(result2){let remaining=TASK_RESULT_BYTES,content=[];for(let block of result2.content){if(remaining<=0)break;let text2=boundText(block.type==="text"?block.text:"[Image omitted from background history]",remaining);content.push({type:"text",text:text2}),remaining-=Math.max(1,Buffer.byteLength(text2))}let details;try{let budget=TASK_DETAILS_BYTES,json=JSON.stringify(result2.details,(key,value)=>{if(budget-=Buffer.byteLength(key)+3,budget-=typeof value=="string"?Buffer.byteLength(value)+2:8,budget<0)throw new Error("Background details exceed the storage budget");return value});json!==void 0&&Buffer.byteLength(json)<=TASK_DETAILS_BYTES&&(details=JSON.parse(json))}catch{}return{content,details}}function retainResult(task,result2,truncated=!1){let bounded=boundedResult({content:result2.content,details:void 0});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})}async function readOutputSlice(path14,options={}){let bytes=finiteLimit(options.bytes,TASK_READ_BYTES,TASK_RESULT_BYTES),file=await open2(path14,"r");try{let{size}=await file.stat(),since=finiteLimit(options.sinceBytes,0,Number.MAX_SAFE_INTEGER),floor=since>size?0:since,start=options.sinceBytes!==void 0?Math.max(floor,size-bytes):options.mode==="head"?0:Math.max(0,size-bytes),length=Math.min(bytes,size-start),buffer=Buffer.alloc(Math.min(length+1,size-start)),{bytesRead}=await file.read(buffer,0,buffer.length,start),slice=alignedSlice(buffer.subarray(0,bytesRead),0,Math.min(length,bytesRead));return{text:slice.toString("utf8"),totalBytes:size,truncated:options.sinceBytes!==void 0?start>floor||slice.length<length:slice.length<size,fromByte:start+slice.byteOffset-buffer.byteOffset}}finally{await file.close()}}function sliceText(text2,options={}){let buffer=Buffer.from(text2),bytes=finiteLimit(options.bytes,TASK_READ_BYTES,TASK_RESULT_BYTES),since=finiteLimit(options.sinceBytes,0,Number.MAX_SAFE_INTEGER),floor=since>buffer.length?0:since,start=options.sinceBytes!==void 0?Math.max(floor,buffer.length-bytes):options.mode==="head"?0:Math.max(0,buffer.length-bytes),slice=alignedSlice(buffer,start,Math.min(buffer.length,start+bytes));return{text:slice.toString("utf8"),totalBytes:buffer.length,truncated:slice.length<buffer.length-floor,fromByte:slice.byteOffset-buffer.byteOffset}}var TASK_HISTORY_VERSION=2;function dataObject(value){if(value===null||typeof value!="object"||Array.isArray(value))throw new Error("Expected object");let prototype=Object.getPrototypeOf(value);if(prototype!==Object.prototype&&prototype!==null)throw new Error("Expected plain object");return value}function field(object3,key){let descriptor=Object.getOwnPropertyDescriptor(object3,key);if(descriptor&&!("value"in descriptor))throw new Error("Unexpected accessor");return descriptor?.value}function historyString(value,bytes,exact=!1){if(typeof value!="string")throw new Error("Expected string");if(exact&&(!value||value.length>bytes||Buffer.byteLength(value)>bytes||value.includes("\0")))throw new Error("Invalid identity or path");return boundText(value,bytes)}function parseTaskHistory(record){try{let envelope=dataObject(record);if(field(envelope,"version")!==TASK_HISTORY_VERSION)return;let source=dataObject(field(envelope,"task")),kind=field(source,"kind"),mode=field(source,"mode"),status=field(source,"status");if(typeof kind!="string"||!/^[a-z][a-z0-9-]{0,63}$/.test(kind)||mode!=="foreground"&&mode!=="background"||status!=="completed"&&status!=="partial"&&status!=="failed"&&status!=="cancelled"&&status!=="timeout")return;let startedAt=field(source,"startedAt"),endedAt=field(source,"endedAt");if(typeof startedAt!="number"||!Number.isSafeInteger(startedAt)||startedAt<0||typeof endedAt!="number"||!Number.isSafeInteger(endedAt)||endedAt<startedAt)return;let anchor=field(source,"anchorId"),task={id:historyString(field(source,"id"),512,!0),kind,mode,status,startedAt,endedAt,title:historyString(field(source,"title"),TASK_TITLE_BYTES),toolCallId:historyString(field(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 value=field(source,key);value!==void 0&&(task[key]=historyString(value,bytes,key==="outputPath"))}for(let key of["commandTruncated","resultTruncated"]){let value=field(source,key);if(value!==void 0&&typeof value!="boolean")return;task[key]=value}let exitCode=field(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!==field(source,"command")&&(task.commandTruncated=!0);let result2=field(source,"result");if(result2!==void 0){let object3=dataObject(result2),blocks=field(object3,"content");if(!Array.isArray(blocks))return;let content=[],remaining=TASK_RESULT_BYTES;for(let index3=0;index3<blocks.length&&remaining>0;index3++){let block=dataObject(field(blocks,String(index3))),type=field(block,"type");if(type!=="text"&&type!=="image")return;let original=type==="text"?field(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:void 0})}return task}catch{return}}var EXPIRED_OUTPUT="Output has expired: the managed log was released; showing the stored result.";function freeze(value){if(value!==null&&typeof value=="object"&&!Object.isFrozen(value)){for(let child of Object.values(value))freeze(child);Object.freeze(value)}return value}function snapshotOf(record){return record.snapshot??=freeze(structuredClone(record.task)),record.snapshot}function changed(record){record.snapshot=void 0}function errorText(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Task cleanup failed"}}function oldestTask(tasks){let oldest;for(let task of tasks)(!oldest||task.endedAt<oldest.endedAt)&&(oldest=task);return oldest}var isForeground=task=>task.mode==="foreground",TaskStore=class{constructor(maxHistory,maxRetained,isClosed,onCleanupError){this.records=new Map,this.cleanups=new Set,this.maxHistory=maxHistory,this.maxRetained=maxRetained,this.isClosed=isClosed,this.onCleanupError=onCleanupError}get closed(){return this.isClosed()}restoreHistory(records,toolResults=new Map){if(this.closed)return;let history=this.historyRecords(),foreground=history.filter(record=>isForeground(record.task)).length,foregroundCapacity=Math.max(0,this.maxHistory-foreground),backgroundCapacity=Math.max(0,this.maxHistory-(history.length-foreground)),capacity=Math.max(0,Math.min(foregroundCapacity+backgroundCapacity,this.maxRetained-this.records.size-this.cleanups.size)),newest=new Map;for(let value of records){let task=parseTaskHistory(value);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 inline=isForeground(task),limit=inline?foregroundCapacity:backgroundCapacity;if(limit===0)continue;newest.set(task.id,task);let group=[...newest.values()].filter(candidate=>isForeground(candidate)===inline);if(group.length>limit&&newest.delete(oldestTask(group).id),newest.size>capacity){let inlineTasks=[...newest.values()].filter(isForeground);newest.delete(oldestTask(inlineTasks.length?inlineTasks:newest.values()).id)}}for(let task of[...newest.values()].sort((a,b2)=>a.endedAt-b2.endedAt)){let content=toolResults.get(task.toolCallId);!task.result&&content&&retainResult(task,{content,details:void 0});let expired=task.outputPath!==void 0;task.outputPath=void 0,this.records.set(task.id,{task,settled:!0,visible:!0,delivery:"delivered",pins:0,deliveryHolds:0,waiters:new Set,readError:expired?EXPIRED_OUTPUT:void 0})}}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,changed(record),record.readError=EXPIRED_OUTPUT;let pending=Promise.resolve().then(cleanup).catch(error=>{try{this.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 inline of[!1,!0]){let group=history.filter(record=>record.visible&&isForeground(record.task)===inline);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)}};var TASK_BACKGROUND_REJECTION="Background execution is not permitted in this host. Run with background: false or omit background. No work was started.";function isTaskTerminal(status){return status!=="queued"&&status!=="running"&&status!=="stopping"}var TaskExecutionError=class extends Error{constructor(message,status){super(message),this.name="TaskExecutionError",this.status=status}},TaskLookupError=class extends Error{constructor(kind,matches){super(kind==="ambiguous"?"Ambiguous task ID":"Unknown task ID"),this.name="TaskLookupError",this.kind=kind,this.matches=matches}};function errorText2(error){try{return boundText(error instanceof Error?error.message:String(error),4096)}catch{return"Task execution failed (unprintable error)"}}var TaskRuntime=class{get closed(){return this._closed}get session(){return this.options.session}constructor(options={}){this.executions=new Map,this.listeners=new Set,this._closed=!1,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,this.store=new TaskStore(this.maxHistory,this.maxRetained,()=>this.closed,options.onCleanupError)}restoreHistory(records,toolResults){this.store.restoreHistory(records,toolResults)}get enabled(){return this.configuredEnabled&&!this.closed&&this.options.backgroundAllowed!==!1}setEnabled(enabled){this.configuredEnabled=enabled,this.emit()}backgroundActive(){let count=0;for(let record of this.store.records.values())!record.settled&&record.task.mode==="background"&&count++;return count}limitError(){return new Error(`Background task limit reached (${this.maxActive}); stop or wait for a background task, or run in the foreground.`)}async execute(execution){if(execution.background&&this.options.backgroundAllowed===!1)throw new Error(TASK_BACKGROUND_REJECTION);if(this.closed)throw new Error("Task service is closed");if(execution.background){if(!this.enabled)throw new Error("Background execution is not available in this host");if(this.backgroundActive()>=this.maxActive)throw this.limitError();if(this.store.records.size+this.store.cleanups.size>=this.maxRetained)throw new Error("Task history retention limit reached; deliver pending notifications or release pinned or claimed records")}if(execution.signal?.aborted)throw execution.signal.reason??new Error("Execution aborted");if(!/^[a-z][a-z0-9-]{0,63}$/.test(execution.kind))throw new Error("Invalid task source");let anchorId=this.options.anchor?.()??null;if(anchorId!==null&&Buffer.byteLength(anchorId)>8192)throw new Error("Task branch anchor is too large");let task={id:`${execution.kind}-${randomUUID2()}`,kind:execution.kind,title:boundText(execution.title,TASK_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((resolve20,reject)=>{resolveCaller=resolve20,rejectCaller=reject}),resolveDone,record={task,settled:!1,visible:!0,delivery:"none",pins:0,deliveryHolds:0,waiters:new Set},active={controller:new AbortController,accepted:!1,handedOff:!1,detachRequested:execution.background??!1,modeListeners:new Set,removeParent:()=>{},handoff:()=>{!active.accepted||!active.detachRequested||record.settled||active.handedOff||this.closed||!record.visible||active.controller.signal.aborted||(active.handedOff=!0,task.mode="background",changed(record),active.removeParent(),resolveCaller({kind:"background",task:snapshotOf(record)}),this.emit())},done:new Promise(resolve20=>{resolveDone=resolve20})},parentSignal=execution.signal,onUpdate=execution.background?void 0:execution.onUpdate,parentAbort=()=>{(!active.detachRequested||!active.accepted)&&this.cancel(record)};parentSignal?.addEventListener("abort",parentAbort,{once:!0}),active.removeParent=()=>{parentSignal?.removeEventListener("abort",parentAbort),onUpdate=void 0},this.store.records.set(task.id,record),this.executions.set(task.id,active);let control={id:task.id,signal:active.controller.signal,get mode(){return task.mode},onModeChange:listener=>record.settled||this.closed?()=>{}:(active.modeListeners.add(listener),()=>{active.modeListeners.delete(listener)}),requestCancel:()=>this.cancel(record),accept:()=>{record.settled||active.accepted||this.closed||active.controller.signal.aborted||(active.accepted=!0,task.status==="queued"&&(task.status="running"),changed(record),active.detachRequested&&active.removeParent(),queueMicrotask(()=>queueMicrotask(active.handoff)),this.emit())},publish:result2=>{if(!(record.settled||this.closed)){if(retainResult(task,result2),changed(record),result2.usage!==void 0&&(active.publishedUsage=structuredClone(result2.usage)),!active.detachRequested&&!active.handedOff)try{onUpdate?.(result2)}catch{}this.emit()}},setOutputPath:(path14,cleanup)=>{if(record.settled){if(cleanup)throw new Error("Task execution has settled");return}if(record.cleanup)throw new Error("Managed output is already registered");if(Buffer.byteLength(path14)>8192)throw new Error("Task output path is too large");record.cleanup=cleanup,task.outputPath=path14,changed(record),this.emit()}},finish=(completion,error)=>{if(record.settled)return;record.settled=!0,active.modeListeners.clear(),active.removeParent(),task.endedAt=Date.now();let failed=completion===void 0;task.status=completion?.status??(error instanceof TaskExecutionError?error.status:active.controller.signal.aborted?"cancelled":failed?"failed":"completed"),completion&&(retainResult(task,completion.result),completion.error!==void 0&&(task.error=boundText(completion.error,4096)),completion.exitCode!==void 0&&(task.exitCode=completion.exitCode)),failed&&(task.error=errorText2(error),retainResult(task,{content:[{type:"text",text:task.error},...task.result?.content??[]],details:void 0},task.resultTruncated)),changed(record);let settlementWarning;try{this.options.onSettled?.(snapshotOf(record),completion?.usage??completion?.result.usage??active.publishedUsage)}catch(accountingError){let warning=`Usage settlement failed: ${errorText2(accountingError)}`;settlementWarning=warning,task.error=boundText([task.error,warning].filter(Boolean).join(`
|
|
665
665
|
`),8192),retainResult(task,{content:[{type:"text",text:warning},...task.result?.content??[]],details:void 0},task.resultTruncated),changed(record)}if(active.publishedUsage=void 0,record.delivery=active.handedOff?"pending":"delivered",!active.handedOff)if(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.executions.delete(task.id),this.store.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}detachable(record){let active=this.executions.get(record.task.id);return!!active&&!record.settled&&!active.detachRequested&&!active.controller.signal.aborted}detachForeground(){if(!this.enabled)return 0;let eligible=[...this.store.records.values()].filter(record=>this.detachable(record)).sort((left,right)=>left.task.startedAt-right.task.startedAt);if(!eligible.length)return 0;let free=this.maxActive-this.backgroundActive();if(free<=0)throw this.limitError();let records=eligible.slice(0,free);for(let record of records)this.prepareDetach(record);for(let record of records)this.finishDetach(record);return this.emit(),records.length}canDetach(id){let record=this.lookup(id);return this.enabled&&this.backgroundActive()<this.maxActive&&this.detachable(record)}detach(id){let record=this.lookup(id);if(!this.enabled||!this.detachable(record))return!1;if(this.backgroundActive()>=this.maxActive)throw this.limitError();return this.prepareDetach(record),this.finishDetach(record),this.emit(),!0}prepareDetach(record){let active=this.executions.get(record.task.id);active.detachRequested=!0,record.task.mode="background",changed(record),active.accepted&&active.removeParent()}finishDetach(record){let active=this.executions.get(record.task.id);active.handoff();for(let listener of active.modeListeners)try{listener(record.task.mode)}catch{}}list(){return[...this.store.records.values()].filter(record=>record.visible).map(snapshotOf)}lookup(id){let exact=this.store.records.get(id);if(exact)return exact;let matches=[...this.store.records.values()].filter(({task})=>task.id.startsWith(id)||task.id.slice(task.kind.length+1).startsWith(id));if(!id||matches.length!==1)throw new TaskLookupError(matches.length>1?"ambiguous":"unknown",matches.map(snapshotOf));return matches[0]}get(id){return snapshotOf(this.lookup(id))}async read(id,options={}){let record=this.lookup(id),release2=this.retain(record.task.id);try{let task=snapshotOf(record);if(task.outputPath)try{return{task,...await readOutputSlice(task.outputPath,options)}}catch(error){return{task,readError:boundText(`Output could not be read: ${errorText2(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(`
|
|
666
|
-
`)||task.error||"No output yet.")}waitForRecords(records,timeoutMs,signal,interruptSignal){return records.some(record=>record.settled)||interruptSignal?.aborted?Promise.resolve():new Promise((resolve20,reject)=>{let finished=!1,timer,complete2=(aborted=!1)=>{if(!finished){finished=!0,timer!==void 0&&clearTimeout(timer),signal?.removeEventListener("abort",abort),interruptSignal?.removeEventListener("abort",interrupt);for(let record of records)record.waiters.delete(wake);aborted?reject(signal?.reason??new Error("Wait aborted")):resolve20(),this.store.trim(),this.emit()}},wake=()=>complete2(),abort=()=>complete2(!0),interrupt=()=>complete2();for(let record of records)record.waiters.add(wake);signal?.addEventListener("abort",abort,{once:!0}),interruptSignal?.addEventListener("abort",interrupt,{once:!0}),timer=setTimeout(wake,finiteLimit(timeoutMs,2e4,
|
|
666
|
+
`)||task.error||"No output yet.")}waitForRecords(records,timeoutMs,signal,interruptSignal){return records.some(record=>record.settled)||interruptSignal?.aborted?Promise.resolve():new Promise((resolve20,reject)=>{let finished=!1,timer,complete2=(aborted=!1)=>{if(!finished){finished=!0,timer!==void 0&&clearTimeout(timer),signal?.removeEventListener("abort",abort),interruptSignal?.removeEventListener("abort",interrupt);for(let record of records)record.waiters.delete(wake);aborted?reject(signal?.reason??new Error("Wait aborted")):resolve20(),this.store.trim(),this.emit()}},wake=()=>complete2(),abort=()=>complete2(!0),interrupt=()=>complete2();for(let record of records)record.waiters.add(wake);signal?.addEventListener("abort",abort,{once:!0}),interruptSignal?.addEventListener("abort",interrupt,{once:!0}),timer=setTimeout(wake,finiteLimit(timeoutMs,2e4,6e5)),(this.closed||interruptSignal?.aborted)&&wake(),signal?.aborted&&abort()})}async wait(id,timeoutMs=2e4,signal,interruptSignal){if(signal?.aborted)throw signal.reason??new Error("Wait aborted");let record=this.lookup(id);return record.settled?snapshotOf(record):(await this.waitForRecords([record],timeoutMs,signal,interruptSignal),snapshotOf(record))}async waitAny(timeoutMs=2e4,signal,interruptSignal){if(signal?.aborted)throw signal.reason??new Error("Wait aborted");let records=[...this.store.records.values()].filter(record=>record.visible&&record.task.mode==="background"&&!record.settled);if(records.length===0||interruptSignal?.aborted)return;await this.waitForRecords(records,timeoutMs,signal,interruptSignal);let settled=records.filter(record=>record.settled).sort((left,right)=>(left.task.endedAt??0)-(right.task.endedAt??0))[0];return settled?snapshotOf(settled):void 0}kill(id){return this.cancel(this.lookup(id))}cancel(record){let active=this.executions.get(record.task.id);return!active||record.settled||active.controller.signal.aborted?!1:(record.task.status="stopping",changed(record),active.controller.abort(),this.emit(),!0)}subscribe(listener){return this.closed?()=>{}:(this.listeners.add(listener),()=>{this.listeners.delete(listener)})}retain(id){let record=this.lookup(id);record.pins++;let released=!1;return()=>{released||(released=!0,record.pins--,this.store.trim(),!this.closed&&this.pauses===0&&this.candidate(record)&&this.emit())}}holdDelivery(id){let record=this.lookup(id),releaseRetention=this.retain(id);record.deliveryHolds++;let released=!1;return()=>{released||(released=!0,record.deliveryHolds--,releaseRetention())}}pause(){this.pauses++;let resumed=!1;return()=>{resumed||(resumed=!0,this.pauses--,this.emit())}}pendingNotifications(){return this.closed||this.pauses>0?[]:[...this.store.records.values()].filter(record=>this.candidate(record)).map(snapshotOf)}candidate(record){return record.visible&&record.delivery==="pending"&&record.waiters.size===0&&record.deliveryHolds===0}claimNotification(id){if(this.closed||this.pauses>0)return!1;let record=this.store.records.get(id);return!record||!this.candidate(record)?!1:(record.delivery="claimed",!0)}markDelivered(id){let record=this.store.records.get(id);record&&(record.delivery="delivered",this.store.trim())}releaseNotification(id){let record=this.store.records.get(id);!record||record.delivery!=="claimed"||(record.delivery="pending",this.store.trim(),this.emit())}close(){if(!this.closed){this._closed=!0,this.listeners.clear();for(let record of this.store.records.values()){this.executions.get(record.task.id)?.removeParent(),this.cancel(record);for(let waiter of[...record.waiters])waiter()}this.store.trim()}}async shutdown(graceMs=2e3){this.close(),await this.drain([...this.store.records.values()],graceMs)}activeOutsideBranch(ancestors){return[...this.store.records.values()].filter(record=>!record.settled&&record.task.anchorId!==null&&!ancestors.has(record.task.anchorId)).map(snapshotOf)}async cancelOutsideBranch(ancestors){for(let record of this.store.records.values())record.visible=record.task.anchorId===null||ancestors.has(record.task.anchorId);let outside=[...this.store.records.values()].filter(record=>!record.visible);for(let record of outside)this.cancel(record);this.store.trim(),this.emit(),await this.drain(outside,2e3)}async drain(records,graceMs){let timer;try{await Promise.race([Promise.all(records.map(record=>this.executions.get(record.task.id)?.done)).then(()=>Promise.all(this.store.cleanups)),new Promise(resolve20=>{timer=setTimeout(resolve20,finiteLimit(graceMs,2e3,6e4))})])}finally{timer!==void 0&&clearTimeout(timer)}}emit(){if(!this.closed)for(let listener of[...this.listeners]){if(this.closed)break;try{listener()}catch{}}}};var SYSTEM_PROMPT_SECTION_NAME=/^[a-z][a-z0-9_-]*$/;function normalizeBuildSystemPromptOptions(input2){return{customPrompt:input2.customPrompt,forceSystemPrompt:input2.forceSystemPrompt,selectedTools:[...input2.selectedTools??["read","bash","edit","write"]],hiddenTools:[...input2.hiddenTools??[]],toolSnippets:{...input2.toolSnippets??{}},toolGuidelines:Object.fromEntries(Object.entries(input2.toolGuidelines??{}).map(([name,guidelines])=>[name,[...guidelines]])),promptGuidelines:[...input2.promptGuidelines??[]],appendSystemPrompt:input2.appendSystemPrompt??"",sections:{...input2.sections??{}},cwd:input2.cwd,contextFiles:(input2.contextFiles??[]).map(file=>({...file})),skills:(input2.skills??[]).map(skill=>({...skill}))}}function renderProjectContext(contextFiles){return["Project-specific instructions and guidelines:",...contextFiles.map(({path:path14,content})=>`<project_instructions path="${path14}">
|
|
667
667
|
${content}
|
|
668
668
|
</project_instructions>`)].join(`
|
|
669
669
|
|
|
@@ -680,7 +680,7 @@ In addition to the tools above, you may have access to other custom tools depend
|
|
|
680
680
|
- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing
|
|
681
681
|
- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`}appendSystemPrompt&&(promptSections.addendum=appendSystemPrompt),contextFiles.length>0&&(promptSections.project_context=renderProjectContext(contextFiles));let readers=["read","bash"],skillFileReadTool=readers.find(tool=>declaredTools.includes(tool))??(readers.some(tool=>selectedTools.includes(tool))?"indirect":void 0);if(skillFileReadTool&&skills.length>0){let skillsPrompt=formatSkillsForPrompt(skills,skillFileReadTool).trim();skillsPrompt&&(promptSections.skills=skillsPrompt)}promptSections.cwd=cwd.replace(/\\/g,"/");for(let[name,content]of Object.entries(customSections))content&&(promptSections[name]=content);let sections={preamble:promptSections.preamble};for(let[name,content]of Object.entries(promptSections))name!=="preamble"&&(sections[name]=`<${name}>
|
|
682
682
|
${content}
|
|
683
|
-
</${name}>`);return sections}function buildSystemPromptState(input2){return input2.forceSystemPrompt!==void 0?{content:input2.forceSystemPrompt}:{content:"",sections:buildSystemPromptSections(input2)}}function buildSystemPrompt(input2){return getSystemMessageText({role:"system",...buildSystemPromptState(input2),timestamp:0})}function diffSystemPromptSections(previous,current){let patch={};for(let[name,text2]of Object.entries(current))previous[name]!==text2&&(patch[name]=text2);for(let name of Object.keys(previous))current[name]===void 0&&(patch[name]=null);return Object.keys(patch).length>0?patch:void 0}var RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS=["app.interrupt","app.tasks.detach","app.clear","app.exit","app.suspend","app.thinking.cycle","app.model.cycleForward","app.model.cycleBackward","app.model.select","app.tools.expand","app.thinking.toggle","app.editor.external","app.message.copy","app.message.followUp","tui.input.submit","tui.select.confirm","tui.select.cancel","tui.input.copy","tui.editor.deleteToLineEnd"],buildBuiltinKeybindings=resolvedKeybindings=>{let builtinKeybindings={};for(let[keybinding,keys]of Object.entries(resolvedKeybindings)){if(keys===void 0)continue;let keyList=Array.isArray(keys)?keys:[keys],restrictOverride=RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS.includes(keybinding);for(let key of keyList){let normalizedKey=key.toLowerCase();builtinKeybindings[normalizedKey]?.restrictOverride&&!restrictOverride||(builtinKeybindings[normalizedKey]={keybinding,restrictOverride})}}return builtinKeybindings};function isUserBashEventResult(value){if(typeof value!="object"||value===null)return!1;let candidate=value,hasOperations=candidate.operations!==void 0,hasResult=candidate.result!==void 0;if(hasOperations===hasResult)return!1;if(hasOperations){let operations=candidate.operations;return typeof operations!="object"||operations===null?!1:typeof operations.exec=="function"}let result2=candidate.result;if(typeof result2!="object"||result2===null)return!1;let resultRecord=result2;return typeof resultRecord.output=="string"&&"exitCode"in resultRecord&&(resultRecord.exitCode===void 0||typeof resultRecord.exitCode=="number")&&typeof resultRecord.cancelled=="boolean"&&typeof resultRecord.truncated=="boolean"&&(resultRecord.fullOutputPath===void 0||typeof resultRecord.fullOutputPath=="string")}async function emitSessionShutdownEvent(extensionRunner,event){return extensionRunner.hasHandlers("session_shutdown")?(await extensionRunner.emit(event),!0):!1}function snapshotEventHandlers(extensions,event){return extensions.map(ext2=>({ext:ext2,handlers:ext2.handlers.get(event)?.slice()??[]}))}function sameMessages(left,right){return left.length===right.length&&left.every((message,index3)=>message===right[index3])}function restoreSystemMessages(current,visible,returned){if(sameMessages(returned,visible))return current;let head=getCurrentSystemMessage(current);return head?[head,...returned]:returned}async function emitProjectTrustEvent(extensionsResult,event,ctx){let errors=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(extensionsResult.extensions,"project_trust"))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult.trusted==="undecided")continue;return{result:handlerResult,errors}}catch(error){errors.push({extensionPath:ext2.path,event:event.type,error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:void 0})}return{errors}}var noOpUIContext={select:async()=>{},confirm:async()=>!1,input:async()=>{},notify:()=>{},onTerminalInput:()=>()=>{},setStatus:()=>{},setWorkingMessage:()=>{},setWorkingVisible:()=>{},setWorkingIndicator:()=>{},setHiddenThinkingLabel:()=>{},setWidget:()=>{},setFooter:()=>{},setHeader:()=>{},setTitle:()=>{},custom:async()=>{},pasteToEditor:()=>{},setEditorText:()=>{},getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:()=>{},setEditorComponent:()=>{},getEditorComponent:()=>{},get theme(){return theme},getAllThemes:()=>[],getTheme:()=>{},setTheme:_theme=>({success:!1,error:"UI not available"}),getToolsExpanded:()=>!1,setToolsExpanded:()=>{}},ExtensionRunner=class{constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.unboundTasks=new TaskRuntime,this.getTasks=()=>this.unboundTasks,this.mode="print",this.errorListeners=new Set,this.getModel=()=>{},this.getScopedModels=()=>[],this.isIdleFn=()=>!0,this.isProjectTrustedFn=()=>!0,this.getSignalFn=()=>{},this.waitForIdleFn=async()=>{},this.abortFn=()=>{},this.hasPendingMessagesFn=()=>!1,this.getContextUsageFn=()=>{},this.getContextSnapshotFn=async()=>{throw new Error("Context snapshots are not available in this host")},this.compactFn=()=>{},this.getSystemPromptFn=()=>"",this.getSystemPromptOptionsFn=()=>normalizeBuildSystemPromptOptions({cwd:this.cwd}),this.getCallableToolsFn=()=>[],this.reportedMcpServers=new Set,this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{},this.shutdownHandler=()=>{},this.shortcutDiagnostics=[],this.commandDiagnostics=[],this.uiPromptDepth=0,this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions2,contextActions,providerActions){this.runtime.sendMessage=actions2.sendMessage,this.runtime.sendUserMessage=actions2.sendUserMessage,this.runtime.appendEntry=actions2.appendEntry,this.runtime.setSessionName=actions2.setSessionName,this.runtime.getSessionName=actions2.getSessionName,this.runtime.setLabel=actions2.setLabel,this.runtime.getActiveTools=actions2.getActiveTools,this.runtime.getAllTools=actions2.getAllTools,this.runtime.getSettings=actions2.getSettings,this.runtime.setActiveTools=actions2.setActiveTools,this.runtime.refreshTools=actions2.refreshTools,this.runtime.getCommands=actions2.getCommands,this.runtime.setModel=actions2.setModel,this.runtime.getThinkingLevel=actions2.getThinkingLevel,this.runtime.setThinkingLevel=actions2.setThinkingLevel,this.runtime.createContext=()=>this.createContext(),this.getTasks=contextActions.getTasks??(()=>this.unboundTasks),this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,contextActions.getContextSnapshot&&(this.getContextSnapshotFn=contextActions.getContextSnapshot),this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>normalizeBuildSystemPromptOptions({cwd:this.cwd})),this.executeToolFn=contextActions.executeTool,this.getCallableToolsFn=contextActions.getCallableTools??(()=>[]),this.runtime.mcpServers.setChangeListener(()=>{this.emit({type:"mcp_servers_change",servers:this.runtime.mcpServers.list()}),this.reportUnhandledMcpServers()});for(let{name,config,extensionPath}of this.runtime.pendingProviderRegistrations)try{providerActions?.registerProvider?providerActions.registerProvider(name,config):this.modelRegistry.registerProvider(name,config)}catch(err){this.emitError({extensionPath,event:"register_provider",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingProviderRegistrations=[];for(let{provider,extensionPath}of this.runtime.pendingNativeProviderRegistrations)try{providerActions?.registerNativeProvider?providerActions.registerNativeProvider(provider):this.modelRegistry.registerProvider(provider)}catch(err){this.emitError({extensionPath,event:"register_provider",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingNativeProviderRegistrations=[];let registerVirtualModel=definition=>{providerActions?.registerVirtualModel?providerActions.registerVirtualModel(definition):this.modelRegistry.registerVirtualModel(definition)};for(let{definition,extensionPath}of this.runtime.pendingVirtualModelRegistrations)try{registerVirtualModel(definition)}catch(err){this.emitError({extensionPath,event:"register_virtual_model",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingVirtualModelRegistrations=[],this.runtime.registerProvider=(name,config)=>{if(providerActions?.registerProvider){providerActions.registerProvider(name,config);return}this.modelRegistry.registerProvider(name,config)},this.runtime.registerNativeProvider=provider=>{if(providerActions?.registerNativeProvider){providerActions.registerNativeProvider(provider);return}this.modelRegistry.registerProvider(provider)},this.runtime.unregisterProvider=name=>{if(providerActions?.unregisterProvider){providerActions.unregisterProvider(name);return}this.modelRegistry.unregisterProvider(name)},this.runtime.registerVirtualModel=registerVirtualModel,this.runtime.unregisterVirtualModel=(provider,id)=>{providerActions?.unregisterVirtualModel?providerActions.unregisterVirtualModel(provider,id):this.modelRegistry.unregisterVirtualModel(provider,id)}}bindCommandContext(actions2){if(actions2){this.waitForIdleFn=actions2.waitForIdle,this.newSessionHandler=actions2.newSession,this.forkHandler=actions2.fork,this.navigateTreeHandler=actions2.navigateTree,this.switchSessionHandler=actions2.switchSession,this.reloadHandler=actions2.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(err){throw finish(),err}}emitUIPromptEvent(event){queueMicrotask(()=>{this.emit(event)})}getUIContext(){return this.uiContext}hasUI(){return this.uiContext!==noOpUIContext}getExtensionPaths(){return this.extensions.map(e=>e.path)}getAllRegisteredTools(){let toolsByName=new Map;for(let ext2 of this.extensions)for(let tool of ext2.tools.values())toolsByName.has(tool.definition.name)||toolsByName.set(tool.definition.name,tool);return Array.from(toolsByName.values())}getToolDefinition(toolName){for(let ext2 of this.extensions){let tool=ext2.tools.get(toolName);if(tool)return tool.definition}}getFlags(){let allFlags=new Map;for(let ext2 of this.extensions)for(let[name,flag]of ext2.flags)allFlags.has(name)||allFlags.set(name,flag);return allFlags}setFlagValue(name,value){this.runtime.flagValues.set(name,value)}getFlagValues(){return new Map(this.runtime.flagValues)}getShortcuts(resolvedKeybindings){this.shortcutDiagnostics=[];let builtinKeybindings=buildBuiltinKeybindings(resolvedKeybindings),extensionShortcuts=new Map,addDiagnostic=(message,extensionPath)=>{this.shortcutDiagnostics.push({type:"warning",message,path:extensionPath}),this.hasUI()||console.warn(message)};for(let ext2 of this.extensions)for(let[key,shortcut]of ext2.shortcuts){let normalizedKey=key.toLowerCase(),builtInKeybinding=builtinKeybindings[normalizedKey];if(builtInKeybinding?.restrictOverride===!0){addDiagnostic(`Extension shortcut '${key}' from ${shortcut.extensionPath} conflicts with built-in shortcut. Skipping.`,shortcut.extensionPath);continue}builtInKeybinding?.restrictOverride===!1&&addDiagnostic(`Extension shortcut conflict: '${key}' is built-in shortcut for ${builtInKeybinding.keybinding} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath);let existingExtensionShortcut=extensionShortcuts.get(normalizedKey);existingExtensionShortcut&&addDiagnostic(`Extension shortcut conflict: '${key}' registered by both ${existingExtensionShortcut.extensionPath} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath),extensionShortcuts.set(normalizedKey,shortcut)}return extensionShortcuts}getShortcutDiagnostics(){return this.shortcutDiagnostics}invalidate(message="This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."){this.staleMessage||(this.unboundTasks.close(),this.staleMessage=message,this.runtime.invalidate(message))}assertActive(){if(this.staleMessage)throw new Error(this.staleMessage)}onError(listener){return this.errorListeners.add(listener),()=>this.errorListeners.delete(listener)}emitError(error){for(let listener of this.errorListeners)listener(error)}reportUnhandledMcpServers(){if(!this.hasHandlers("mcp_servers_change"))for(let server of this.runtime.mcpServers.list())this.reportedMcpServers.has(server.name)||(this.reportedMcpServers.add(server.name),this.emitError({extensionPath:server.extensionPath,event:"register_mcp_server",error:`MCP server "${server.name}" is registered, but no loaded extension connects MCP servers; another extension may have replaced the built-in MCP support`}))}hasHandlers(eventType){for(let ext2 of this.extensions){let handlers=ext2.handlers.get(eventType);if(handlers&&handlers.length>0)return!0}return!1}getMessageRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.messageRenderers.get(customType);if(renderer)return renderer}}getMarkdownTransformers(){return this.extensions.flatMap(ext2=>ext2.markdownTransformer?[ext2.markdownTransformer]:[])}resolveToolRenderers(toolName,base){let resolvers=this.extensions.flatMap(ext2=>ext2.toolRenderers??[]),resolve20=index3=>index3<resolvers.length?resolvers[index3](toolName,()=>resolve20(index3+1)):base();return resolve20(0)}getEntryRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.entryRenderers?.get(customType);if(renderer)return renderer}}resolveRegisteredCommands(){let commands=[],counts=new Map;for(let ext2 of this.extensions)for(let command of ext2.commands.values())commands.push(command),counts.set(command.name,(counts.get(command.name)??0)+1);let seen=new Map,takenInvocationNames=new Set;return commands.map(command=>{let occurrence=(seen.get(command.name)??0)+1;seen.set(command.name,occurrence);let invocationName=(counts.get(command.name)??0)>1?`${command.name}:${occurrence}`:command.name;if(takenInvocationNames.has(invocationName)){let suffix=occurrence;do suffix++,invocationName=`${command.name}:${suffix}`;while(takenInvocationNames.has(invocationName))}return takenInvocationNames.add(invocationName),{...command,invocationName}})}getModelRegistry(){return this.modelRegistry}getRegisteredCommands(){return this.commandDiagnostics=[],this.resolveRegisteredCommands()}getCommandDiagnostics(){return this.commandDiagnostics}getCommand(name){return this.resolveRegisteredCommands().find(command=>command.invocationName===name)}shutdown(){this.shutdownHandler()}getActiveTools(){return this.assertActive(),this.runtime.getActiveTools()}createContext(){let runner=this,getModel2=this.getModel,getScopedModels=this.getScopedModels;return{get tasks(){return runner.assertActive(),runner.getTasks()},get ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get modelRuntime(){return runner.assertActive(),runner.modelRegistry.getRuntime()},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),getContextSnapshot:()=>(runner.assertActive(),runner.getContextSnapshotFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}createToolContext(toolCallId,signal){let runner=this;return Object.defineProperties(this.createContext(),{tools:{get(){return runner.assertActive(),runner.getCallableToolsFn()}},executeTool:{value:async(name,args,options={})=>(runner.assertActive(),runner.executeToolFn?runner.executeToolFn(toolCallId,name,args,{...options,signal:options.signal??signal}):{toolCall:{type:"toolCall",id:`${toolCallId}/0`,name,arguments:{}},result:{content:[{type:"text",text:"Nested tool calls are not available in this context"}],details:{}},isError:!0})}})}createCommandContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));return context.getSystemPromptOptions=()=>(this.assertActive(),this.getSystemPromptOptionsFn()),context.waitForIdle=()=>(this.assertActive(),this.waitForIdleFn()),context.newSession=options=>(this.assertActive(),this.newSessionHandler(options)),context.fork=(entryId,options)=>(this.assertActive(),this.forkHandler(entryId,options)),context.navigateTree=(targetId,options)=>(this.assertActive(),this.navigateTreeHandler(targetId,options)),context.switchSession=(sessionPath,options)=>(this.assertActive(),this.switchSessionHandler(sessionPath,options)),context.reload=()=>(this.assertActive(),this.reloadHandler()),context}async emitBoundary(baseEvent,buildContext){let ctx=this.createContext(),entries=[],shouldContinue=!1,context=await buildContext(entries),valid3=!0;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,baseEvent.type))for(let handler of handlers){let event={...baseEvent,entries,continue:shouldContinue,context};try{let handlerResult=await handler(event,ctx);handlerResult?.entries!==void 0&&(entries=handlerResult.entries),handlerResult?.continue!==void 0&&(shouldContinue=handlerResult.continue)}catch(err){this.emitError({extensionPath:ext2.path,event:baseEvent.type,error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}try{context=await buildContext(entries),valid3=!0}catch(err){valid3=!1,this.emitError({extensionPath:ext2.path,event:baseEvent.type,error:`Invalid boundary entries: ${err instanceof Error?err.message:String(err)}`,stack:err instanceof Error?err.stack:void 0})}}return valid3?{entries,continue:shouldContinue,context,valid:!0}:{entries:[],continue:!1,context,valid:!1}}isSessionBeforeEvent(event){return event.type==="session_before_switch"||event.type==="session_before_fork"||event.type==="session_before_compact"||event.type==="session_before_tree"}async emit(event){let ctx=this.createContext(),result2;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,event.type))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(this.isSessionBeforeEvent(event)&&handlerResult&&(result2=handlerResult,result2.cancel))return result2}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:event.type,error:message,stack})}return result2}async emitCacheWarmingDecision(event){let ctx=this.createContext(),action=event.action;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,event.type))for(let handler of handlers)try{let result2=await handler(event,ctx);result2?.action!==void 0&&(action=result2.action)}catch(err){this.emitError({extensionPath:ext2.path,event:event.type,error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}return action}async emitMessageEnd(event){let ctx=this.createContext(),currentMessage=event.message,modified=!1;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"message_end"))for(let handler of handlers)try{let currentEvent={...event,message:currentMessage},handlerResult=await handler(currentEvent,ctx);if(!handlerResult?.message)continue;if(handlerResult.message.role!==currentMessage.role){this.emitError({extensionPath:ext2.path,event:"message_end",error:"message_end handlers must return a message with the same role"});continue}currentMessage=handlerResult.message,modified=!0}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"message_end",error:message,stack})}return modified?currentMessage:void 0}async emitToolResult(event){let ctx=this.createContext(),currentEvent={...event},modified=!1;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"tool_result"))for(let handler of handlers)try{let handlerResult=await handler(currentEvent,ctx);if(!handlerResult)continue;handlerResult.content!==void 0&&(currentEvent.content=handlerResult.content,handlerResult.structuredContent===void 0&&delete currentEvent.structuredContent,modified=!0),handlerResult.details!==void 0&&(currentEvent.details=handlerResult.details,modified=!0),handlerResult.structuredContent!==void 0&&(currentEvent.structuredContent=handlerResult.structuredContent,modified=!0),handlerResult.isError!==void 0&&(currentEvent.isError=handlerResult.isError,modified=!0),handlerResult.usage!==void 0&&(currentEvent.usage=handlerResult.usage,modified=!0)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"tool_result",error:message,stack})}if(modified)return{content:currentEvent.content,details:currentEvent.details,structuredContent:currentEvent.structuredContent,isError:currentEvent.isError,usage:currentEvent.usage}}async emitToolCall(event){let ctx=this.createContext(),result2;for(let{handlers}of snapshotEventHandlers(this.extensions,"tool_call"))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result2=handlerResult,result2.block))return result2}return result2}async emitUserBash(event){let ctx=this.createContext();for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"user_bash"))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult===void 0)continue;if(!isUserBashEventResult(handlerResult))throw new Error("Invalid user_bash handler result: return undefined for local execution or exactly one valid { operations } or { result } object");return handlerResult}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;throw this.emitError({extensionPath:ext2.path,event:"user_bash",error:message,stack}),err}}async emitContext(messages){let ctx=this.createContext(),currentMessages=structuredClone(messages);for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"context"))for(let handler of handlers)try{let visibleMessages=currentMessages.filter(message=>message.role!=="system"),visibleSnapshot=visibleMessages.slice(),returned=(await handler({type:"context",messages:visibleMessages},ctx))?.messages??(sameMessages(visibleMessages,visibleSnapshot)?void 0:visibleMessages);if(!returned)continue;currentMessages=restoreSystemMessages(currentMessages,visibleSnapshot,returned)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context",error:message,stack})}for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"context_with_system"))for(let handler of handlers)try{let hadLeadingSystemMessage=currentMessages[0]?.role==="system";currentMessages=(await handler({type:"context_with_system",messages:currentMessages},ctx))?.messages??currentMessages,hadLeadingSystemMessage&¤tMessages[0]?.role!=="system"&&this.emitError({extensionPath:ext2.path,event:"context_with_system",error:"Handler removed the leading system message; the request has no prompt or initial tool declarations. Keep it at index 0 or replace a dropped prefix with getCurrentSystemMessage()."})}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context_with_system",error:message,stack})}return currentMessages}async emitBeforeProviderRequest(payload){let ctx=this.createContext(),currentPayload=payload;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_provider_request"))for(let handler of handlers)try{let handlerResult=await handler({type:"before_provider_request",payload:currentPayload},ctx);handlerResult!==void 0&&(currentPayload=handlerResult)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_request",error:message,stack})}return currentPayload}async emitBeforeProviderHeaders(headers){let ctx=this.createContext();for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_provider_headers"))for(let handler of handlers)try{await handler({type:"before_provider_headers",headers},ctx)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_headers",error:message,stack})}return headers}async emitBeforeAgentStart(trigger,systemPromptOptions){let currentOptions=normalizeBuildSystemPromptOptions(systemPromptOptions),renderCurrentSystemPrompt=()=>buildSystemPrompt(currentOptions),ctx=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));ctx.getSystemPrompt=()=>(this.assertActive(),renderCurrentSystemPrompt());let messages=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_agent_start"))for(let handler of handlers)try{let event={...trigger,type:"before_agent_start",get systemPrompt(){return renderCurrentSystemPrompt()},systemPromptOptions:currentOptions},handlerResult=await handler(event,ctx);if(handlerResult){let result2=handlerResult;result2.message&&messages.push(result2.message),result2.systemPrompt!==void 0&&(currentOptions.forceSystemPrompt=result2.systemPrompt)}}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_agent_start",error:message,stack})}return{messages,systemPromptOptions:currentOptions}}async emitResourcesDiscover(cwd,reason){let ctx=this.createContext(),skillPaths=[],promptPaths=[],themePaths=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"resources_discover"))for(let handler of handlers)try{let result2=await handler({type:"resources_discover",cwd,reason},ctx);result2?.skillPaths?.length&&skillPaths.push(...result2.skillPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result2?.promptPaths?.length&&promptPaths.push(...result2.promptPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result2?.themePaths?.length&&themePaths.push(...result2.themePaths.map(path14=>({path:path14,extensionPath:ext2.path})))}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"resources_discover",error:message,stack})}return{skillPaths,promptPaths,themePaths}}async emitInput(text2,images,source,streamingBehavior){let ctx=this.createContext(),currentText=text2,currentImages=images;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"input"))for(let handler of handlers)try{let result2=await handler({type:"input",text:currentText,images:currentImages,source,streamingBehavior},ctx);if(result2?.action==="handled")return result2;result2?.action==="transform"&&(currentText=result2.text,currentImages=result2.images??currentImages)}catch(err){this.emitError({extensionPath:ext2.path,event:"input",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}return currentText!==text2||currentImages!==images?{action:"transform",text:currentText,images:currentImages}:{action:"continue"}}};var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
|
|
683
|
+
</${name}>`);return sections}function buildSystemPromptState(input2){return input2.forceSystemPrompt!==void 0?{content:input2.forceSystemPrompt}:{content:"",sections:buildSystemPromptSections(input2)}}function buildSystemPrompt(input2){return getSystemMessageText({role:"system",...buildSystemPromptState(input2),timestamp:0})}function diffSystemPromptSections(previous,current){let patch={};for(let[name,text2]of Object.entries(current))previous[name]!==text2&&(patch[name]=text2);for(let name of Object.keys(previous))current[name]===void 0&&(patch[name]=null);return Object.keys(patch).length>0?patch:void 0}var RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS=["app.interrupt","app.clear","app.exit","app.suspend","app.thinking.cycle","app.model.cycleForward","app.model.cycleBackward","app.model.select","app.tools.expand","app.thinking.toggle","app.editor.external","app.message.copy","app.message.followUp","tui.input.submit","tui.select.confirm","tui.select.cancel","tui.input.copy","tui.editor.deleteToLineEnd"],buildBuiltinKeybindings=resolvedKeybindings=>{let builtinKeybindings={},reserved2=new Set([...RESERVED_KEYBINDINGS_FOR_EXTENSION_CONFLICTS,...getReservedKeybindings()]);for(let[keybinding,keys]of Object.entries(resolvedKeybindings)){if(keys===void 0)continue;let keyList=Array.isArray(keys)?keys:[keys],restrictOverride=reserved2.has(keybinding);for(let key of keyList){let normalizedKey=key.toLowerCase();builtinKeybindings[normalizedKey]?.restrictOverride&&!restrictOverride||(builtinKeybindings[normalizedKey]={keybinding,restrictOverride})}}return builtinKeybindings};function isUserBashEventResult(value){if(typeof value!="object"||value===null)return!1;let candidate=value,hasOperations=candidate.operations!==void 0,hasResult=candidate.result!==void 0;if(hasOperations===hasResult)return!1;if(hasOperations){let operations=candidate.operations;return typeof operations!="object"||operations===null?!1:typeof operations.exec=="function"}let result2=candidate.result;if(typeof result2!="object"||result2===null)return!1;let resultRecord=result2;return typeof resultRecord.output=="string"&&"exitCode"in resultRecord&&(resultRecord.exitCode===void 0||typeof resultRecord.exitCode=="number")&&typeof resultRecord.cancelled=="boolean"&&typeof resultRecord.truncated=="boolean"&&(resultRecord.fullOutputPath===void 0||typeof resultRecord.fullOutputPath=="string")}async function emitSessionShutdownEvent(extensionRunner,event){return extensionRunner.hasHandlers("session_shutdown")?(await extensionRunner.emit(event),!0):!1}function snapshotEventHandlers(extensions,event){return extensions.map(ext2=>({ext:ext2,handlers:ext2.handlers.get(event)?.slice()??[]}))}function sameMessages(left,right){return left.length===right.length&&left.every((message,index3)=>message===right[index3])}function restoreSystemMessages(current,visible,returned){if(sameMessages(returned,visible))return current;let head=getCurrentSystemMessage(current);return head?[head,...returned]:returned}async function emitProjectTrustEvent(extensionsResult,event,ctx){let errors=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(extensionsResult.extensions,"project_trust"))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult.trusted==="undecided")continue;return{result:handlerResult,errors}}catch(error){errors.push({extensionPath:ext2.path,event:event.type,error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:void 0})}return{errors}}var noOpUIContext={select:async()=>{},confirm:async()=>!1,input:async()=>{},notify:()=>{},onTerminalInput:()=>()=>{},setStatus:()=>{},setWorkingMessage:()=>{},setWorkingVisible:()=>{},setWorkingIndicator:()=>{},setHiddenThinkingLabel:()=>{},setWidget:()=>{},setFooter:()=>{},setHeader:()=>{},setTitle:()=>{},custom:async()=>{},pasteToEditor:()=>{},setEditorText:()=>{},getEditorText:()=>"",editor:async()=>{},addAutocompleteProvider:()=>{},setEditorComponent:()=>{},getEditorComponent:()=>{},get theme(){return theme},getAllThemes:()=>[],getTheme:()=>{},setTheme:_theme=>({success:!1,error:"UI not available"}),getToolsExpanded:()=>!1,setToolsExpanded:()=>{}},ExtensionRunner=class{constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.unboundTasks=new TaskRuntime,this.getTasks=()=>this.unboundTasks,this.mode="print",this.errorListeners=new Set,this.getModel=()=>{},this.getScopedModels=()=>[],this.isIdleFn=()=>!0,this.isProjectTrustedFn=()=>!0,this.getSignalFn=()=>{},this.waitForIdleFn=async()=>{},this.abortFn=()=>{},this.hasPendingMessagesFn=()=>!1,this.getContextUsageFn=()=>{},this.getContextSnapshotFn=async()=>{throw new Error("Context snapshots are not available in this host")},this.compactFn=()=>{},this.getSystemPromptFn=()=>"",this.getSystemPromptOptionsFn=()=>normalizeBuildSystemPromptOptions({cwd:this.cwd}),this.getCallableToolsFn=()=>[],this.reportedMcpServers=new Set,this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{},this.shutdownHandler=()=>{},this.shortcutDiagnostics=[],this.commandDiagnostics=[],this.uiPromptDepth=0,this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions2,contextActions,providerActions){this.runtime.sendMessage=actions2.sendMessage,this.runtime.sendUserMessage=actions2.sendUserMessage,this.runtime.appendEntry=actions2.appendEntry,this.runtime.setSessionName=actions2.setSessionName,this.runtime.getSessionName=actions2.getSessionName,this.runtime.setLabel=actions2.setLabel,this.runtime.getActiveTools=actions2.getActiveTools,this.runtime.getAllTools=actions2.getAllTools,this.runtime.getSettings=actions2.getSettings,this.runtime.setActiveTools=actions2.setActiveTools,this.runtime.refreshTools=actions2.refreshTools,this.runtime.getCommands=actions2.getCommands,this.runtime.setModel=actions2.setModel,this.runtime.getThinkingLevel=actions2.getThinkingLevel,this.runtime.setThinkingLevel=actions2.setThinkingLevel,this.runtime.createContext=()=>this.createContext(),this.getTasks=contextActions.getTasks??(()=>this.unboundTasks),this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,contextActions.getContextSnapshot&&(this.getContextSnapshotFn=contextActions.getContextSnapshot),this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>normalizeBuildSystemPromptOptions({cwd:this.cwd})),this.executeToolFn=contextActions.executeTool,this.getCallableToolsFn=contextActions.getCallableTools??(()=>[]),this.runtime.mcpServers.setChangeListener(()=>{this.emit({type:"mcp_servers_change",servers:this.runtime.mcpServers.list()}),this.reportUnhandledMcpServers()});for(let{name,config,extensionPath}of this.runtime.pendingProviderRegistrations)try{providerActions?.registerProvider?providerActions.registerProvider(name,config):this.modelRegistry.registerProvider(name,config)}catch(err){this.emitError({extensionPath,event:"register_provider",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingProviderRegistrations=[];for(let{provider,extensionPath}of this.runtime.pendingNativeProviderRegistrations)try{providerActions?.registerNativeProvider?providerActions.registerNativeProvider(provider):this.modelRegistry.registerProvider(provider)}catch(err){this.emitError({extensionPath,event:"register_provider",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingNativeProviderRegistrations=[];let registerVirtualModel=definition=>{providerActions?.registerVirtualModel?providerActions.registerVirtualModel(definition):this.modelRegistry.registerVirtualModel(definition)};for(let{definition,extensionPath}of this.runtime.pendingVirtualModelRegistrations)try{registerVirtualModel(definition)}catch(err){this.emitError({extensionPath,event:"register_virtual_model",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}this.runtime.pendingVirtualModelRegistrations=[],this.runtime.registerProvider=(name,config)=>{if(providerActions?.registerProvider){providerActions.registerProvider(name,config);return}this.modelRegistry.registerProvider(name,config)},this.runtime.registerNativeProvider=provider=>{if(providerActions?.registerNativeProvider){providerActions.registerNativeProvider(provider);return}this.modelRegistry.registerProvider(provider)},this.runtime.unregisterProvider=name=>{if(providerActions?.unregisterProvider){providerActions.unregisterProvider(name);return}this.modelRegistry.unregisterProvider(name)},this.runtime.registerVirtualModel=registerVirtualModel,this.runtime.unregisterVirtualModel=(provider,id)=>{providerActions?.unregisterVirtualModel?providerActions.unregisterVirtualModel(provider,id):this.modelRegistry.unregisterVirtualModel(provider,id)}}bindCommandContext(actions2){if(actions2){this.waitForIdleFn=actions2.waitForIdle,this.newSessionHandler=actions2.newSession,this.forkHandler=actions2.fork,this.navigateTreeHandler=actions2.navigateTree,this.switchSessionHandler=actions2.switchSession,this.reloadHandler=actions2.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(err){throw finish(),err}}emitUIPromptEvent(event){queueMicrotask(()=>{this.emit(event)})}getUIContext(){return this.uiContext}hasUI(){return this.uiContext!==noOpUIContext}getExtensionPaths(){return this.extensions.map(e=>e.path)}getAllRegisteredTools(){let toolsByName=new Map;for(let ext2 of this.extensions)for(let tool of ext2.tools.values())toolsByName.has(tool.definition.name)||toolsByName.set(tool.definition.name,tool);return Array.from(toolsByName.values())}getToolDefinition(toolName){for(let ext2 of this.extensions){let tool=ext2.tools.get(toolName);if(tool)return tool.definition}}getFlags(){let allFlags=new Map;for(let ext2 of this.extensions)for(let[name,flag]of ext2.flags)allFlags.has(name)||allFlags.set(name,flag);return allFlags}setFlagValue(name,value){this.runtime.flagValues.set(name,value)}getFlagValues(){return new Map(this.runtime.flagValues)}getShortcuts(resolvedKeybindings){this.shortcutDiagnostics=[];let builtinKeybindings=buildBuiltinKeybindings(resolvedKeybindings),extensionShortcuts=new Map,addDiagnostic=(message,extensionPath)=>{this.shortcutDiagnostics.push({type:"warning",message,path:extensionPath}),this.hasUI()||console.warn(message)};for(let ext2 of this.extensions)for(let[key,shortcut]of ext2.shortcuts){let normalizedKey=key.toLowerCase(),builtInKeybinding=builtinKeybindings[normalizedKey];if(builtInKeybinding?.restrictOverride===!0){addDiagnostic(`Extension shortcut '${key}' from ${shortcut.extensionPath} conflicts with built-in shortcut. Skipping.`,shortcut.extensionPath);continue}builtInKeybinding?.restrictOverride===!1&&addDiagnostic(`Extension shortcut conflict: '${key}' is built-in shortcut for ${builtInKeybinding.keybinding} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath);let existingExtensionShortcut=extensionShortcuts.get(normalizedKey);existingExtensionShortcut&&addDiagnostic(`Extension shortcut conflict: '${key}' registered by both ${existingExtensionShortcut.extensionPath} and ${shortcut.extensionPath}. Using ${shortcut.extensionPath}.`,shortcut.extensionPath),extensionShortcuts.set(normalizedKey,shortcut)}return extensionShortcuts}getShortcutDiagnostics(){return this.shortcutDiagnostics}invalidate(message="This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."){this.staleMessage||(this.unboundTasks.close(),this.staleMessage=message,this.runtime.invalidate(message))}assertActive(){if(this.staleMessage)throw new Error(this.staleMessage)}onError(listener){return this.errorListeners.add(listener),()=>this.errorListeners.delete(listener)}emitError(error){for(let listener of this.errorListeners)listener(error)}reportUnhandledMcpServers(){if(!this.hasHandlers("mcp_servers_change"))for(let server of this.runtime.mcpServers.list())this.reportedMcpServers.has(server.name)||(this.reportedMcpServers.add(server.name),this.emitError({extensionPath:server.extensionPath,event:"register_mcp_server",error:`MCP server "${server.name}" is registered, but no loaded extension connects MCP servers; another extension may have replaced the built-in MCP support`}))}hasHandlers(eventType){for(let ext2 of this.extensions){let handlers=ext2.handlers.get(eventType);if(handlers&&handlers.length>0)return!0}return!1}getMessageRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.messageRenderers.get(customType);if(renderer)return renderer}}getMarkdownTransformers(){return this.extensions.flatMap(ext2=>ext2.markdownTransformer?[ext2.markdownTransformer]:[])}resolveToolRenderers(toolName,base){let resolvers=this.extensions.flatMap(ext2=>ext2.toolRenderers??[]),resolve20=index3=>index3<resolvers.length?resolvers[index3](toolName,()=>resolve20(index3+1)):base();return resolve20(0)}getEntryRenderer(customType){for(let ext2 of this.extensions){let renderer=ext2.entryRenderers?.get(customType);if(renderer)return renderer}}resolveRegisteredCommands(){let commands=[],counts=new Map;for(let ext2 of this.extensions)for(let command of ext2.commands.values())commands.push(command),counts.set(command.name,(counts.get(command.name)??0)+1);let seen=new Map,takenInvocationNames=new Set;return commands.map(command=>{let occurrence=(seen.get(command.name)??0)+1;seen.set(command.name,occurrence);let invocationName=(counts.get(command.name)??0)>1?`${command.name}:${occurrence}`:command.name;if(takenInvocationNames.has(invocationName)){let suffix=occurrence;do suffix++,invocationName=`${command.name}:${suffix}`;while(takenInvocationNames.has(invocationName))}return takenInvocationNames.add(invocationName),{...command,invocationName}})}getModelRegistry(){return this.modelRegistry}getRegisteredCommands(){return this.commandDiagnostics=[],this.resolveRegisteredCommands()}getCommandDiagnostics(){return this.commandDiagnostics}getCommand(name){return this.resolveRegisteredCommands().find(command=>command.invocationName===name)}shutdown(){this.shutdownHandler()}getActiveTools(){return this.assertActive(),this.runtime.getActiveTools()}createContext(){let runner=this,getModel2=this.getModel,getScopedModels=this.getScopedModels;return{get tasks(){return runner.assertActive(),runner.getTasks()},get ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get modelRuntime(){return runner.assertActive(),runner.modelRegistry.getRuntime()},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),getContextSnapshot:()=>(runner.assertActive(),runner.getContextSnapshotFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}createToolContext(toolCallId,signal){let runner=this;return Object.defineProperties(this.createContext(),{tools:{get(){return runner.assertActive(),runner.getCallableToolsFn()}},executeTool:{value:async(name,args,options={})=>(runner.assertActive(),runner.executeToolFn?runner.executeToolFn(toolCallId,name,args,{...options,signal:options.signal??signal}):{toolCall:{type:"toolCall",id:`${toolCallId}/0`,name,arguments:{}},result:{content:[{type:"text",text:"Nested tool calls are not available in this context"}],details:{}},isError:!0})}})}createCommandContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));return context.getSystemPromptOptions=()=>(this.assertActive(),this.getSystemPromptOptionsFn()),context.waitForIdle=()=>(this.assertActive(),this.waitForIdleFn()),context.newSession=options=>(this.assertActive(),this.newSessionHandler(options)),context.fork=(entryId,options)=>(this.assertActive(),this.forkHandler(entryId,options)),context.navigateTree=(targetId,options)=>(this.assertActive(),this.navigateTreeHandler(targetId,options)),context.switchSession=(sessionPath,options)=>(this.assertActive(),this.switchSessionHandler(sessionPath,options)),context.reload=()=>(this.assertActive(),this.reloadHandler()),context}async emitBoundary(baseEvent,buildContext){let ctx=this.createContext(),entries=[],shouldContinue=!1,context=await buildContext(entries),valid3=!0;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,baseEvent.type))for(let handler of handlers){let event={...baseEvent,entries,continue:shouldContinue,context};try{let handlerResult=await handler(event,ctx);handlerResult?.entries!==void 0&&(entries=handlerResult.entries),handlerResult?.continue!==void 0&&(shouldContinue=handlerResult.continue)}catch(err){this.emitError({extensionPath:ext2.path,event:baseEvent.type,error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}try{context=await buildContext(entries),valid3=!0}catch(err){valid3=!1,this.emitError({extensionPath:ext2.path,event:baseEvent.type,error:`Invalid boundary entries: ${err instanceof Error?err.message:String(err)}`,stack:err instanceof Error?err.stack:void 0})}}return valid3?{entries,continue:shouldContinue,context,valid:!0}:{entries:[],continue:!1,context,valid:!1}}isSessionBeforeEvent(event){return event.type==="session_before_switch"||event.type==="session_before_fork"||event.type==="session_before_compact"||event.type==="session_before_tree"}async emit(event){let ctx=this.createContext(),result2;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,event.type))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(this.isSessionBeforeEvent(event)&&handlerResult&&(result2=handlerResult,result2.cancel))return result2}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:event.type,error:message,stack})}return result2}async emitCacheWarmingDecision(event){let ctx=this.createContext(),action=event.action;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,event.type))for(let handler of handlers)try{let result2=await handler(event,ctx);result2?.action!==void 0&&(action=result2.action)}catch(err){this.emitError({extensionPath:ext2.path,event:event.type,error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}return action}async emitMessageEnd(event){let ctx=this.createContext(),currentMessage=event.message,modified=!1;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"message_end"))for(let handler of handlers)try{let currentEvent={...event,message:currentMessage},handlerResult=await handler(currentEvent,ctx);if(!handlerResult?.message)continue;if(handlerResult.message.role!==currentMessage.role){this.emitError({extensionPath:ext2.path,event:"message_end",error:"message_end handlers must return a message with the same role"});continue}currentMessage=handlerResult.message,modified=!0}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"message_end",error:message,stack})}return modified?currentMessage:void 0}async emitToolResult(event){let ctx=this.createContext(),currentEvent={...event},modified=!1;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"tool_result"))for(let handler of handlers)try{let handlerResult=await handler(currentEvent,ctx);if(!handlerResult)continue;handlerResult.content!==void 0&&(currentEvent.content=handlerResult.content,handlerResult.structuredContent===void 0&&delete currentEvent.structuredContent,modified=!0),handlerResult.details!==void 0&&(currentEvent.details=handlerResult.details,modified=!0),handlerResult.structuredContent!==void 0&&(currentEvent.structuredContent=handlerResult.structuredContent,modified=!0),handlerResult.isError!==void 0&&(currentEvent.isError=handlerResult.isError,modified=!0),handlerResult.usage!==void 0&&(currentEvent.usage=handlerResult.usage,modified=!0)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"tool_result",error:message,stack})}if(modified)return{content:currentEvent.content,details:currentEvent.details,structuredContent:currentEvent.structuredContent,isError:currentEvent.isError,usage:currentEvent.usage}}async emitToolCall(event){let ctx=this.createContext(),result2;for(let{handlers}of snapshotEventHandlers(this.extensions,"tool_call"))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result2=handlerResult,result2.block))return result2}return result2}async emitUserBash(event){let ctx=this.createContext();for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"user_bash"))for(let handler of handlers)try{let handlerResult=await handler(event,ctx);if(handlerResult===void 0)continue;if(!isUserBashEventResult(handlerResult))throw new Error("Invalid user_bash handler result: return undefined for local execution or exactly one valid { operations } or { result } object");return handlerResult}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;throw this.emitError({extensionPath:ext2.path,event:"user_bash",error:message,stack}),err}}async emitContext(messages){let ctx=this.createContext(),currentMessages=structuredClone(messages);for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"context"))for(let handler of handlers)try{let visibleMessages=currentMessages.filter(message=>message.role!=="system"),visibleSnapshot=visibleMessages.slice(),returned=(await handler({type:"context",messages:visibleMessages},ctx))?.messages??(sameMessages(visibleMessages,visibleSnapshot)?void 0:visibleMessages);if(!returned)continue;currentMessages=restoreSystemMessages(currentMessages,visibleSnapshot,returned)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context",error:message,stack})}for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"context_with_system"))for(let handler of handlers)try{let hadLeadingSystemMessage=currentMessages[0]?.role==="system";currentMessages=(await handler({type:"context_with_system",messages:currentMessages},ctx))?.messages??currentMessages,hadLeadingSystemMessage&¤tMessages[0]?.role!=="system"&&this.emitError({extensionPath:ext2.path,event:"context_with_system",error:"Handler removed the leading system message; the request has no prompt or initial tool declarations. Keep it at index 0 or replace a dropped prefix with getCurrentSystemMessage()."})}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"context_with_system",error:message,stack})}return currentMessages}async emitBeforeProviderRequest(payload){let ctx=this.createContext(),currentPayload=payload;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_provider_request"))for(let handler of handlers)try{let handlerResult=await handler({type:"before_provider_request",payload:currentPayload},ctx);handlerResult!==void 0&&(currentPayload=handlerResult)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_request",error:message,stack})}return currentPayload}async emitBeforeProviderHeaders(headers){let ctx=this.createContext();for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_provider_headers"))for(let handler of handlers)try{await handler({type:"before_provider_headers",headers},ctx)}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_provider_headers",error:message,stack})}return headers}async emitBeforeAgentStart(trigger,systemPromptOptions){let currentOptions=normalizeBuildSystemPromptOptions(systemPromptOptions),renderCurrentSystemPrompt=()=>buildSystemPrompt(currentOptions),ctx=Object.defineProperties({},Object.getOwnPropertyDescriptors(this.createContext()));ctx.getSystemPrompt=()=>(this.assertActive(),renderCurrentSystemPrompt());let messages=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"before_agent_start"))for(let handler of handlers)try{let event={...trigger,type:"before_agent_start",get systemPrompt(){return renderCurrentSystemPrompt()},systemPromptOptions:currentOptions},handlerResult=await handler(event,ctx);if(handlerResult){let result2=handlerResult;result2.message&&messages.push(result2.message),result2.systemPrompt!==void 0&&(currentOptions.forceSystemPrompt=result2.systemPrompt)}}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"before_agent_start",error:message,stack})}return{messages,systemPromptOptions:currentOptions}}async emitResourcesDiscover(cwd,reason){let ctx=this.createContext(),skillPaths=[],promptPaths=[],themePaths=[];for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"resources_discover"))for(let handler of handlers)try{let result2=await handler({type:"resources_discover",cwd,reason},ctx);result2?.skillPaths?.length&&skillPaths.push(...result2.skillPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result2?.promptPaths?.length&&promptPaths.push(...result2.promptPaths.map(path14=>({path:path14,extensionPath:ext2.path}))),result2?.themePaths?.length&&themePaths.push(...result2.themePaths.map(path14=>({path:path14,extensionPath:ext2.path})))}catch(err){let message=err instanceof Error?err.message:String(err),stack=err instanceof Error?err.stack:void 0;this.emitError({extensionPath:ext2.path,event:"resources_discover",error:message,stack})}return{skillPaths,promptPaths,themePaths}}async emitInput(text2,images,source,streamingBehavior){let ctx=this.createContext(),currentText=text2,currentImages=images;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"input"))for(let handler of handlers)try{let result2=await handler({type:"input",text:currentText,images:currentImages,source,streamingBehavior},ctx);if(result2?.action==="handled")return result2;result2?.action==="transform"&&(currentText=result2.text,currentImages=result2.images??currentImages)}catch(err){this.emitError({extensionPath:ext2.path,event:"input",error:err instanceof Error?err.message:String(err),stack:err instanceof Error?err.stack:void 0})}return currentText!==text2||currentImages!==images?{action:"transform",text:currentText,images:currentImages}:{action:"continue"}}};var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
|
|
684
684
|
|
|
685
685
|
<summary>
|
|
686
686
|
`,COMPACTION_SUMMARY_SUFFIX=`
|
|
@@ -878,43 +878,7 @@ Hint: ${hints.join(`
|
|
|
878
878
|
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+=`
|
|
879
879
|
\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,outputSchema:definition.outputSchema,constrainedSampling:definition.constrainedSampling,prepareArguments:wrapPrepareArguments(definition),executionMode:definition.executionMode,execute:(toolCallId,params,signal,onUpdate,ctx)=>definition.execute(toolCallId,params,signal,onUpdate,ctx??ctxFactory?.(toolCallId,signal))}}function createToolDefinitionFromAgentTool(tool){return{name:tool.name,label:tool.label,description:tool.description,parameters:tool.parameters,outputSchema:tool.outputSchema,constrainedSampling:tool.constrainedSampling,prepareArguments:tool.prepareArguments,executionMode:tool.executionMode,execute:async(toolCallId,params,signal,onUpdate)=>tool.execute(toolCallId,params,signal,onUpdate)}}function wrapRegisteredTool(registeredTool,runner){return wrapToolDefinition(registeredTool.definition,(toolCallId,signal)=>runner.createToolContext(toolCallId,signal))}function wrapRegisteredTools(registeredTools,runner){return registeredTools.map(tool=>wrapRegisteredTool(tool,runner))}import*as fs5 from"node:fs";import{createRequire as createRequire5}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(resolve20=>{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),resolve20({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve20({stdout,stderr,code:1,killed})})})}function toolPatternRegExp(pattern){let source=pattern.split("*").map(part=>part.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join(".*");return new RegExp(`^${source}$`)}function createToolNameMatcher(entries){let names2=new Set(entries.filter(entry=>!entry.includes("*"))),patterns=entries.filter(entry=>entry.includes("*")).map(toolPatternRegExp);return name=>names2.has(name)||patterns.some(pattern=>pattern.test(name))}var LIST_MCP_RESOURCES_TOOL="list_mcp_resources",LIST_MCP_RESOURCE_TEMPLATES_TOOL="list_mcp_resource_templates",READ_MCP_RESOURCE_TOOL="read_mcp_resource",MCP_RESOURCE_TOOLS=new Set([LIST_MCP_RESOURCES_TOOL,LIST_MCP_RESOURCE_TEMPLATES_TOOL,READ_MCP_RESOURCE_TOOL]);function isMcpToolName(name){return name.startsWith("mcp__")||MCP_RESOURCE_TOOLS.has(name)}var MCP_EXPOSURES=["codemode","deferred","direct","hidden"],MCP_EXPOSURE_ALIASES={"codemode-deferred":"codemode"},LOOPBACK_HOSTS=["localhost","127.0.0.1","[::1]"];function isLoopbackRedirectUri(value){if(!URL.canParse(value))return!1;let url=new URL(value);return url.protocol==="http:"&&LOOPBACK_HOSTS.includes(url.hostname)&&url.search===""&&url.hash===""}var SERVER_NAME=/^[A-Za-z0-9_-]+$/;function mcpNamespace(server){return`mcp__${server.replace(/-/g,"_")}`}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isStringRecord(value){return isRecord3(value)&&Object.values(value).every(entry=>typeof entry=="string")}function validateOAuth(value){if(value===void 0)return;if(!isRecord3(value))return"oauth must be an object";if(value.clientId!==void 0&&typeof value.clientId!="string")return"oauth.clientId must be a string";if(value.clientSecret!==void 0&&typeof value.clientSecret!="string")return"oauth.clientSecret must be a string";let port=value.callbackPort;if(port!==void 0&&(typeof port!="number"||!Number.isInteger(port)||port<1||port>65535))return"oauth.callbackPort must be a port number";if(value.callbackUrl!==void 0){if(typeof value.callbackUrl!="string"||!isLoopbackRedirectUri(value.callbackUrl))return"oauth.callbackUrl must be an http URI on localhost, 127.0.0.1, or [::1] without query or fragment";let urlPort=new URL(value.callbackUrl).port;if(urlPort&&port!==void 0&&Number(urlPort)!==port)return"oauth.callbackUrl and oauth.callbackPort name different ports"}if(value.scope!==void 0&&typeof value.scope!="string")return"oauth.scope must be a string";if(value.clientName!==void 0&&(typeof value.clientName!="string"||!value.clientName.trim()))return"oauth.clientName must be a non-empty string";if(value.clientRegistration!==void 0&&value.clientRegistration!=="dcr"){if(value.clientRegistration!=="cimd")return'oauth.clientRegistration must be "dcr" or "cimd"';if(value.clientId!==void 0||value.clientName!==void 0)return'oauth.clientRegistration "cimd" cannot be combined with oauth.clientId or oauth.clientName';let callback=typeof value.callbackUrl=="string"?new URL(value.callbackUrl):void 0;if(callback&&(callback.hostname==="[::1]"||callback.pathname!=="/callback"))return'oauth.clientRegistration "cimd" requires oauth.callbackUrl on localhost or 127.0.0.1 with path /callback'}let metadataUrl=value.authServerMetadataUrl;if(metadataUrl!==void 0){let url=typeof metadataUrl=="string"&&URL.canParse(metadataUrl)?new URL(metadataUrl):void 0;if(!url||!(url.protocol==="https:"||url.protocol==="http:"&&LOOPBACK_HOSTS.includes(url.hostname)))return"oauth.authServerMetadataUrl must be an https URL, or http on localhost, 127.0.0.1, or [::1]"}}function isExposure(value){return typeof value=="string"&&MCP_EXPOSURES.includes(value)}function resolveExposureAlias(value){return typeof value=="string"?MCP_EXPOSURE_ALIASES[value]??value:value}function resolveExposureAliases(value){let{exposure,toolExposure}=value,resolved={...value};return exposure!==void 0&&(resolved.exposure=resolveExposureAlias(exposure)),isRecord3(toolExposure)&&(resolved.toolExposure=Object.fromEntries(Object.entries(toolExposure).map(([tool,entry])=>[tool,resolveExposureAlias(entry)]))),resolved}function getMcpToolExposure(config,toolName){let overrides=config.toolExposure??{},exact=overrides[toolName];if(exact!==void 0)return exact;for(let[pattern,exposure]of Object.entries(overrides))if(pattern.includes("*")&&toolPatternRegExp(pattern).test(toolName))return exposure;return config.exposure??"codemode"}function validateMcpServerConfig(name,raw){if(!SERVER_NAME.test(name))return`invalid server name "${name}" (use letters, digits, "_" and "-")`;if(!isRecord3(raw))return`server "${name}" must be an object`;let value=resolveExposureAliases(raw),{type,exposure,enabled,timeout,toolExposure,description}=value,exposures=MCP_EXPOSURES.map(value2=>`"${value2}"`).join(", ");if(exposure!==void 0&&!isExposure(exposure))return`server "${name}": exposure must be one of ${exposures}`;if(toolExposure!==void 0){if(!isRecord3(toolExposure))return`server "${name}": toolExposure must map tool names to exposures`;for(let[tool,value2]of Object.entries(toolExposure))if(!isExposure(value2))return`server "${name}": toolExposure "${tool}" must be one of ${exposures}`}if(enabled!==void 0&&typeof enabled!="boolean")return`server "${name}": enabled must be a boolean`;if(description!==void 0&&typeof description!="string")return`server "${name}": description must be a string`;if(timeout!==void 0&&(typeof timeout!="number"||!(timeout>0)))return`server "${name}": timeout must be a positive number of seconds`;if(type==="sse")return`server "${name}": legacy SSE transport is not supported; use the streamable HTTP URL`;if(typeof value.url=="string"&&(type===void 0||type==="http"||type==="streamable-http")){if(!URL.canParse(value.url)||!/^https?:$/.test(new URL(value.url).protocol))return`server "${name}": url must be an http or https URL`;if(value.headers!==void 0&&!isStringRecord(value.headers))return`server "${name}": headers must map names to strings`;let oauthError=validateOAuth(value.oauth);if(oauthError)return`server "${name}": ${oauthError}`;if(value.auth!==void 0){if(!isRecord3(value.auth)||typeof value.auth.provider!="string"||!value.auth.provider)return`server "${name}": auth.provider must be a provider name`;let url=new URL(value.url);if(url.protocol!=="https:"&&!LOOPBACK_HOSTS.includes(url.hostname))return`server "${name}": auth requires an https URL, or http on localhost, 127.0.0.1, or [::1]`}return value}return typeof value.command=="string"&&(type===void 0||type==="stdio")?value.args!==void 0&&!(Array.isArray(value.args)&&value.args.every(arg=>typeof arg=="string"))?`server "${name}": args must be an array of strings`:value.env!==void 0&&!isStringRecord(value.env)?`server "${name}": env must map names to strings`:value.cwd!==void 0&&typeof value.cwd!="string"?`server "${name}": cwd must be a string`:value:`server "${name}" needs either "command" (stdio) or "url" (streamable HTTP)`}var McpServerRegistry=class{constructor(){this.servers=new Map}register(server){this.servers.set(server.name,server),this.changeListener?.()}unregister(name,extensionPath){this.servers.get(name)?.extensionPath===extensionPath&&(this.servers.delete(name),this.changeListener?.())}get(name){return this.servers.get(name)}list(){return[...this.servers.values()].map(server=>({...server,config:structuredClone(server.config)}))}setChangeListener(listener){this.changeListener=listener}};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(`
|
|
880
880
|
--- ${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)}
|
|
881
|
-
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire5(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-XNEYDLXF.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"),piAiModelsEntry=resolveImport("@earendil-works/pi-ai/models"),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/models":piAiModelsEntry,"@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/models":piAiModelsEntry,"@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,assertActive=()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,getSettings:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],mcpServers:new McpServerRegistry,pendingVirtualModelRegistrations:[],createContext:notInitialized,assertActive,invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)},registerVirtualModel:(definition,extensionPath="<unknown>")=>{runtime.pendingVirtualModelRegistrations.push({definition,extensionPath})},unregisterVirtualModel:(provider,id)=>{runtime.pendingVirtualModelRegistrations=runtime.pendingVirtualModelRegistrations.filter(({definition})=>definition.provider!==provider||definition.id!==id)}};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){if(assertActive(),typeof name!="string"||name.length===0)throw new Error(`Command registered by extension "${extension.path}" must have a non-empty string name. Use pi.registerCommand("name", { description, handler }).`);if(typeof options?.handler!="function")throw new Error(`Command "/${name}" registered by extension "${extension.path}" must define handler().`);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)},registerToolRenderer(resolver){assertActive(),extension.toolRenderers??=[],extension.toolRenderers.push(resolver)},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()},getSettings(){return assertActive(),runtime.getSettings()},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))},registerMcpServer(name,config){assertActive();let validated=validateMcpServerConfig(name,config);if(typeof validated=="string")throw new Error(`Invalid MCP server registered by extension "${extension.path}": ${validated}`);let owner=runtime.mcpServers.get(name)?.extensionPath;if(owner!==void 0&&owner!==extension.path)throw new Error(`MCP server "${name}" is already registered by extension "${owner}"`);let clash=runtime.mcpServers.list().find(server2=>server2.name!==name&&mcpNamespace(server2.name)===mcpNamespace(name));if(clash)throw new Error(`MCP server "${name}" conflicts with registered server "${clash.name}"`);let server={name,config:structuredClone(validated),extensionPath:extension.path};applyRuntimeChange(()=>runtime.mcpServers.register(server))},unregisterMcpServer(name){assertActive(),applyRuntimeChange(()=>runtime.mcpServers.unregister(name,extension.path))},getMcpServers(){return assertActive(),runtime.mcpServers.list()},registerVirtualModel(model){assertActive();let definition={...model,route:request=>model.route(request,runtime.createContext())};applyRuntimeChange(()=>runtime.registerVirtualModel(definition,extension.path))},unregisterVirtualModel(provider,id){assertActive(),applyRuntimeChange(()=>runtime.unregisterVirtualModel(provider,id))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let 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=getSyntheticPathSource(extensionPath)??"local",baseDir=isSyntheticPath(extensionPath)?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(err){return{extension:null,error:`Failed to load extension: ${err instanceof Error?err.message:String(err)}`}}}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=[],warnings=[],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,warnings,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,modelId){return this.runtime.getModel(provider,modelId)}findOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}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)}getModelsOfType(type,provider){return this.runtime.getModelsOfType(type,provider)}getAvailableOfType(type,provider,options){return this.runtime.getAvailableOfType(type,provider,options)}getModelOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}classify(model,context,options){return this.runtime.classify(model,context,options)}generateImages(model,context,options){return this.runtime.generateImages(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)}registerVirtualModel(definition){this.runtime.registerVirtualModel(definition)}unregisterVirtualModel(providerName,id){this.runtime.unregisterVirtualModel(providerName,id)}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,keep="end"){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=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var VisualLinePreview=class{constructor(options){this.options=options}render(width){if(this.cachedLines===void 0||this.cachedWidth!==width){let{text:text2,maxVisualLines,keep,formatHint}=this.options,preview=truncateToVisualLines(text2,maxVisualLines,width,0,keep),lines=preview.visualLines;if(preview.skippedCount>0){let hint=truncateToWidth(formatHint(preview.skippedCount),width,"...");this.cachedLines=keep==="start"?[...lines,hint]:[hint,...lines]}else this.cachedLines=lines;this.cachedWidth=width}return this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}};import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";var ST="(?:\\u0007|\\u001B\\u005C|\\u009C)",OSC_START="\\u001B\\]",CSI_START="[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?",CSI_FINAL="[\\dA-PR-TZcf-nq-uy=><~]",ansiRegex=new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`,"g"),unfinishedAnsiAtEndRegex=new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`),MAX_PENDING_ANSI_LENGTH=256;function splitIncompleteAnsiSuffix(value){if(!value.includes("\x1B")&&!value.includes("\x9B"))return{complete:value,pending:""};let windowStart=Math.max(0,value.length-MAX_PENDING_ANSI_LENGTH),match2=unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));if(!match2)return{complete:value,pending:""};let splitAt=windowStart+match2.index;return{complete:value.slice(0,splitAt),pending:value.slice(splitAt)}}function stripAnsi(value){if(typeof value!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);return!value.includes("\x1B")&&!value.includes("\x9B")?value:value.replace(ansiRegex,"")}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(value){return typeof value=="string"?value:value==null?"":null}function parseLineNumber(value){return typeof value=="string"&&value.trim()!==""&&(value=Number(value)),typeof value=="number"&&Number.isFinite(value)?value:void 0}function formatReadLineRange(offset,limit){if(offset==null&&limit==null)return"";let start=offset==null?1:parseLineNumber(offset);if(start===void 0)return"";if(limit==null)return`:${start}`;let count=parseLineNumber(limit);if(count===void 0)return"";let end=start+count-1;return`:${start}${end?`-${end}`:""}`}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(`
|
|
882
|
-
`),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(`
|
|
883
|
-
`);output=output?`${output}
|
|
884
|
-
${imageIndicators}`:imageIndicators}return output}var COLLAPSED_ARGS_CHARS=100;function formatToolCallWithArgs(title,args,theme2,expanded){let header2=theme2.fg("toolTitle",theme2.bold(title));if(args==null)return header2;let entries=typeof args=="object"&&!Array.isArray(args)?Object.entries(args):[["args",args]];if(entries.length===0)return header2;if(expanded){let lines=entries.map(([key,value])=>{let text2=typeof value=="string"?value:JSON.stringify(value,null,2)??String(value);return` ${key}: ${replaceTabs(text2).replace(/\r/g,"").split(`
|
|
885
|
-
`).join(`
|
|
886
|
-
`)}`});return`${header2}
|
|
887
|
-
${theme2.fg("muted",lines.join(`
|
|
888
|
-
`))}`}let pairs=entries.map(([key,value])=>`${key}=${JSON.stringify(value)??String(value)}`).join(" "),preview=pairs.length>COLLAPSED_ARGS_CHARS?`${pairs.slice(0,COLLAPSED_ARGS_CHARS-3)}...`:pairs;return`${header2} ${theme2.fg("muted",preview)}`}function formatToolDuration(ms){let seconds=ms/1e3;if(seconds<60)return`${seconds.toFixed(1)}s`;let totalSeconds=Math.floor(seconds),minutes=Math.floor(totalSeconds/60),remainder=totalSeconds%60;return minutes<60?`${minutes}m ${remainder}s`:`${Math.floor(minutes/60)}h ${minutes%60}m ${remainder}s`}function startToolTimer(context){let state2=context.state;context.executionStarted&&state2.startedAt===void 0&&(state2.startedAt=Date.now(),state2.endedAt=void 0)}function toolTimerText(context,isPartial){let state2=context.state;if(state2.startedAt!==void 0&&isPartial&&!state2.interval&&(state2.interval=setInterval(()=>context.invalidate(),1e3)),(!isPartial||context.isError)&&(state2.endedAt??=Date.now(),state2.interval&&(clearInterval(state2.interval),state2.interval=void 0)),!isPartial&&context.durationMs!==void 0)return`Took ${formatToolDuration(context.durationMs)}`;if(state2.startedAt===void 0)return;let endTime=state2.endedAt??Date.now();return`${isPartial?"Elapsed":"Took"} ${formatToolDuration(endTime-state2.startedAt)}`}function invalidArgText(theme2){return theme2.fg("error","[invalid arg]")}function renderToolPath(rawPath,theme2,cwd,options){if(rawPath===null)return invalidArgText(theme2);let value=rawPath||options?.emptyFallback;return value?linkPath(theme2.fg("accent",shortenPath2(value)),value,cwd):theme2.fg("toolOutput","...")}import{unlink as unlink2}from"node:fs/promises";import{closeSync as closeSync2,openSync as openSync2,writeSync as writeSync2}from"node:fs";import{open as open3}from"node:fs/promises";import{randomBytes}from"node:crypto";import{createWriteStream}from"node:fs";import{writeFile}from"node:fs/promises";import{tmpdir as tmpdir2}from"node:os";import{join as join20}from"node:path";var OUTPUT_FILE_MODE=384;function createOutputFilePath(prefix,extension){return join20(tmpdir2(),`${prefix}-${randomBytes(8).toString("hex")}${extension}`)}async function writeOutputFile(prefix,extension,data){let path14=createOutputFilePath(prefix,extension);return await writeFile(path14,data,{mode:OUTPUT_FILE_MODE,flag:"wx"}),path14}function createOutputFileStream(prefix,extension){let path14=createOutputFilePath(prefix,extension);return{path:path14,stream:createWriteStream(path14,{mode:OUTPUT_FILE_MODE,flags:"wx"})}}function byteLength(text2){return Buffer.byteLength(text2,"utf-8")}var OutputAccumulator=class{constructor(options={}){if(this.decoder=new TextDecoder,this.rawChunks=[],this.tailText="",this.tailBytes=0,this.tailStartsAtLineBoundary=!0,this.totalRawBytes=0,this.totalDecodedBytes=0,this.completedLines=0,this.totalLines=0,this.currentLineBytes=0,this.hasOpenLine=!1,this.finished=!1,this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"pi-output",options.persistFromStart){let path14=createOutputFilePath(this.tempFilePrefix,".log");this.tempFileFd=openSync2(path14,"wx",384),this.tempFilePath=path14}}append(data){if(this.finished)throw new Error("Cannot append to a finished output accumulator");if(this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),this.tempFileFd!==void 0){let offset=0;for(;offset<data.length;){let written=writeSync2(this.tempFileFd,data,offset,data.length-offset);if(written===0)throw new Error("Output file write made no progress");offset+=written}}else this.tempFileStream||this.shouldUseTempFile()?(this.ensureTempFile(),this.tempFileStream?.write(data)):data.length>0&&this.rawChunks.push(data)}finish(){this.finished||(this.finished=!0,this.appendDecodedText(this.decoder.decode()),this.shouldUseTempFile()&&this.ensureTempFile())}snapshot(options={}){let maxBytes=Math.min(this.maxBytes,options.maxBytes??this.maxBytes),tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}getTotalBytes(){return this.totalRawBytes}async closeTempFile(){if(this.tempFileFd!==void 0){let fd=this.tempFileFd;this.tempFileFd=void 0,closeSync2(fd)}if(!this.tempFileStream)return;let stream2=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve20,reject)=>{let onError=error=>{stream2.off("finish",onFinish),reject(error)},onFinish=()=>{stream2.off("error",onError),resolve20()};stream2.once("error",onError),stream2.once("finish",onFinish),stream2.end()})}async readFullOutput(maxBytes){if(!this.tempFilePath)return{content:new TextDecoder().decode(Buffer.concat(this.rawChunks)),truncated:!1};let file=await open3(this.tempFilePath,"r");try{let size=(await file.stat()).size;if(size<=maxBytes)return{content:new TextDecoder().decode(await file.readFile()),truncated:!1};let headBytes=Math.floor(maxBytes/2),tailBytes=maxBytes-headBytes,head=Buffer.alloc(headBytes),tail2=Buffer.alloc(tailBytes);await file.read(head,0,headBytes,0),await file.read(tail2,0,tailBytes,size-tailBytes);let headText=new TextDecoder().decode(head,{stream:!0}),tailStart=0;for(;tailStart<tail2.length&&(tail2[tailStart]&192)===128;)tailStart++;let tailText=new TextDecoder().decode(tail2.subarray(tailStart)),omitted=size-headBytes-tailBytes;return{content:`${headText}
|
|
889
|
-
|
|
890
|
-
[... ${omitted} bytes omitted ...]
|
|
891
|
-
|
|
892
|
-
${tailText}`,truncated:!0}}finally{await file.close()}}getLastLineBytes(){return this.currentLineBytes}appendDecodedText(text2){if(text2.length===0)return;let bytes=byteLength(text2);this.totalDecodedBytes+=bytes,this.tailText+=text2,this.tailBytes+=bytes,this.tailBytes>this.maxRollingBytes*2&&this.trimTail();let newlines=0,lastNewline=-1;for(let i=text2.indexOf(`
|
|
893
|
-
`);i!==-1;i=text2.indexOf(`
|
|
894
|
-
`,i+1))newlines++,lastNewline=i;if(newlines===0)this.currentLineBytes+=bytes,this.hasOpenLine=!0;else{this.completedLines+=newlines;let tail2=text2.slice(lastNewline+1);this.currentLineBytes=byteLength(tail2),this.hasOpenLine=tail2.length>0}this.totalLines=this.completedLines+(this.hasOpenLine?1:0)}trimTail(){let buffer=Buffer.from(this.tailText,"utf-8");if(buffer.length<=this.maxRollingBytes){this.tailBytes=buffer.length;return}let start=buffer.length-this.maxRollingBytes;for(;start<buffer.length&&(buffer[start]&192)===128;)start++;this.tailStartsAtLineBoundary=start===0?this.tailStartsAtLineBoundary:buffer[start-1]===10,this.tailText=buffer.subarray(start).toString("utf-8"),this.tailBytes=byteLength(this.tailText)}getSnapshotText(){if(this.tailStartsAtLineBoundary)return this.tailText;let firstNewline=this.tailText.indexOf(`
|
|
895
|
-
`);return firstNewline===-1?this.tailText:this.tailText.slice(firstNewline+1)}shouldUseTempFile(){return this.totalRawBytes>this.maxBytes||this.totalDecodedBytes>this.maxBytes||this.totalLines>this.maxLines}ensureTempFile(){if(this.tempFilePath)return;let{path:path14,stream:stream2}=createOutputFileStream(this.tempFilePrefix,".log");this.tempFilePath=path14,this.tempFileStream=stream2;for(let chunk of this.rawChunks)this.tempFileStream.write(chunk);this.rawChunks=[]}};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)]}},shellTimerHooked=Symbol("shellTimerHooked");function ensureShellTimer(context){startToolTimer(context);let state2=context.state;if(state2[shellTimerHooked])return;state2[shellTimerHooked]=!0;let previousDispose=state2.dispose;state2.dispose=()=>{try{previousDispose?.call(state2)}finally{clearInterval(state2.interval),state2.interval=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(`
|
|
896
|
-
`)}function formatFullShellCall(command,timeout,config){let commandDisplay=command===null?invalidArgText(theme):command?styleShellCommand(command,config):theme.fg("toolOutput","...");return formatShellPrompt(config.prompt)+commandDisplay+formatShellTimeout(timeout)}function fitCollapsedShellCall(body2,timeout,width,suffix,config){let prompt=formatShellPrompt(config.prompt),timeoutSuffix=formatShellTimeout(timeout),bodyWidth=Math.max(0,width-visibleWidth(prompt)-visibleWidth(suffix)-visibleWidth(timeoutSuffix)),fittedBody=truncateToWidth(body2,bodyWidth,"");return truncateToWidth(prompt+fittedBody+suffix+timeoutSuffix,width,"\u2026")}function formatTruncatedShellCall(command,timeout,width,config){if(command===null)return truncateToWidth(formatFullShellCall(command,timeout,config),width,"\u2026");if(!command)return formatFullShellCall(command,timeout,config);let physicalLines=command.split(/\r?\n/).filter(line=>line.trim()),firstNonEmptyLine=physicalLines[0]?.trim()??command.trim(),hiddenLines=Math.max(0,physicalLines.length-1),suffix=hiddenLines>0?theme.fg("muted",` (+${hiddenLines} line${hiddenLines===1?"":"s"})`):theme.fg("muted"," \u2026");return fitCollapsedShellCall(styleShellCommand(firstNonEmptyLine,config),timeout,width,suffix,config)}function rebuildBashResultRenderComponent(component,result2,options,showImages,timerText,submittedAsBackground){component.clear();let background=result2.details?.background,output=background?.kind==="background"?`${submittedAsBackground?"Running in the background":"Moved to background"} \xB7 ${background.taskId}`:getTextOutput(result2,showImages).trim(),truncation=result2.details?.truncation,fullOutputPath=result2.details?.fullOutputPath;if(!options.isPartial&&truncation?.truncated&&fullOutputPath&&output.endsWith("]")){let footerStart=output.lastIndexOf(`
|
|
897
|
-
|
|
898
|
-
[`);footerStart!==-1&&output.slice(footerStart).includes(fullOutputPath)&&(output=output.slice(0,footerStart).trimEnd())}if(output){let styledOutput=output.split(`
|
|
899
|
-
`).map(line=>theme.fg("toolOutput",line)).join(`
|
|
900
|
-
`);options.expanded?component.addChild(new Text(`
|
|
901
|
-
${styledOutput}`,0,0)):(component.addChild(new Spacer(1)),component.addChild(new VisualLinePreview({text:styledOutput,maxVisualLines:BASH_PREVIEW_LINES,keep:"end",formatHint:hidden=>theme.fg("muted",`... (${hidden} earlier lines,`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`})))}if(truncation?.truncated||fullOutputPath){let warnings=[];fullOutputPath&&warnings.push(`Full output: ${fullOutputPath}`),truncation?.truncated&&(truncation.truncatedBy==="lines"?warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`):warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes??51200)} limit)`)),component.addChild(new Text(`
|
|
902
|
-
${theme.fg("warning",`[${warnings.join(". ")}]`)}`,0,0))}timerText&&component.addChild(new Text(`
|
|
903
|
-
${theme.fg("muted",timerText)}`,0,0))}function createShellRenderers(config){return{renderCall(args,_theme,context){ensureShellTimer(context);let component=context.lastComponent??new BashCallRenderComponent(config);return component.update(args,context.expanded),component},renderResult(result2,options,_theme,context){ensureShellTimer(context);let timerText=toolTimerText(context,options.isPartial),component=context.lastComponent??new Container,submitted=context.args?.background===!0;return rebuildBashResultRenderComponent(component,result2,options,context.showImages,timerText,submitted),component.invalidate(),component}}}var CMD_NUL_REDIRECT_REGEX=/(\d?&?>+\s*)[Nn][Uu][Ll](?=\s|$|[|&;)\n])/g;function rewriteCmdNulRedirects(command){return command.replace(CMD_NUL_REDIRECT_REGEX,"$1/dev/null")}var MAX_BACKGROUND_OUTPUT_BYTES=20*1024*1024;function shellFailure(error){return error instanceof Error&&error.message==="aborted"?{status:"cancelled",error:"Command aborted"}:error instanceof Error&&error.message.startsWith("timeout:")?{status:"timeout",error:`Command timed out after ${error.message.split(":")[1]} seconds`}:{status:"failed",error:boundText(error instanceof Error?error.message:String(error),4096)}}function formatOutput(output,snapshot,managed,emptyText){let truncation=snapshot.truncation,text2=snapshot.content||emptyText,details=managed?{fullOutputPath:snapshot.fullOutputPath}:void 0;if(truncation.truncated){details={truncation,fullOutputPath:snapshot.fullOutputPath};let startLine=truncation.totalLines-truncation.outputLines+1,endLine=truncation.totalLines;if(truncation.lastLinePartial){let lastLineSize=formatSize(output.getLastLineBytes());text2+=`
|
|
904
|
-
|
|
905
|
-
[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`}else truncation.truncatedBy==="lines"?text2+=`
|
|
906
|
-
|
|
907
|
-
[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`:text2+=`
|
|
908
|
-
|
|
909
|
-
[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(truncation.maxBytes)} limit). Full output: ${snapshot.fullOutputPath}]`}return{text:text2,details}}async function runShellCommand(options){let{operations,context,managed,signal,timeout}=options,output=new OutputAccumulator({tempFilePrefix:options.tempFilePrefix,persistFromStart:!!managed}),startedAt=performance.now(),outputError,acceptingOutput=!0,unsubscribe,updateTimer,updateDirty=!1,lastUpdateAt=0,failOutput=error=>{if(!outputError){outputError=error instanceof Error?error:new Error(String(error));try{managed&&managed.control.requestCancel()}catch{}}},checkOutputLimit=()=>{managed?.control.mode==="background"&&output.getTotalBytes()>MAX_BACKGROUND_OUTPUT_BYTES&&failOutput(new Error("Background command exceeded the 20 MiB output limit"))},snapshot=()=>output.snapshot({persistIfTruncated:!0,maxBytes:managed?.control.mode==="background"?40*1024:void 0}),publish=snapshot2=>{let result2={content:snapshot2?[{type:"text",text:snapshot2.content}]:[],details:snapshot2?{truncation:snapshot2.truncation.truncated?snapshot2.truncation:void 0,fullOutputPath:snapshot2.fullOutputPath}:void 0};managed?managed.control.publish(result2):options.onUpdate?.(result2)},emitOutputUpdate=()=>{!managed&&!options.onUpdate||!updateDirty||(updateDirty=!1,lastUpdateAt=Date.now(),publish(snapshot()))},clearUpdateTimer=()=>{updateTimer&&clearTimeout(updateTimer),updateTimer=void 0},scheduleOutputUpdate=()=>{if(!managed&&!options.onUpdate)return;updateDirty=!0;let delay2=BASH_UPDATE_THROTTLE_MS-(Date.now()-lastUpdateAt);delay2<=0?(clearUpdateTimer(),emitOutputUpdate()):updateTimer??=setTimeout(()=>{updateTimer=void 0,emitOutputUpdate()},delay2)},handleData=data=>{if(!(!acceptingOutput||outputError))try{if(managed?.control.mode==="background"&&output.getTotalBytes()+data.length>MAX_BACKGROUND_OUTPUT_BYTES){let remaining=Math.max(0,MAX_BACKGROUND_OUTPUT_BYTES-output.getTotalBytes());output.append(data.subarray(0,remaining)),failOutput(new Error("Background command exceeded the 20 MiB output limit"))}else output.append(data);scheduleOutputUpdate()}catch(error){if(!managed)throw error;failOutput(error)}};try{if(managed){let path14=output.snapshot().fullOutputPath,cleanup=async()=>{await output.closeTempFile(),await unlink2(path14).catch(error=>{if(error.code!=="ENOENT")throw error})};try{managed.control.setOutputPath(path14,cleanup)}catch(error){throw await cleanup(),error}unsubscribe=managed.control.onModeChange(checkOutputLimit)}publish();let failure,exitCode;try{if(signal?.aborted)throw new Error("aborted");let execution=operations.exec(context.command,context.cwd,{onData:handleData,signal,timeout,env:context.env});managed?.control.accept(),{exitCode}=await execution,exitCode===null?failure={status:"failed",error:"Command terminated without an exit code"}:exitCode!==0&&(failure={status:"failed",error:`Command exited with code ${exitCode}`})}catch(error){failure=shellFailure(error)}acceptingOutput=!1,output.finish(),clearUpdateTimer(),managed?publish(snapshot()):emitOutputUpdate();let final=snapshot();await output.closeTempFile(),outputError&&(failure={status:"failed",error:boundText(outputError.message,4096)});let{text:text2,details}=formatOutput(output,final,!!managed,failure?"":"(no output)"),fullOutput=typeof exitCode=="number"&&!outputError?await output.readFullOutput(1024*1024):void 0;return{status:failure?.status,error:failure?.error,...exitCode!==void 0?{exitCode}:{},result:{...fullOutput&&typeof exitCode=="number"?{structuredContent:{output:fullOutput.content,truncated:fullOutput.truncated,...fullOutput.truncated&&final.fullOutputPath?{full_output_path:final.fullOutputPath}:{},exit_code:exitCode,wall_time_seconds:Math.round((performance.now()-startedAt)/100)/10},...failure?{isError:!0}:{}}:{},content:[{type:"text",text:failure?`${text2?`${text2}
|
|
910
|
-
|
|
911
|
-
`:""}${failure.error}`:text2}],details}}}finally{acceptingOutput=!1,unsubscribe?.(),clearUpdateTimer(),await output.closeTempFile()}}import{constants as constants3}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";var MAX_TIMEOUT_MS=2147483647,MAX_TIMEOUT_SECONDS=MAX_TIMEOUT_MS/1e3;function resolveTimeoutMs(timeout){if(timeout===void 0)return;if(!Number.isFinite(timeout)||timeout<=0)throw new Error("Invalid timeout: must be a finite number of seconds");let timeoutMs=timeout*1e3;if(timeoutMs>MAX_TIMEOUT_MS)throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);return timeoutMs}var bashSchema=typebox_exports.Object({command:typebox_exports.String({description:"Shell command to execute"}),timeout:typebox_exports.Optional(typebox_exports.Number({description:"Timeout in seconds (optional, no default timeout)"})),background:typebox_exports.Optional(typebox_exports.Boolean({description:"true returns a managed task ID immediately and runs the command in the background, and you are notified when it completes \u2014 do not poll for its result; omit or false to block until exit"}))}),bashToolSystemPromptContribution={snippet:"Execute bash commands, foreground or background",guidelines:["You can inspect PI_* environment variables for current model and session details."]},bashOutputSchema=typebox_exports.Union([typebox_exports.Object({output:typebox_exports.String({description:"Combined stdout and stderr, up to 1 MiB, keeping head and tail when truncated."}),truncated:typebox_exports.Boolean(),full_output_path:typebox_exports.Optional(typebox_exports.String()),exit_code:typebox_exports.Number(),wall_time_seconds:typebox_exports.Number()}),typebox_exports.Object({task_id:typebox_exports.String(),status:typebox_exports.String()})]);function createLocalShellOperations(shellName,resolveShellConfig,normalizeCommand=command=>command){return{exec:async(command,cwd,{onData,signal,timeout,env:env2})=>{let timeoutMs=resolveTimeoutMs(timeout);if(signal?.aborted)throw new Error("aborted");let shellConfig=resolveShellConfig();try{await fsAccess(cwd,constants3.F_OK)}catch{throw new Error(`Working directory does not exist: ${cwd}
|
|
912
|
-
Cannot execute ${shellName} commands.`)}if(signal?.aborted)throw new Error("aborted");let commandFromStdin=shellConfig.commandTransport==="stdin",normalizedCommand=normalizeCommand(command),child=spawn4(shellConfig.shell,commandFromStdin?shellConfig.args:[...shellConfig.args,normalizedCommand],{cwd,detached:process.platform!=="win32",env:env2??getShellEnv(),stdio:[commandFromStdin?"pipe":"ignore","pipe","pipe"],windowsHide:!0});commandFromStdin&&(child.stdin?.on("error",()=>{}),child.stdin?.end(normalizedCommand)),child.pid&&trackDetachedChildPid(child.pid);let timedOut=!1,timeoutHandle,onAbort=()=>{child.pid&&killProcessTree(child.pid)};try{timeoutMs!==void 0&&(timeoutHandle=setTimeout(()=>{timedOut=!0,child.pid&&killProcessTree(child.pid)},timeoutMs)),child.stdout?.on("data",onData),child.stderr?.on("data",onData),signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));let exitCode=await waitForChildProcess(child);if(signal?.aborted)throw new Error("aborted");if(timedOut)throw new Error(`timeout:${timeout}`);let signalCode=child.signalCode;return{exitCode:exitCode??(signalCode?128+(osConstants.signals[signalCode]??0):1)}}finally{child.pid&&untrackDetachedChildPid(child.pid),timeoutHandle&&clearTimeout(timeoutHandle),signal&&signal.removeEventListener("abort",onAbort)}}}}function resolveSpawnContext(command,cwd,spawnHook,exposeSessionEnvironment,ctx){let env2={...getShellEnv()};if(delete env2.PI_SESSION_ID,delete env2.PI_SESSION_FILE,delete env2.PI_PROVIDER,delete env2.PI_MODEL,delete env2.PI_REASONING_LEVEL,exposeSessionEnvironment&&ctx){let model=ctx.model;env2.PI_SESSION_ID=ctx.sessionManager.getSessionId();let sessionFile=ctx.sessionManager.getSessionFile();sessionFile&&(env2.PI_SESSION_FILE=sessionFile),model&&(env2.PI_PROVIDER=model.provider,env2.PI_MODEL=model.id),ctx.thinkingLevel&&(env2.PI_REASONING_LEVEL=ctx.thinkingLevel)}let baseContext={command,cwd,env:env2};return spawnHook?spawnHook(baseContext):baseContext}function shellToolResult(completion,managed){let status=completion.status;if(completion.result.structuredContent)return completion.result;if(status==="failed"||status==="timeout"||status==="cancelled"){let text2=completion.result.content.filter(part=>part.type==="text").map(part=>part.text).join(`
|
|
913
|
-
`),message=completion.error?text2||completion.error:`${text2?`${text2}
|
|
914
|
-
|
|
915
|
-
`:""}Command ${status}`;throw managed?new TaskExecutionError(message,status):new Error(message)}return completion.result}function createShellToolDefinition(cwd,config,options){let ops=options.operations,commandPrefix=options?.commandPrefix,exposeSessionEnvironment=options?.exposeSessionEnvironment??!0,spawnHook=options?.spawnHook;return{name:config.name,label:config.label,description:`Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${2e3} lines or ${51200/1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits \u2014 use it when your next step needs the output; background: true returns immediately with a task ID \u2014 use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use tasks read to inspect output, tasks wait with an ID for one task or without one for any running task, and tasks kill to stop it. Steering interrupts only a wait, never execution. Background output is limited to 20 MiB; an expired tasks wait window never stops the command.`,promptSnippet:config.promptSnippet,promptGuidelines:exposeSessionEnvironment&&config.promptGuidelines?[...config.promptGuidelines]:void 0,parameters:bashSchema,outputSchema:bashOutputSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(toolCallId,{command,timeout,background},parentSignal,originalUpdate,ctx){let host=ctx?.tasks;if(host?.closed)throw new Error("Task service is closed");let run=async managed=>{let signal=managed?.control.signal??parentSignal;try{if(managed){if(signal?.aborted)throw new Error("Command aborted");resolveTimeoutMs(timeout)}let resolvedCommand=commandPrefix?`${commandPrefix}
|
|
916
|
-
${command}`:command,spawnContext=resolveSpawnContext(resolvedCommand,ctx?.cwd||cwd,spawnHook,exposeSessionEnvironment,ctx);return await runShellCommand({operations:ops,context:spawnContext,tempFilePrefix:config.tempFilePrefix,timeout,signal,onUpdate:originalUpdate,managed})}catch(error){throw managed?new TaskExecutionError(error instanceof Error?error.message:String(error),managed.control.signal.aborted?"cancelled":"failed"):error}};if(!host){if(background)throw new Error("Background execution is not available in this host. No command was started.");return shellToolResult(await run(),!1)}let outcome=await host.execute({kind:config.name,title:command,toolCallId,command,cwd:ctx?.cwd||cwd,background,signal:parentSignal,onUpdate:originalUpdate,run:control=>run({control})});if(outcome.kind==="result")return shellToolResult(outcome,!0);let tail2=`Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. 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 tasks read to inspect output, tasks wait only when your next step is blocked on a result (one ID or any running task; prefer foreground next time in that case), or tasks kill to stop it.`,handoff=background===!0?`Command handed to background. ${tail2}`:`Command moved to the background while it was running, by the user. The execution continues unchanged \u2014 no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so tasks read now returns partial output, not a fresh start. ${tail2}`;return{structuredContent:{task_id:outcome.task.id,status:outcome.task.status},content:[{type:"text",text:`${handoff}${outcome.task.outputPath?`
|
|
917
|
-
Full output: ${outcome.task.outputPath}`:""}`}],details:{background:{kind:"background",taskId:outcome.task.id},fullOutputPath:outcome.task.outputPath}}},...createShellRenderers(config)}}function normalizeLocalBashCommand(command,platform3=process.platform){return platform3==="win32"?rewriteCmdNulRedirects(command):command}function createLocalBashOperations(options){return createLocalShellOperations("bash",()=>getShellConfig(options?.shellPath),normalizeLocalBashCommand)}var bashToolConfig={name:"bash",label:"bash",shellName:"bash",prompt:"$",promptSnippet:bashToolSystemPromptContribution.snippet,promptGuidelines:bashToolSystemPromptContribution.guidelines,tempFilePrefix:"pi-bash"};function createBashToolDefinition(cwd,options){return createShellToolDefinition(cwd,bashToolConfig,{...options,operations:options?.operations??createLocalBashOperations({shellPath:options?.shellPath})})}function createBashTool(cwd,options){let definition=createBashToolDefinition(cwd,options),tool=wrapToolDefinition(definition);return Object.assign(tool,{promptSnippet:definition.promptSnippet,promptGuidelines:definition.promptGuidelines}),tool}var Diff2=class{diff(oldStr,newStr,options={}){let callback;typeof options=="function"?(callback=options,options={}):"callback"in options&&(callback=options.callback);let oldString=this.castInput(oldStr,options),newString=this.castInput(newStr,options),oldTokens=this.removeEmpty(this.tokenize(oldString,options)),newTokens=this.removeEmpty(this.tokenize(newString,options));return this.diffWithOptionsObj(oldTokens,newTokens,options,callback)}diffWithOptionsObj(oldTokens,newTokens,options,callback){var _a2;let done=value=>{if(value=this.postProcess(value,options),callback){setTimeout(function(){callback(value)},0);return}else return value},newLen=newTokens.length,oldLen=oldTokens.length,editLength=1,maxEditLength=newLen+oldLen;options.maxEditLength!=null&&(maxEditLength=Math.min(maxEditLength,options.maxEditLength));let maxExecutionTime=(_a2=options.timeout)!==null&&_a2!==void 0?_a2:1/0,abortAfterTimestamp=Date.now()+maxExecutionTime,bestPath=[{oldPos:-1,lastComponent:void 0}],newPos=this.extractCommon(bestPath[0],newTokens,oldTokens,0,options);if(bestPath[0].oldPos+1>=oldLen&&newPos+1>=newLen)return done(this.buildValues(bestPath[0].lastComponent,newTokens,oldTokens));let minDiagonalToConsider=-1/0,maxDiagonalToConsider=1/0,execEditLength=()=>{for(let diagonalPath=Math.max(minDiagonalToConsider,-editLength);diagonalPath<=Math.min(maxDiagonalToConsider,editLength);diagonalPath+=2){let basePath,removePath=bestPath[diagonalPath-1],addPath=bestPath[diagonalPath+1];removePath&&(bestPath[diagonalPath-1]=void 0);let canAdd=!1;if(addPath){let addPathNewPos=addPath.oldPos-diagonalPath;canAdd=addPath&&0<=addPathNewPos&&addPathNewPos<newLen}let canRemove=removePath&&removePath.oldPos+1<oldLen;if(!canAdd&&!canRemove){bestPath[diagonalPath]=void 0;continue}if(!canRemove||canAdd&&removePath.oldPos<addPath.oldPos?basePath=this.addToPath(addPath,!0,!1,0,options):basePath=this.addToPath(removePath,!1,!0,1,options),newPos=this.extractCommon(basePath,newTokens,oldTokens,diagonalPath,options),basePath.oldPos+1>=oldLen&&newPos+1>=newLen)return done(this.buildValues(basePath.lastComponent,newTokens,oldTokens))||!0;bestPath[diagonalPath]=basePath,basePath.oldPos+1>=oldLen&&(maxDiagonalToConsider=Math.min(maxDiagonalToConsider,diagonalPath-1)),newPos+1>=newLen&&(minDiagonalToConsider=Math.max(minDiagonalToConsider,diagonalPath+1))}editLength++};if(callback)(function exec(){setTimeout(function(){if(editLength>maxEditLength||Date.now()>abortAfterTimestamp)return callback(void 0);execEditLength()||exec()},0)})();else for(;editLength<=maxEditLength&&Date.now()<=abortAfterTimestamp;){let ret=execEditLength();if(ret)return ret}}addToPath(path14,added,removed,oldPosInc,options){let last=path14.lastComponent;return last&&!options.oneChangePerToken&&last.added===added&&last.removed===removed?{oldPos:path14.oldPos+oldPosInc,lastComponent:{count:last.count+1,added,removed,previousComponent:last.previousComponent}}:{oldPos:path14.oldPos+oldPosInc,lastComponent:{count:1,added,removed,previousComponent:last}}}extractCommon(basePath,newTokens,oldTokens,diagonalPath,options){let newLen=newTokens.length,oldLen=oldTokens.length,oldPos=basePath.oldPos,newPos=oldPos-diagonalPath,commonCount=0;for(;newPos+1<newLen&&oldPos+1<oldLen&&this.equals(oldTokens[oldPos+1],newTokens[newPos+1],options);)newPos++,oldPos++,commonCount++,options.oneChangePerToken&&(basePath.lastComponent={count:1,previousComponent:basePath.lastComponent,added:!1,removed:!1});return commonCount&&!options.oneChangePerToken&&(basePath.lastComponent={count:commonCount,previousComponent:basePath.lastComponent,added:!1,removed:!1}),basePath.oldPos=oldPos,newPos}equals(left,right,options){return options.comparator?options.comparator(left,right):left===right||!!options.ignoreCase&&left.toLowerCase()===right.toLowerCase()}removeEmpty(array){let ret=[];for(let i=0;i<array.length;i++)array[i]&&ret.push(array[i]);return ret}castInput(value,options){return value}tokenize(value,options){return Array.from(value)}join(chars){return chars.join("")}postProcess(changeObjects,options){return changeObjects}get useLongestToken(){return!1}buildValues(lastComponent,newTokens,oldTokens){let components=[],nextComponent;for(;lastComponent;)components.push(lastComponent),nextComponent=lastComponent.previousComponent,delete lastComponent.previousComponent,lastComponent=nextComponent;components.reverse();let componentLen=components.length,componentPos=0,newPos=0,oldPos=0;for(;componentPos<componentLen;componentPos++){let component=components[componentPos];if(component.removed)component.value=this.join(oldTokens.slice(oldPos,oldPos+component.count)),oldPos+=component.count;else{if(!component.added&&this.useLongestToken){let value=newTokens.slice(newPos,newPos+component.count);value=value.map(function(value2,i){let oldValue=oldTokens[oldPos+i];return oldValue.length>value2.length?oldValue:value2}),component.value=this.join(value)}else component.value=this.join(newTokens.slice(newPos,newPos+component.count));newPos+=component.count,component.added||(oldPos+=component.count)}}return components}};function longestCommonPrefix(str1,str2){let i;for(i=0;i<str1.length&&i<str2.length;i++)if(str1[i]!=str2[i])return str1.slice(0,i);return str1.slice(0,i)}function longestCommonSuffix(str1,str2){let i;if(!str1||!str2||str1[str1.length-1]!=str2[str2.length-1])return"";for(i=0;i<str1.length&&i<str2.length;i++)if(str1[str1.length-(i+1)]!=str2[str2.length-(i+1)])return str1.slice(-i);return str1.slice(-i)}function replacePrefix(string2,oldPrefix,newPrefix){if(string2.slice(0,oldPrefix.length)!=oldPrefix)throw Error(`string ${JSON.stringify(string2)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);return newPrefix+string2.slice(oldPrefix.length)}function replaceSuffix(string2,oldSuffix,newSuffix){if(!oldSuffix)return string2+newSuffix;if(string2.slice(-oldSuffix.length)!=oldSuffix)throw Error(`string ${JSON.stringify(string2)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);return string2.slice(0,-oldSuffix.length)+newSuffix}function removePrefix(string2,oldPrefix){return replacePrefix(string2,oldPrefix,"")}function removeSuffix(string2,oldSuffix){return replaceSuffix(string2,oldSuffix,"")}function maximumOverlap(string1,string2){return string2.slice(0,overlapCount(string1,string2))}function overlapCount(a,b2){let startA=0;a.length>b2.length&&(startA=a.length-b2.length);let endB=b2.length;a.length<b2.length&&(endB=a.length);let map=Array(endB),k2=0;map[0]=0;for(let j2=1;j2<endB;j2++){for(b2[j2]==b2[k2]?map[j2]=map[k2]:map[j2]=k2;k2>0&&b2[j2]!=b2[k2];)k2=map[k2];b2[j2]==b2[k2]&&k2++}k2=0;for(let i=startA;i<a.length;i++){for(;k2>0&&a[i]!=b2[k2];)k2=map[k2];a[i]==b2[k2]&&k2++}return k2}function segment(string2,segmenter5){let parts=[];for(let segmentObj of Array.from(segmenter5.segment(string2))){let segment2=segmentObj.segment;parts.length&&/\s/.test(parts[parts.length-1])&&/\s/.test(segment2)?parts[parts.length-1]+=segment2:parts.push(segment2)}return parts}function trailingWs(string2,segmenter5){if(segmenter5)return leadingAndTrailingWs(string2,segmenter5)[1];let i;for(i=string2.length-1;i>=0&&string2[i].match(/\s/);i--);return string2.substring(i+1)}function leadingWs(string2,segmenter5){if(segmenter5)return leadingAndTrailingWs(string2,segmenter5)[0];let match2=string2.match(/^\s*/);return match2?match2[0]:""}function leadingAndTrailingWs(string2,segmenter5){if(!segmenter5)return[leadingWs(string2),trailingWs(string2)];if(segmenter5.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');let segments=segment(string2,segmenter5),firstSeg=segments[0],lastSeg=segments[segments.length-1],head=/\s/.test(firstSeg)?firstSeg:"",tail2=/\s/.test(lastSeg)?lastSeg:"";return[head,tail2]}var extendedWordChars="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}",tokenizeIncludingWhitespace=new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`,"ug"),WordDiff=class extends Diff2{equals(left,right,options){return options.ignoreCase&&(left=left.toLowerCase(),right=right.toLowerCase()),left.trim()===right.trim()}tokenize(value,options={}){let parts;if(options.intlSegmenter){let segmenter5=options.intlSegmenter;if(segmenter5.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');parts=segment(value,segmenter5)}else parts=value.match(tokenizeIncludingWhitespace)||[];let tokens2=[],prevPart=null;return parts.forEach(part=>{/\s/.test(part)?prevPart==null?tokens2.push(part):tokens2.push(tokens2.pop()+part):prevPart!=null&&/\s/.test(prevPart)?tokens2[tokens2.length-1]==prevPart?tokens2.push(tokens2.pop()+part):tokens2.push(prevPart+part):tokens2.push(part),prevPart=part}),tokens2}join(tokens2){return tokens2.map((token,i)=>i==0?token:token.replace(/^\s+/,"")).join("")}postProcess(changes,options){if(!changes||options.oneChangePerToken)return changes;let lastKeep=null,insertion=null,deletion=null;return changes.forEach(change=>{change.added?insertion=change:change.removed?deletion=change:((insertion||deletion)&&dedupeWhitespaceInChangeObjects(lastKeep,deletion,insertion,change,options.intlSegmenter),lastKeep=change,insertion=null,deletion=null)}),(insertion||deletion)&&dedupeWhitespaceInChangeObjects(lastKeep,deletion,insertion,null,options.intlSegmenter),changes}},wordDiff=new WordDiff;function diffWords(oldStr,newStr,options){return options?.ignoreWhitespace!=null&&!options.ignoreWhitespace?diffWordsWithSpace(oldStr,newStr,options):wordDiff.diff(oldStr,newStr,options)}function dedupeWhitespaceInChangeObjects(startKeep,deletion,insertion,endKeep,segmenter5){if(deletion&&insertion){let[oldWsPrefix,oldWsSuffix]=leadingAndTrailingWs(deletion.value,segmenter5),[newWsPrefix,newWsSuffix]=leadingAndTrailingWs(insertion.value,segmenter5);if(startKeep){let commonWsPrefix=longestCommonPrefix(oldWsPrefix,newWsPrefix);startKeep.value=replaceSuffix(startKeep.value,newWsPrefix,commonWsPrefix),deletion.value=removePrefix(deletion.value,commonWsPrefix),insertion.value=removePrefix(insertion.value,commonWsPrefix)}if(endKeep){let commonWsSuffix=longestCommonSuffix(oldWsSuffix,newWsSuffix);endKeep.value=replacePrefix(endKeep.value,newWsSuffix,commonWsSuffix),deletion.value=removeSuffix(deletion.value,commonWsSuffix),insertion.value=removeSuffix(insertion.value,commonWsSuffix)}}else if(insertion){if(startKeep){let ws=leadingWs(insertion.value,segmenter5);insertion.value=insertion.value.substring(ws.length)}if(endKeep){let ws=leadingWs(endKeep.value,segmenter5);endKeep.value=endKeep.value.substring(ws.length)}}else if(startKeep&&endKeep){let newWsFull=leadingWs(endKeep.value,segmenter5),[delWsStart,delWsEnd]=leadingAndTrailingWs(deletion.value,segmenter5),newWsStart=longestCommonPrefix(newWsFull,delWsStart);deletion.value=removePrefix(deletion.value,newWsStart);let newWsEnd=longestCommonSuffix(removePrefix(newWsFull,newWsStart),delWsEnd);deletion.value=removeSuffix(deletion.value,newWsEnd),endKeep.value=replacePrefix(endKeep.value,newWsFull,newWsEnd),startKeep.value=replaceSuffix(startKeep.value,newWsFull,newWsFull.slice(0,newWsFull.length-newWsEnd.length))}else if(endKeep){let endKeepWsPrefix=leadingWs(endKeep.value,segmenter5),deletionWsSuffix=trailingWs(deletion.value,segmenter5),overlap=maximumOverlap(deletionWsSuffix,endKeepWsPrefix);deletion.value=removeSuffix(deletion.value,overlap)}else if(startKeep){let startKeepWsSuffix=trailingWs(startKeep.value,segmenter5),deletionWsPrefix=leadingWs(deletion.value,segmenter5),overlap=maximumOverlap(startKeepWsSuffix,deletionWsPrefix);deletion.value=removePrefix(deletion.value,overlap)}}var WordsWithSpaceDiff=class extends Diff2{tokenize(value){let regex=new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`,"ug");return value.match(regex)||[]}},wordsWithSpaceDiff=new WordsWithSpaceDiff;function diffWordsWithSpace(oldStr,newStr,options){return wordsWithSpaceDiff.diff(oldStr,newStr,options)}var LineDiff=class extends Diff2{constructor(){super(...arguments),this.tokenize=tokenize}equals(left,right,options){return options.ignoreWhitespace?((!options.newlineIsToken||!left.includes(`
|
|
881
|
+
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire5(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-QX6D3D7X.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"),piAiModelsEntry=resolveImport("@earendil-works/pi-ai/models"),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/models":piAiModelsEntry,"@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/models":piAiModelsEntry,"@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,assertActive=()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,setSessionName:notInitialized,getSessionName:notInitialized,setLabel:notInitialized,getActiveTools:notInitialized,getAllTools:notInitialized,getSettings:notInitialized,setActiveTools:notInitialized,refreshTools:()=>{},getCommands:notInitialized,setModel:()=>Promise.reject(new Error("Extension runtime not initialized")),getThinkingLevel:notInitialized,setThinkingLevel:notInitialized,flagValues:new Map,pendingProviderRegistrations:[],pendingNativeProviderRegistrations:[],mcpServers:new McpServerRegistry,pendingVirtualModelRegistrations:[],createContext:notInitialized,assertActive,invalidate:message=>{if(!state2.staleMessage){state2.staleMessage=message??"This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().";for(let unsubscribe of eventBusUnsubscribers)unsubscribe();eventBusUnsubscribers.clear()}},trackEventBusSubscription:unsubscribe=>{let active=!0,trackedUnsubscribe=()=>{active&&(active=!1,eventBusUnsubscribers.delete(trackedUnsubscribe),unsubscribe())};return eventBusUnsubscribers.add(trackedUnsubscribe),trackedUnsubscribe},registerProvider:(name,config,extensionPath="<unknown>")=>{runtime.pendingProviderRegistrations.push({name,config,extensionPath})},registerNativeProvider:(provider,extensionPath="<unknown>")=>{runtime.pendingNativeProviderRegistrations.push({provider,extensionPath})},unregisterProvider:name=>{runtime.pendingProviderRegistrations=runtime.pendingProviderRegistrations.filter(r=>r.name!==name),runtime.pendingNativeProviderRegistrations=runtime.pendingNativeProviderRegistrations.filter(r=>r.provider.id!==name)},registerVirtualModel:(definition,extensionPath="<unknown>")=>{runtime.pendingVirtualModelRegistrations.push({definition,extensionPath})},unregisterVirtualModel:(provider,id)=>{runtime.pendingVirtualModelRegistrations=runtime.pendingVirtualModelRegistrations.filter(({definition})=>definition.provider!==provider||definition.id!==id)}};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){if(assertActive(),typeof name!="string"||name.length===0)throw new Error(`Command registered by extension "${extension.path}" must have a non-empty string name. Use pi.registerCommand("name", { description, handler }).`);if(typeof options?.handler!="function")throw new Error(`Command "/${name}" registered by extension "${extension.path}" must define handler().`);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)},registerToolRenderer(resolver){assertActive(),extension.toolRenderers??=[],extension.toolRenderers.push(resolver)},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()},getSettings(){return assertActive(),runtime.getSettings()},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))},registerMcpServer(name,config){assertActive();let validated=validateMcpServerConfig(name,config);if(typeof validated=="string")throw new Error(`Invalid MCP server registered by extension "${extension.path}": ${validated}`);let owner=runtime.mcpServers.get(name)?.extensionPath;if(owner!==void 0&&owner!==extension.path)throw new Error(`MCP server "${name}" is already registered by extension "${owner}"`);let clash=runtime.mcpServers.list().find(server2=>server2.name!==name&&mcpNamespace(server2.name)===mcpNamespace(name));if(clash)throw new Error(`MCP server "${name}" conflicts with registered server "${clash.name}"`);let server={name,config:structuredClone(validated),extensionPath:extension.path};applyRuntimeChange(()=>runtime.mcpServers.register(server))},unregisterMcpServer(name){assertActive(),applyRuntimeChange(()=>runtime.mcpServers.unregister(name,extension.path))},getMcpServers(){return assertActive(),runtime.mcpServers.list()},registerVirtualModel(model){assertActive();let definition={...model,route:request=>model.route(request,runtime.createContext())};applyRuntimeChange(()=>runtime.registerVirtualModel(definition,extension.path))},unregisterVirtualModel(provider,id){assertActive(),applyRuntimeChange(()=>runtime.unregisterVirtualModel(provider,id))},events:{emit(channel,data){assertActive(),eventBus.emit(channel,data)},on(channel,handler){assertActive();let unsubscribe=runtime.trackEventBusSubscription(eventBus.on(channel,handler));return state2==="loading"&&loadingUnsubscribers.push(unsubscribe),unsubscribe}}},commit:()=>{if(state2==="loading"){runtime.assertActive();for(let[name,value]of pendingFlagValues)runtime.flagValues.has(name)||runtime.flagValues.set(name,value);for(let apply of pendingRuntimeChanges)apply();state2="active",clearPending()}},discard:()=>{if(state2==="loading"){state2="failed";for(let unsubscribe of loadingUnsubscribers)unsubscribe();clearPending()}}}}function isCurrentCacheToken(cacheToken){return cacheToken!==void 0&&extensionCacheCwd===cacheToken.cwd&&extensionCacheGeneration===cacheToken.generation}async function loadExtensionModule(extensionPath,cacheToken){if(isCurrentCacheToken(cacheToken)){let cachedFactory=extensionCache.get(extensionPath);if(cachedFactory)return cachedFactory}let 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=getSyntheticPathSource(extensionPath)??"local",baseDir=isSyntheticPath(extensionPath)?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(err){return{extension:null,error:`Failed to load extension: ${err instanceof Error?err.message:String(err)}`}}}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=[],warnings=[],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,warnings,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,modelId){return this.runtime.getModel(provider,modelId)}findOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}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)}getModelsOfType(type,provider){return this.runtime.getModelsOfType(type,provider)}getAvailableOfType(type,provider,options){return this.runtime.getAvailableOfType(type,provider,options)}getModelOfType(type,provider,modelId){return this.runtime.getModelOfType(type,provider,modelId)}classify(model,context,options){return this.runtime.classify(model,context,options)}generateImages(model,context,options){return this.runtime.generateImages(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)}registerVirtualModel(definition){this.runtime.registerVirtualModel(definition)}unregisterVirtualModel(providerName,id){this.runtime.unregisterVirtualModel(providerName,id)}getRegisteredProviderConfig(providerName){return this.runtime.getRegisteredProviderConfig(providerName)}getRegisteredNativeProvider(providerName){return this.runtime.getRegisteredNativeProvider(providerName)}getRegisteredProviderIds(){return this.runtime.getRegisteredProviderIds()}};var Diff2=class{diff(oldStr,newStr,options={}){let callback;typeof options=="function"?(callback=options,options={}):"callback"in options&&(callback=options.callback);let oldString=this.castInput(oldStr,options),newString=this.castInput(newStr,options),oldTokens=this.removeEmpty(this.tokenize(oldString,options)),newTokens=this.removeEmpty(this.tokenize(newString,options));return this.diffWithOptionsObj(oldTokens,newTokens,options,callback)}diffWithOptionsObj(oldTokens,newTokens,options,callback){var _a2;let done=value=>{if(value=this.postProcess(value,options),callback){setTimeout(function(){callback(value)},0);return}else return value},newLen=newTokens.length,oldLen=oldTokens.length,editLength=1,maxEditLength=newLen+oldLen;options.maxEditLength!=null&&(maxEditLength=Math.min(maxEditLength,options.maxEditLength));let maxExecutionTime=(_a2=options.timeout)!==null&&_a2!==void 0?_a2:1/0,abortAfterTimestamp=Date.now()+maxExecutionTime,bestPath=[{oldPos:-1,lastComponent:void 0}],newPos=this.extractCommon(bestPath[0],newTokens,oldTokens,0,options);if(bestPath[0].oldPos+1>=oldLen&&newPos+1>=newLen)return done(this.buildValues(bestPath[0].lastComponent,newTokens,oldTokens));let minDiagonalToConsider=-1/0,maxDiagonalToConsider=1/0,execEditLength=()=>{for(let diagonalPath=Math.max(minDiagonalToConsider,-editLength);diagonalPath<=Math.min(maxDiagonalToConsider,editLength);diagonalPath+=2){let basePath,removePath=bestPath[diagonalPath-1],addPath=bestPath[diagonalPath+1];removePath&&(bestPath[diagonalPath-1]=void 0);let canAdd=!1;if(addPath){let addPathNewPos=addPath.oldPos-diagonalPath;canAdd=addPath&&0<=addPathNewPos&&addPathNewPos<newLen}let canRemove=removePath&&removePath.oldPos+1<oldLen;if(!canAdd&&!canRemove){bestPath[diagonalPath]=void 0;continue}if(!canRemove||canAdd&&removePath.oldPos<addPath.oldPos?basePath=this.addToPath(addPath,!0,!1,0,options):basePath=this.addToPath(removePath,!1,!0,1,options),newPos=this.extractCommon(basePath,newTokens,oldTokens,diagonalPath,options),basePath.oldPos+1>=oldLen&&newPos+1>=newLen)return done(this.buildValues(basePath.lastComponent,newTokens,oldTokens))||!0;bestPath[diagonalPath]=basePath,basePath.oldPos+1>=oldLen&&(maxDiagonalToConsider=Math.min(maxDiagonalToConsider,diagonalPath-1)),newPos+1>=newLen&&(minDiagonalToConsider=Math.max(minDiagonalToConsider,diagonalPath+1))}editLength++};if(callback)(function exec(){setTimeout(function(){if(editLength>maxEditLength||Date.now()>abortAfterTimestamp)return callback(void 0);execEditLength()||exec()},0)})();else for(;editLength<=maxEditLength&&Date.now()<=abortAfterTimestamp;){let ret=execEditLength();if(ret)return ret}}addToPath(path14,added,removed,oldPosInc,options){let last=path14.lastComponent;return last&&!options.oneChangePerToken&&last.added===added&&last.removed===removed?{oldPos:path14.oldPos+oldPosInc,lastComponent:{count:last.count+1,added,removed,previousComponent:last.previousComponent}}:{oldPos:path14.oldPos+oldPosInc,lastComponent:{count:1,added,removed,previousComponent:last}}}extractCommon(basePath,newTokens,oldTokens,diagonalPath,options){let newLen=newTokens.length,oldLen=oldTokens.length,oldPos=basePath.oldPos,newPos=oldPos-diagonalPath,commonCount=0;for(;newPos+1<newLen&&oldPos+1<oldLen&&this.equals(oldTokens[oldPos+1],newTokens[newPos+1],options);)newPos++,oldPos++,commonCount++,options.oneChangePerToken&&(basePath.lastComponent={count:1,previousComponent:basePath.lastComponent,added:!1,removed:!1});return commonCount&&!options.oneChangePerToken&&(basePath.lastComponent={count:commonCount,previousComponent:basePath.lastComponent,added:!1,removed:!1}),basePath.oldPos=oldPos,newPos}equals(left,right,options){return options.comparator?options.comparator(left,right):left===right||!!options.ignoreCase&&left.toLowerCase()===right.toLowerCase()}removeEmpty(array){let ret=[];for(let i=0;i<array.length;i++)array[i]&&ret.push(array[i]);return ret}castInput(value,options){return value}tokenize(value,options){return Array.from(value)}join(chars){return chars.join("")}postProcess(changeObjects,options){return changeObjects}get useLongestToken(){return!1}buildValues(lastComponent,newTokens,oldTokens){let components=[],nextComponent;for(;lastComponent;)components.push(lastComponent),nextComponent=lastComponent.previousComponent,delete lastComponent.previousComponent,lastComponent=nextComponent;components.reverse();let componentLen=components.length,componentPos=0,newPos=0,oldPos=0;for(;componentPos<componentLen;componentPos++){let component=components[componentPos];if(component.removed)component.value=this.join(oldTokens.slice(oldPos,oldPos+component.count)),oldPos+=component.count;else{if(!component.added&&this.useLongestToken){let value=newTokens.slice(newPos,newPos+component.count);value=value.map(function(value2,i){let oldValue=oldTokens[oldPos+i];return oldValue.length>value2.length?oldValue:value2}),component.value=this.join(value)}else component.value=this.join(newTokens.slice(newPos,newPos+component.count));newPos+=component.count,component.added||(oldPos+=component.count)}}return components}};function longestCommonPrefix(str1,str2){let i;for(i=0;i<str1.length&&i<str2.length;i++)if(str1[i]!=str2[i])return str1.slice(0,i);return str1.slice(0,i)}function longestCommonSuffix(str1,str2){let i;if(!str1||!str2||str1[str1.length-1]!=str2[str2.length-1])return"";for(i=0;i<str1.length&&i<str2.length;i++)if(str1[str1.length-(i+1)]!=str2[str2.length-(i+1)])return str1.slice(-i);return str1.slice(-i)}function replacePrefix(string2,oldPrefix,newPrefix){if(string2.slice(0,oldPrefix.length)!=oldPrefix)throw Error(`string ${JSON.stringify(string2)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);return newPrefix+string2.slice(oldPrefix.length)}function replaceSuffix(string2,oldSuffix,newSuffix){if(!oldSuffix)return string2+newSuffix;if(string2.slice(-oldSuffix.length)!=oldSuffix)throw Error(`string ${JSON.stringify(string2)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);return string2.slice(0,-oldSuffix.length)+newSuffix}function removePrefix(string2,oldPrefix){return replacePrefix(string2,oldPrefix,"")}function removeSuffix(string2,oldSuffix){return replaceSuffix(string2,oldSuffix,"")}function maximumOverlap(string1,string2){return string2.slice(0,overlapCount(string1,string2))}function overlapCount(a,b2){let startA=0;a.length>b2.length&&(startA=a.length-b2.length);let endB=b2.length;a.length<b2.length&&(endB=a.length);let map=Array(endB),k2=0;map[0]=0;for(let j2=1;j2<endB;j2++){for(b2[j2]==b2[k2]?map[j2]=map[k2]:map[j2]=k2;k2>0&&b2[j2]!=b2[k2];)k2=map[k2];b2[j2]==b2[k2]&&k2++}k2=0;for(let i=startA;i<a.length;i++){for(;k2>0&&a[i]!=b2[k2];)k2=map[k2];a[i]==b2[k2]&&k2++}return k2}function segment(string2,segmenter5){let parts=[];for(let segmentObj of Array.from(segmenter5.segment(string2))){let segment2=segmentObj.segment;parts.length&&/\s/.test(parts[parts.length-1])&&/\s/.test(segment2)?parts[parts.length-1]+=segment2:parts.push(segment2)}return parts}function trailingWs(string2,segmenter5){if(segmenter5)return leadingAndTrailingWs(string2,segmenter5)[1];let i;for(i=string2.length-1;i>=0&&string2[i].match(/\s/);i--);return string2.substring(i+1)}function leadingWs(string2,segmenter5){if(segmenter5)return leadingAndTrailingWs(string2,segmenter5)[0];let match2=string2.match(/^\s*/);return match2?match2[0]:""}function leadingAndTrailingWs(string2,segmenter5){if(!segmenter5)return[leadingWs(string2),trailingWs(string2)];if(segmenter5.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');let segments=segment(string2,segmenter5),firstSeg=segments[0],lastSeg=segments[segments.length-1],head=/\s/.test(firstSeg)?firstSeg:"",tail2=/\s/.test(lastSeg)?lastSeg:"";return[head,tail2]}var extendedWordChars="a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}",tokenizeIncludingWhitespace=new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`,"ug"),WordDiff=class extends Diff2{equals(left,right,options){return options.ignoreCase&&(left=left.toLowerCase(),right=right.toLowerCase()),left.trim()===right.trim()}tokenize(value,options={}){let parts;if(options.intlSegmenter){let segmenter5=options.intlSegmenter;if(segmenter5.resolvedOptions().granularity!="word")throw new Error('The segmenter passed must have a granularity of "word"');parts=segment(value,segmenter5)}else parts=value.match(tokenizeIncludingWhitespace)||[];let tokens2=[],prevPart=null;return parts.forEach(part=>{/\s/.test(part)?prevPart==null?tokens2.push(part):tokens2.push(tokens2.pop()+part):prevPart!=null&&/\s/.test(prevPart)?tokens2[tokens2.length-1]==prevPart?tokens2.push(tokens2.pop()+part):tokens2.push(prevPart+part):tokens2.push(part),prevPart=part}),tokens2}join(tokens2){return tokens2.map((token,i)=>i==0?token:token.replace(/^\s+/,"")).join("")}postProcess(changes,options){if(!changes||options.oneChangePerToken)return changes;let lastKeep=null,insertion=null,deletion=null;return changes.forEach(change=>{change.added?insertion=change:change.removed?deletion=change:((insertion||deletion)&&dedupeWhitespaceInChangeObjects(lastKeep,deletion,insertion,change,options.intlSegmenter),lastKeep=change,insertion=null,deletion=null)}),(insertion||deletion)&&dedupeWhitespaceInChangeObjects(lastKeep,deletion,insertion,null,options.intlSegmenter),changes}},wordDiff=new WordDiff;function diffWords(oldStr,newStr,options){return options?.ignoreWhitespace!=null&&!options.ignoreWhitespace?diffWordsWithSpace(oldStr,newStr,options):wordDiff.diff(oldStr,newStr,options)}function dedupeWhitespaceInChangeObjects(startKeep,deletion,insertion,endKeep,segmenter5){if(deletion&&insertion){let[oldWsPrefix,oldWsSuffix]=leadingAndTrailingWs(deletion.value,segmenter5),[newWsPrefix,newWsSuffix]=leadingAndTrailingWs(insertion.value,segmenter5);if(startKeep){let commonWsPrefix=longestCommonPrefix(oldWsPrefix,newWsPrefix);startKeep.value=replaceSuffix(startKeep.value,newWsPrefix,commonWsPrefix),deletion.value=removePrefix(deletion.value,commonWsPrefix),insertion.value=removePrefix(insertion.value,commonWsPrefix)}if(endKeep){let commonWsSuffix=longestCommonSuffix(oldWsSuffix,newWsSuffix);endKeep.value=replacePrefix(endKeep.value,newWsSuffix,commonWsSuffix),deletion.value=removeSuffix(deletion.value,commonWsSuffix),insertion.value=removeSuffix(insertion.value,commonWsSuffix)}}else if(insertion){if(startKeep){let ws=leadingWs(insertion.value,segmenter5);insertion.value=insertion.value.substring(ws.length)}if(endKeep){let ws=leadingWs(endKeep.value,segmenter5);endKeep.value=endKeep.value.substring(ws.length)}}else if(startKeep&&endKeep){let newWsFull=leadingWs(endKeep.value,segmenter5),[delWsStart,delWsEnd]=leadingAndTrailingWs(deletion.value,segmenter5),newWsStart=longestCommonPrefix(newWsFull,delWsStart);deletion.value=removePrefix(deletion.value,newWsStart);let newWsEnd=longestCommonSuffix(removePrefix(newWsFull,newWsStart),delWsEnd);deletion.value=removeSuffix(deletion.value,newWsEnd),endKeep.value=replacePrefix(endKeep.value,newWsFull,newWsEnd),startKeep.value=replaceSuffix(startKeep.value,newWsFull,newWsFull.slice(0,newWsFull.length-newWsEnd.length))}else if(endKeep){let endKeepWsPrefix=leadingWs(endKeep.value,segmenter5),deletionWsSuffix=trailingWs(deletion.value,segmenter5),overlap=maximumOverlap(deletionWsSuffix,endKeepWsPrefix);deletion.value=removeSuffix(deletion.value,overlap)}else if(startKeep){let startKeepWsSuffix=trailingWs(startKeep.value,segmenter5),deletionWsPrefix=leadingWs(deletion.value,segmenter5),overlap=maximumOverlap(startKeepWsSuffix,deletionWsPrefix);deletion.value=removePrefix(deletion.value,overlap)}}var WordsWithSpaceDiff=class extends Diff2{tokenize(value){let regex=new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`,"ug");return value.match(regex)||[]}},wordsWithSpaceDiff=new WordsWithSpaceDiff;function diffWordsWithSpace(oldStr,newStr,options){return wordsWithSpaceDiff.diff(oldStr,newStr,options)}var LineDiff=class extends Diff2{constructor(){super(...arguments),this.tokenize=tokenize}equals(left,right,options){return options.ignoreWhitespace?((!options.newlineIsToken||!left.includes(`
|
|
918
882
|
`))&&(left=left.trim()),(!options.newlineIsToken||!right.includes(`
|
|
919
883
|
`))&&(right=right.trim())):options.ignoreNewlineAtEof&&!options.newlineIsToken&&(left.endsWith(`
|
|
920
884
|
`)&&(left=left.slice(0,-1)),right.endsWith(`
|
|
@@ -926,7 +890,7 @@ Full output: ${outcome.task.outputPath}`:""}`}],details:{background:{kind:"backg
|
|
|
926
890
|
`}function createTwoFilesPatch(oldFileName,newFileName,oldStr,newStr,oldHeader,newHeader,options){if(typeof options=="function"&&(options={callback:options}),options?.callback){let{callback}=options;structuredPatch(oldFileName,newFileName,oldStr,newStr,oldHeader,newHeader,Object.assign(Object.assign({},options),{callback:patchObj=>{callback(patchObj?formatPatch(patchObj,options.headerOptions):void 0)}}))}else{let patchObj=structuredPatch(oldFileName,newFileName,oldStr,newStr,oldHeader,newHeader,options);return patchObj?formatPatch(patchObj,options?.headerOptions):void 0}}function splitLines(text2){let hasTrailingNl=text2.endsWith(`
|
|
927
891
|
`),result2=text2.split(`
|
|
928
892
|
`).map(line=>line+`
|
|
929
|
-
`);return hasTrailingNl?result2.pop():result2.push(result2.pop().slice(0,-1)),result2}import{constants as
|
|
893
|
+
`);return hasTrailingNl?result2.pop():result2.push(result2.pop().slice(0,-1)),result2}import{constants as constants4}from"fs";import{access as access2,readFile as readFile2}from"fs/promises";import{accessSync as accessSync3,constants as constants3}from"node:fs";import{access}from"node:fs/promises";var NARROW_NO_BREAK_SPACE="\u202F";function tryMacOSScreenshotPath(filePath){return filePath.replace(/ (AM|PM)\./gi,`${NARROW_NO_BREAK_SPACE}$1.`)}function tryNFDVariant(filePath){return filePath.normalize("NFD")}function tryCurlyQuoteVariant(filePath){return filePath.replace(/'/g,"\u2019")}function fileExists(filePath){try{return accessSync3(filePath,constants3.F_OK),!0}catch{return!1}}async function pathExists(filePath){try{return await access(filePath,constants3.F_OK),!0}catch{return!1}}function resolveToCwd(filePath,cwd){return resolvePath(filePath,cwd,{normalizeUnicodeSpaces:!0,stripAtPrefix:!0})}function resolveReadPath(filePath,cwd){let resolved=resolveToCwd(filePath,cwd);if(fileExists(resolved))return resolved;let amPmVariant=tryMacOSScreenshotPath(resolved);if(amPmVariant!==resolved&&fileExists(amPmVariant))return amPmVariant;let nfdVariant=tryNFDVariant(resolved);if(nfdVariant!==resolved&&fileExists(nfdVariant))return nfdVariant;let curlyVariant=tryCurlyQuoteVariant(resolved);if(curlyVariant!==resolved&&fileExists(curlyVariant))return curlyVariant;let nfdCurlyVariant=tryCurlyQuoteVariant(nfdVariant);return nfdCurlyVariant!==resolved&&fileExists(nfdCurlyVariant)?nfdCurlyVariant:resolved}async function resolveReadPathAsync(filePath,cwd){let resolved=resolveToCwd(filePath,cwd);if(await pathExists(resolved))return resolved;let amPmVariant=tryMacOSScreenshotPath(resolved);if(amPmVariant!==resolved&&await pathExists(amPmVariant))return amPmVariant;let nfdVariant=tryNFDVariant(resolved);if(nfdVariant!==resolved&&await pathExists(nfdVariant))return nfdVariant;let curlyVariant=tryCurlyQuoteVariant(resolved);if(curlyVariant!==resolved&&await pathExists(curlyVariant))return curlyVariant;let nfdCurlyVariant=tryCurlyQuoteVariant(nfdVariant);return nfdCurlyVariant!==resolved&&await pathExists(nfdCurlyVariant)?nfdCurlyVariant:resolved}function detectLineEnding(content){let crlfIdx=content.indexOf(`\r
|
|
930
894
|
`),lfIdx=content.indexOf(`
|
|
931
895
|
`);return lfIdx===-1||crlfIdx===-1?`
|
|
932
896
|
`:crlfIdx<lfIdx?`\r
|
|
@@ -941,13 +905,20 @@ Full output: ${outcome.task.outputPath}`:""}`}],details:{background:{kind:"backg
|
|
|
941
905
|
`),newLines=newContent.split(`
|
|
942
906
|
`),maxLineNum=Math.max(oldLines.length,newLines.length),lineNumWidth=String(maxLineNum).length,oldLineNum=1,newLineNum=1,lastWasChange=!1,firstChangedLine;for(let i=0;i<parts.length;i++){let part=parts[i],raw=part.value.split(`
|
|
943
907
|
`);if(raw[raw.length-1]===""&&raw.pop(),part.added||part.removed){firstChangedLine===void 0&&(firstChangedLine=newLineNum);for(let line of raw)if(part.added){let lineNum=String(newLineNum).padStart(lineNumWidth," ");output.push(`+${lineNum} ${line}`),newLineNum++}else{let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(`-${lineNum} ${line}`),oldLineNum++}lastWasChange=!0}else{let nextPartIsChange=i<parts.length-1&&(parts[i+1].added||parts[i+1].removed),hasLeadingChange=lastWasChange,hasTrailingChange=nextPartIsChange;if(hasLeadingChange&&hasTrailingChange)if(raw.length<=contextLines*2)for(let line of raw){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}else{let leadingLines=raw.slice(0,contextLines),trailingLines=raw.slice(raw.length-contextLines),skippedLines=raw.length-leadingLines.length-trailingLines.length;for(let line of leadingLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines;for(let line of trailingLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}}else if(hasLeadingChange){let shownLines=raw.slice(0,contextLines),skippedLines=raw.length-shownLines.length;for(let line of shownLines){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}skippedLines>0&&(output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines)}else if(hasTrailingChange){let skippedLines=Math.max(0,raw.length-contextLines);skippedLines>0&&(output.push(` ${"".padStart(lineNumWidth," ")} ...`),oldLineNum+=skippedLines,newLineNum+=skippedLines);for(let line of raw.slice(skippedLines)){let lineNum=String(oldLineNum).padStart(lineNumWidth," ");output.push(` ${lineNum} ${line}`),oldLineNum++,newLineNum++}}else oldLineNum+=raw.length,newLineNum+=raw.length;lastWasChange=!1}}return{diff:output.join(`
|
|
944
|
-
`),firstChangedLine}}async function computeEditsDiff(path14,edits,cwd){let absolutePath=resolveToCwd(path14,cwd);try{try{await access2(absolutePath,
|
|
945
|
-
`),result2=[],i=0;for(;i<lines.length;){let line=lines[i],parsed=parseDiffLine(line);if(!parsed){result2.push(theme.fg("toolDiffContext",line)),i++;continue}if(parsed.prefix==="-"){let removedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="-")break;removedLines.push({lineNum:p.lineNum,content:p.content}),i++}let addedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="+")break;addedLines.push({lineNum:p.lineNum,content:p.content}),i++}if(removedLines.length===1&&addedLines.length===1){let removed=removedLines[0],added=addedLines[0],{removedLine,addedLine}=renderIntraLineDiff(
|
|
946
|
-
`)}import
|
|
908
|
+
`),firstChangedLine}}async function computeEditsDiff(path14,edits,cwd){let absolutePath=resolveToCwd(path14,cwd);try{try{await access2(absolutePath,constants4.R_OK)}catch(error){let errorMessage9=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);return{error:`Could not edit file: ${path14}. ${errorMessage9}.`}}let rawContent=await readFile2(absolutePath,"utf-8"),{text:content}=splitBom(rawContent),normalizedContent=normalizeToLF(content),{baseContent,newContent}=applyEditsToNormalizedContent(normalizedContent,edits,path14);return generateDiffString(baseContent,newContent)}catch(err){return{error:err instanceof Error?err.message:String(err)}}}import{realpath}from"node:fs/promises";import{resolve as resolve6}from"node:path";var fileMutationQueues=new Map,registrationQueue=Promise.resolve();function isMissingPathError(error){return typeof error=="object"&&error!==null&&"code"in error&&(error.code==="ENOENT"||error.code==="ENOTDIR")}async function getMutationQueueKey(filePath){let resolvedPath=resolve6(filePath);try{return await realpath(resolvedPath)}catch(error){if(isMissingPathError(error))return resolvedPath;throw error}}async function withFileMutationQueue(filePath,fn){let registration=registrationQueue.then(async()=>{let key2=await getMutationQueueKey(filePath),currentQueue2=fileMutationQueues.get(key2)??Promise.resolve(),releaseNext2,nextQueue=new Promise(resolveQueue=>{releaseNext2=resolveQueue}),chainedQueue2=currentQueue2.then(()=>nextQueue);return fileMutationQueues.set(key2,chainedQueue2),{key:key2,currentQueue:currentQueue2,chainedQueue:chainedQueue2,releaseNext:releaseNext2}});registrationQueue=registration.then(()=>{},()=>{});let{key,currentQueue,chainedQueue,releaseNext}=await registration;await currentQueue;try{return await fn()}finally{releaseNext(),fileMutationQueues.get(key)===chainedQueue&&fileMutationQueues.delete(key)}}function parseDiffLine(line){let match2=line.match(/^([+-\s])(\s*\d*)\s(.*)$/);return match2?{prefix:match2[1],lineNum:match2[2],content:match2[3]}:null}function replaceTabs(text2){return text2.replace(/\t/g," ")}function renderIntraLineDiff(oldContent,newContent){let wordDiff2=diffWords(oldContent,newContent),removedLine="",addedLine="",isFirstRemoved=!0,isFirstAdded=!0;for(let part of wordDiff2)if(part.removed){let value=part.value;if(isFirstRemoved){let leadingWs2=value.match(/^(\s*)/)?.[1]||"";value=value.slice(leadingWs2.length),removedLine+=leadingWs2,isFirstRemoved=!1}value&&(removedLine+=theme.inverse(value))}else if(part.added){let value=part.value;if(isFirstAdded){let leadingWs2=value.match(/^(\s*)/)?.[1]||"";value=value.slice(leadingWs2.length),addedLine+=leadingWs2,isFirstAdded=!1}value&&(addedLine+=theme.inverse(value))}else removedLine+=part.value,addedLine+=part.value;return{removedLine,addedLine}}function renderDiff(diffText,_options={}){let lines=diffText.split(`
|
|
909
|
+
`),result2=[],i=0;for(;i<lines.length;){let line=lines[i],parsed=parseDiffLine(line);if(!parsed){result2.push(theme.fg("toolDiffContext",line)),i++;continue}if(parsed.prefix==="-"){let removedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="-")break;removedLines.push({lineNum:p.lineNum,content:p.content}),i++}let addedLines=[];for(;i<lines.length;){let p=parseDiffLine(lines[i]);if(!p||p.prefix!=="+")break;addedLines.push({lineNum:p.lineNum,content:p.content}),i++}if(removedLines.length===1&&addedLines.length===1){let removed=removedLines[0],added=addedLines[0],{removedLine,addedLine}=renderIntraLineDiff(replaceTabs(removed.content),replaceTabs(added.content));result2.push(theme.fg("toolDiffRemoved",`-${removed.lineNum} ${removedLine}`)),result2.push(theme.fg("toolDiffAdded",`+${added.lineNum} ${addedLine}`))}else{for(let removed of removedLines)result2.push(theme.fg("toolDiffRemoved",`-${removed.lineNum} ${replaceTabs(removed.content)}`));for(let added of addedLines)result2.push(theme.fg("toolDiffAdded",`+${added.lineNum} ${replaceTabs(added.content)}`))}}else parsed.prefix==="+"?(result2.push(theme.fg("toolDiffAdded",`+${parsed.lineNum} ${replaceTabs(parsed.content)}`)),i++):(result2.push(theme.fg("toolDiffContext",` ${parsed.lineNum} ${replaceTabs(parsed.content)}`)),i++)}return result2.join(`
|
|
910
|
+
`)}import*as os4 from"node:os";import{pathToFileURL as pathToFileURL2}from"node:url";var ST="(?:\\u0007|\\u001B\\u005C|\\u009C)",OSC_START="\\u001B\\]",CSI_START="[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?",CSI_FINAL="[\\dA-PR-TZcf-nq-uy=><~]",ansiRegex=new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`,"g"),unfinishedAnsiAtEndRegex=new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`),MAX_PENDING_ANSI_LENGTH=256;function splitIncompleteAnsiSuffix(value){if(!value.includes("\x1B")&&!value.includes("\x9B"))return{complete:value,pending:""};let windowStart=Math.max(0,value.length-MAX_PENDING_ANSI_LENGTH),match2=unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));if(!match2)return{complete:value,pending:""};let splitAt=windowStart+match2.index;return{complete:value.slice(0,splitAt),pending:value.slice(splitAt)}}function stripAnsi(value){if(typeof value!="string")throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);return!value.includes("\x1B")&&!value.includes("\x9B")?value:value.replace(ansiRegex,"")}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(value){return typeof value=="string"?value:value==null?"":null}function parseLineNumber(value){return typeof value=="string"&&value.trim()!==""&&(value=Number(value)),typeof value=="number"&&Number.isFinite(value)?value:void 0}function formatReadLineRange(offset,limit){if(offset==null&&limit==null)return"";let start=offset==null?1:parseLineNumber(offset);if(start===void 0)return"";if(limit==null)return`:${start}`;let count=parseLineNumber(limit);if(count===void 0)return"";let end=start+count-1;return`:${start}${end?`-${end}`:""}`}function replaceTabs2(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(`
|
|
911
|
+
`),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(`
|
|
912
|
+
`);output=output?`${output}
|
|
913
|
+
${imageIndicators}`:imageIndicators}return output}var COLLAPSED_ARGS_CHARS=100;function formatToolCallWithArgs(title,args,theme2,expanded){let header2=theme2.fg("toolTitle",theme2.bold(title));if(args==null)return header2;let entries=typeof args=="object"&&!Array.isArray(args)?Object.entries(args):[["args",args]];if(entries.length===0)return header2;if(expanded){let lines=entries.map(([key,value])=>{let text2=typeof value=="string"?value:JSON.stringify(value,null,2)??String(value);return` ${key}: ${replaceTabs2(text2).replace(/\r/g,"").split(`
|
|
914
|
+
`).join(`
|
|
915
|
+
`)}`});return`${header2}
|
|
916
|
+
${theme2.fg("muted",lines.join(`
|
|
917
|
+
`))}`}let pairs=entries.map(([key,value])=>`${key}=${JSON.stringify(value)??String(value)}`).join(" "),preview=pairs.length>COLLAPSED_ARGS_CHARS?`${pairs.slice(0,COLLAPSED_ARGS_CHARS-3)}...`:pairs;return`${header2} ${theme2.fg("muted",preview)}`}function formatToolDuration(ms){let seconds=ms/1e3;if(seconds<60)return`${seconds.toFixed(1)}s`;let totalSeconds=Math.floor(seconds),minutes=Math.floor(totalSeconds/60),remainder=totalSeconds%60;return minutes<60?`${minutes}m ${remainder}s`:`${Math.floor(minutes/60)}h ${minutes%60}m ${remainder}s`}function startToolTimer(context){let state2=context.state;context.executionStarted&&state2.startedAt===void 0&&(state2.startedAt=Date.now(),state2.endedAt=void 0)}function toolTimerText(context,isPartial){let state2=context.state;if(state2.startedAt!==void 0&&isPartial&&!state2.interval&&(state2.interval=setInterval(()=>context.invalidate(),1e3)),(!isPartial||context.isError)&&(state2.endedAt??=Date.now(),state2.interval&&(clearInterval(state2.interval),state2.interval=void 0)),!isPartial&&context.durationMs!==void 0)return`Took ${formatToolDuration(context.durationMs)}`;if(state2.startedAt===void 0)return;let endTime=state2.endedAt??Date.now();return`${isPartial?"Elapsed":"Took"} ${formatToolDuration(endTime-state2.startedAt)}`}function invalidArgText(theme2){return theme2.fg("error","[invalid arg]")}function renderToolPath(rawPath,theme2,cwd,options){if(rawPath===null)return invalidArgText(theme2);let value=rawPath||options?.emptyFallback;return value?linkPath(theme2.fg("accent",shortenPath2(value)),value,cwd):theme2.fg("toolOutput","...")}import{constants as constants5}from"fs";import{access as fsAccess,readFile as fsReadFile,writeFile as fsWriteFile}from"fs/promises";var EditCallRenderComponent=class extends Container{constructor(){super(...arguments),this.previewPending=!1}};function getEditCallRenderComponent(state2,lastComponent){if(lastComponent instanceof EditCallRenderComponent)return state2.callComponent=lastComponent,lastComponent;if(state2.callComponent)return state2.callComponent;let component=new EditCallRenderComponent;return state2.callComponent=component,component}function getRenderablePreviewInput(args){if(!args)return null;let path14=typeof args.path=="string"?args.path:typeof args.file_path=="string"?args.file_path:null;return path14?Array.isArray(args.edits)&&args.edits.length>0&&args.edits.every(edit=>typeof edit?.oldText=="string"&&typeof edit?.newText=="string")?{path:path14,edits:args.edits}:typeof args.oldText=="string"&&typeof args.newText=="string"?{path:path14,edits:[{oldText:args.oldText,newText:args.newText}]}:null:null}function formatEditCall(args,theme2,cwd){let pathDisplay=renderToolPath(str(args?.file_path??args?.path),theme2,cwd);return`${theme2.fg("toolTitle",theme2.bold("edit"))} ${pathDisplay}`}var EDIT_COLLAPSED_DIFF_LINES=10;function boundDiffBody(renderedDiff,expanded,theme2){if(expanded)return renderedDiff;let lines=renderedDiff.split(`
|
|
947
918
|
`);if(lines.length<=EDIT_COLLAPSED_DIFF_LINES)return renderedDiff;let shown=lines.slice(0,EDIT_COLLAPSED_DIFF_LINES),remaining=lines.length-shown.length;return`${shown.join(`
|
|
948
919
|
`)}${theme2.fg("muted",`
|
|
949
920
|
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}function formatEditResult(args,preview,result2,theme2,isError,expanded){let rawPath=str(args?.file_path??args?.path),previewDiff=preview&&!("error"in preview)?preview.diff:void 0,previewError=preview&&"error"in preview?preview.error:void 0;if(isError){let errorText3=result2.content.filter(c=>c.type==="text").map(c=>c.text||"").join(`
|
|
950
|
-
`);return!errorText3||errorText3===previewError?void 0:theme2.fg("error",errorText3)}let resultDiff=result2.details?.diff;if(resultDiff&&resultDiff!==previewDiff)return boundDiffBody(renderDiff(resultDiff,{filePath:rawPath??void 0}),expanded,theme2)}function buildEditCallComponent(component,args,theme2,cwd,expanded){component.clear(),component.addChild(new Text(formatEditCall(args,theme2,cwd),0,0));let preview=component.preview;if(!preview)return component;let body2="error"in preview?theme2.fg("error",preview.error):boundDiffBody(renderDiff(preview.diff),expanded,theme2);return component.addChild(new Spacer(1)),component.addChild(new Text(body2,0,0)),component}function setEditPreview(component,preview,argsKey){let current=component.preview,changed2=current===void 0||("error"in current&&"error"in preview?current.error!==preview.error:"error"in current!="error"in preview)||!("error"in current)&&!("error"in preview)&&(current.diff!==preview.diff||current.firstChangedLine!==preview.firstChangedLine);return component.preview=preview,component.previewArgsKey=argsKey,component.previewPending=!1,changed2}var editRenderers={renderCall(args,theme2,context){let component=getEditCallRenderComponent(context.state,context.lastComponent),previewInput=getRenderablePreviewInput(args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0;if(component.previewArgsKey!==argsKey&&(component.preview=void 0,component.previewArgsKey=argsKey,component.previewPending=!1),context.argsComplete&&previewInput&&!component.preview&&!component.previewPending){component.previewPending=!0;let requestKey=argsKey;computeEditsDiff(previewInput.path,previewInput.edits,context.cwd).then(preview=>{component.previewArgsKey===requestKey&&(setEditPreview(component,preview,requestKey),context.invalidate())})}return buildEditCallComponent(component,args,theme2,context.cwd,context.expanded)},renderResult(result2,options,theme2,context){let callComponent=context.state.callComponent,previewInput=getRenderablePreviewInput(context.args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0,typedResult=result2,resultDiff=context.isError?void 0:typedResult.details?.diff,changed2=!1;callComponent&&(typeof resultDiff=="string"&&(changed2=setEditPreview(callComponent,{diff:resultDiff,firstChangedLine:typedResult.details?.firstChangedLine},argsKey)||changed2),changed2&&buildEditCallComponent(callComponent,context.args,theme2,context.cwd,context.expanded));let output=formatEditResult(context.args,callComponent?.preview,typedResult,theme2,context.isError,options.expanded),component=context.lastComponent??new Container;return component.clear(),output&&(component.addChild(new Spacer(1)),component.addChild(new Text(output,context.outputPad,0))),component}};var replaceEditSchema=typebox_exports.Object({oldText:typebox_exports.String({description:"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call."}),newText:typebox_exports.String({description:"Replacement text for this targeted edit."})},{}),editSchema=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to edit (relative or absolute)"}),edits:typebox_exports.Array(replaceEditSchema,{description:"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead."})},{}),editToolSystemPromptContribution={snippet:"Make precise file edits with exact text replacement, including multiple disjoint edits in one call",guidelines:["Use edit for precise changes (edits[].oldText must match exactly)","When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls","Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.","Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions."]};function isSingleEditInput(value){if(!value||typeof value!="object"||Array.isArray(value))return!1;let edit=value;return typeof edit.oldText=="string"&&typeof edit.newText=="string"}var defaultEditOperations={readFile:path14=>fsReadFile(path14),writeFile:(path14,content)=>fsWriteFile(path14,content,"utf-8"),access:path14=>fsAccess2(path14,constants6.R_OK|constants6.W_OK)};function prepareEditArguments(input2){if(!input2||typeof input2!="object")return input2;let args=input2;if(typeof args.edits=="string")try{let parsed=JSON.parse(args.edits);Array.isArray(parsed)?args.edits=parsed:isSingleEditInput(parsed)&&(args.edits=[parsed])}catch{}else isSingleEditInput(args.edits)&&(args.edits=[args.edits]);let legacy=args;if(typeof legacy.oldText!="string"||typeof legacy.newText!="string")return args;let edits=Array.isArray(legacy.edits)?[...legacy.edits]:[];edits.push({oldText:legacy.oldText,newText:legacy.newText});let{oldText:_oldText,newText:_newText,...rest}=legacy;return{...rest,edits}}function validateEditInput(input2){if(!Array.isArray(input2.edits)||input2.edits.length===0)throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");return{path:input2.path,edits:input2.edits}}function createEditToolDefinition(cwd,options){let ops=options?.operations??defaultEditOperations;return{name:"edit",label:"edit",description:"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.",promptSnippet:editToolSystemPromptContribution.snippet,promptGuidelines:[...editToolSystemPromptContribution.guidelines],parameters:editSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:prepareEditArguments,async execute(_toolCallId,input2,signal,_onUpdate,ctx){let{path:path14,edits}=validateEditInput(input2),absolutePath=resolveToCwd(path14,ctx?.cwd||cwd);return withFileMutationQueue(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};throwIfAborted();try{await ops.access(absolutePath)}catch(error){throwIfAborted();let errorMessage9=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);throw new Error(`Could not edit file: ${path14}. ${errorMessage9}.`)}throwIfAborted();let rawContent=(await ops.readFile(absolutePath)).toString("utf-8");throwIfAborted();let{bom,text:content}=splitBom(rawContent),originalEnding=detectLineEnding(content),normalizedContent=normalizeToLF(content),{baseContent,newContent}=applyEditsToNormalizedContent(normalizedContent,edits,path14);throwIfAborted();let finalContent=bom+restoreLineEndings(newContent,originalEnding);await ops.writeFile(absolutePath,finalContent),throwIfAborted();let diffResult=generateDiffString(baseContent,newContent),patch=generateUnifiedPatch(path14,baseContent,newContent);return{content:[{type:"text",text:`Successfully replaced ${edits.length} block(s) in ${path14}.`}],details:{diff:diffResult.diff,patch,firstChangedLine:diffResult.firstChangedLine}}})},...editRenderers}}function createEditTool(cwd,options){return wrapToolDefinition(createEditToolDefinition(cwd,options))}import{createInterface as createInterface2}from"node:readline";import{spawn as spawn5}from"child_process";import path8 from"path";import{spawnSync as spawnSync4}from"child_process";import{chmodSync as chmodSync2,createWriteStream as createWriteStream2,existsSync as existsSync11,mkdirSync as mkdirSync6,readdirSync as readdirSync7,renameSync,rmSync as rmSync2}from"fs";import{arch,platform}from"os";import{join as join21}from"path";import{Readable}from"stream";import{pipeline}from"stream/promises";var TOOLS_DIR=getBinDir(),NETWORK_TIMEOUT_MS2=1e4,DOWNLOAD_TIMEOUT_MS=12e4;function isOfflineModeEnabled2(){let value=process.env.PI_OFFLINE;return value?value==="1"||value.toLowerCase()==="true"||value.toLowerCase()==="yes":!1}var TOOLS={fd:{name:"fd",repo:"sharkdp/fd",binaryName:"fd",systemBinaryNames:["fd","fdfind"],tagPrefix:"v",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null},rg:{name:"ripgrep",repo:"BurntSushi/ripgrep",binaryName:"rg",tagPrefix:"",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null}};function commandExists(cmd){try{let result2=spawnSync4(cmd,["--version"],{stdio:"pipe"});return result2.error===void 0||result2.error===null}catch{return!1}}function getToolPath(tool){let config=TOOLS[tool];if(!config)return null;let localPath=join21(TOOLS_DIR,config.binaryName+(platform()==="win32"?".exe":""));if(existsSync11(localPath))return localPath;let systemBinaryNames=config.systemBinaryNames??[config.binaryName];for(let systemBinaryName of systemBinaryNames)if(commandExists(systemBinaryName))return systemBinaryName;return null}async function getLatestVersion(repo){let response=await fetchWithRetry(`https://github.com/${repo}/releases/latest`,{headers:{"User-Agent":getPiUserAgent(VERSION)},redirect:"manual"},{timeoutMs:NETWORK_TIMEOUT_MS2});try{await response.body?.cancel()}catch{}let location=response.status>=300&&response.status<400?response.headers.get("location"):null;if(!location)throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);let tag=new URL(location,"https://github.com").pathname.split("/").pop();if(!tag||!location.includes("/releases/tag/"))throw new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);return decodeURIComponent(tag).replace(/^v/,"")}async function downloadFile(url,dest){let response=await fetchWithRetry(url,void 0,{timeoutMs:DOWNLOAD_TIMEOUT_MS});if(!response.ok)throw new Error(`Download failed with HTTP ${response.status}: ${url}`);if(!response.body)throw new Error("No response body");let fileStream=createWriteStream2(dest);await pipeline(Readable.fromWeb(response.body),fileStream)}function findBinaryRecursively(rootDir,binaryFileName){let stack=[rootDir];for(;stack.length>0;){let currentDir=stack.pop();if(!currentDir)continue;let entries=readdirSync7(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join21(currentDir,entry.name);if(entry.isFile()&&entry.name===binaryFileName)return fullPath;entry.isDirectory()&&stack.push(fullPath)}}return null}function formatSpawnFailure(result2){if(result2.error?.message)return result2.error.message;let stderr=result2.stderr?.toString().trim();if(stderr)return stderr;let stdout=result2.stdout?.toString().trim();return stdout||`exit status ${result2.status??"unknown"}`}function runExtractionCommand(command,args){let result2=spawnSync4(command,args,{stdio:"pipe"});return!result2.error&&result2.status===0?null:`${command}: ${formatSpawnFailure(result2)}`}function extractTarGzArchive(archivePath,extractDir,assetName){let failure=runExtractionCommand("tar",["xzf",archivePath,"-C",extractDir]);if(failure)throw new Error(`Failed to extract ${assetName}: ${failure}`)}function getWindowsTarCommand(){let systemRoot=process.env.SystemRoot;if(systemRoot){let systemTar=join21(systemRoot,"System32","tar.exe");if(existsSync11(systemTar))return systemTar}return"tar.exe"}function extractZipArchive(archivePath,extractDir,assetName){let failures=[];if(platform()==="win32"){let tarFailure=runExtractionCommand(getWindowsTarCommand(),["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure);let powershellFailure=runExtractionCommand("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }",archivePath,extractDir]);if(!powershellFailure)return;failures.push(powershellFailure)}else{let unzipFailure=runExtractionCommand("unzip",["-q",archivePath,"-d",extractDir]);if(!unzipFailure)return;failures.push(unzipFailure);let tarFailure=runExtractionCommand("tar",["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure)}throw new Error(`Failed to extract ${assetName}: ${failures.join("; ")}`)}async function downloadTool(tool){let config=TOOLS[tool];if(!config)throw new Error(`Unknown tool: ${tool}`);let plat=platform(),architecture=arch(),version2=tool==="fd"&&plat==="darwin"&&architecture==="x64"?"10.3.0":await getLatestVersion(config.repo),assetName=config.getAssetName(version2,plat,architecture);if(!assetName)throw new Error(`Unsupported platform: ${plat}/${architecture}`);mkdirSync6(TOOLS_DIR,{recursive:!0});let downloadUrl=`https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version2}/${assetName}`,archivePath=join21(TOOLS_DIR,assetName),binaryExt=plat==="win32"?".exe":"",binaryPath=join21(TOOLS_DIR,config.binaryName+binaryExt);await downloadFile(downloadUrl,archivePath);let extractDir=join21(TOOLS_DIR,`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2,10)}`);mkdirSync6(extractDir,{recursive:!0});try{if(assetName.endsWith(".tar.gz"))extractTarGzArchive(archivePath,extractDir,assetName);else if(assetName.endsWith(".zip"))extractZipArchive(archivePath,extractDir,assetName);else throw new Error(`Unsupported archive format: ${assetName}`);let binaryFileName=config.binaryName+binaryExt,extractedDir=join21(extractDir,assetName.replace(/\.(tar\.gz|zip)$/,"")),extractedBinary=[join21(extractedDir,binaryFileName),join21(extractDir,binaryFileName)].find(candidate=>existsSync11(candidate));if(extractedBinary||(extractedBinary=findBinaryRecursively(extractDir,binaryFileName)??void 0),extractedBinary)renameSync(extractedBinary,binaryPath);else throw new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);plat!=="win32"&&chmodSync2(binaryPath,493)}finally{rmSync2(archivePath,{force:!0}),rmSync2(extractDir,{recursive:!0,force:!0})}return binaryPath}var TERMUX_PACKAGES={fd:"fd",rg:"ripgrep"};async function ensureTool(tool,onStatus){let existingPath=getToolPath(tool);if(existingPath)return existingPath;let config=TOOLS[tool];if(config){if(isOfflineModeEnabled2()){onStatus?.({type:"warning",message:`${config.name} not found. Offline mode enabled, skipping download.`});return}if(platform()==="android"){let pkgName=TERMUX_PACKAGES[tool]??tool;onStatus?.({type:"warning",message:`${config.name} not found. Install with: pkg install ${pkgName}`});return}onStatus?.({type:"info",message:`${config.name} not found. Downloading...`});try{let path14=await downloadTool(tool);return onStatus?.({type:"info",message:`${config.name} installed to ${path14}`}),path14}catch(e){let messages=[];for(let current=e,depth=0;current instanceof Error&&depth<5;current=current.cause,depth++)messages.includes(current.message)||messages.push(current.message);onStatus?.({type:"warning",message:`Failed to download ${config.name}: ${messages.length>0?messages.join(": "):String(e)}`});return}}}function formatFindCall(args,theme2){let pattern=str(args?.pattern),rawPath=str(args?.path),path14=rawPath!==null?shortenPath2(rawPath||"."):null,limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("find"))+" "+(pattern===null?invalidArg:theme2.fg("accent",pattern||""))+theme2.fg("toolOutput",` in ${path14===null?invalidArg:path14}`);return limit!==void 0&&(text2+=theme2.fg("toolOutput",` (limit ${limit})`)),text2}function formatFindResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
921
|
+
`);return!errorText3||errorText3===previewError?void 0:theme2.fg("error",errorText3)}let resultDiff=result2.details?.diff;if(resultDiff&&resultDiff!==previewDiff)return boundDiffBody(renderDiff(resultDiff,{filePath:rawPath??void 0}),expanded,theme2)}function buildEditCallComponent(component,args,theme2,cwd,expanded){component.clear(),component.addChild(new Text(formatEditCall(args,theme2,cwd),0,0));let preview=component.preview;if(!preview)return component;let body2="error"in preview?theme2.fg("error",preview.error):boundDiffBody(renderDiff(preview.diff),expanded,theme2);return component.addChild(new Spacer(1)),component.addChild(new Text(body2,0,0)),component}function setEditPreview(component,preview,argsKey){let current=component.preview,changed2=current===void 0||("error"in current&&"error"in preview?current.error!==preview.error:"error"in current!="error"in preview)||!("error"in current)&&!("error"in preview)&&(current.diff!==preview.diff||current.firstChangedLine!==preview.firstChangedLine);return component.preview=preview,component.previewArgsKey=argsKey,component.previewPending=!1,changed2}var editRenderers={renderCall(args,theme2,context){let component=getEditCallRenderComponent(context.state,context.lastComponent),previewInput=getRenderablePreviewInput(args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0;if(component.previewArgsKey!==argsKey&&(component.preview=void 0,component.previewArgsKey=argsKey,component.previewPending=!1),context.argsComplete&&previewInput&&!component.preview&&!component.previewPending){component.previewPending=!0;let requestKey=argsKey;computeEditsDiff(previewInput.path,previewInput.edits,context.cwd).then(preview=>{component.previewArgsKey===requestKey&&(setEditPreview(component,preview,requestKey),context.invalidate())})}return buildEditCallComponent(component,args,theme2,context.cwd,context.expanded)},renderResult(result2,options,theme2,context){let callComponent=context.state.callComponent,previewInput=getRenderablePreviewInput(context.args),argsKey=previewInput?JSON.stringify({path:previewInput.path,edits:previewInput.edits}):void 0,typedResult=result2,resultDiff=context.isError?void 0:typedResult.details?.diff,changed2=!1;callComponent&&(typeof resultDiff=="string"&&(changed2=setEditPreview(callComponent,{diff:resultDiff,firstChangedLine:typedResult.details?.firstChangedLine},argsKey)||changed2),changed2&&buildEditCallComponent(callComponent,context.args,theme2,context.cwd,context.expanded));let output=formatEditResult(context.args,callComponent?.preview,typedResult,theme2,context.isError,options.expanded),component=context.lastComponent??new Container;return component.clear(),output&&(component.addChild(new Spacer(1)),component.addChild(new Text(output,context.outputPad,0))),component}};var replaceEditSchema=typebox_exports.Object({oldText:typebox_exports.String({description:"Exact text for one targeted replacement. It must be unique in the original file and must not overlap with any other edits[].oldText in the same call."}),newText:typebox_exports.String({description:"Replacement text for this targeted edit."})},{}),editSchema=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to edit (relative or absolute)"}),edits:typebox_exports.Array(replaceEditSchema,{description:"One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead."})},{}),editToolSystemPromptContribution={snippet:"Make precise file edits with exact text replacement, including multiple disjoint edits in one call",guidelines:["Use edit for precise changes (edits[].oldText must match exactly)","When changing multiple separate locations in one file, use one edit call with multiple entries in edits[] instead of multiple edit calls","Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.","Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions."]};function isSingleEditInput(value){if(!value||typeof value!="object"||Array.isArray(value))return!1;let edit=value;return typeof edit.oldText=="string"&&typeof edit.newText=="string"}var defaultEditOperations={readFile:path14=>fsReadFile(path14),writeFile:(path14,content)=>fsWriteFile(path14,content,"utf-8"),access:path14=>fsAccess(path14,constants5.R_OK|constants5.W_OK)};function prepareEditArguments(input2){if(!input2||typeof input2!="object")return input2;let args=input2;if(typeof args.edits=="string")try{let parsed=JSON.parse(args.edits);Array.isArray(parsed)?args.edits=parsed:isSingleEditInput(parsed)&&(args.edits=[parsed])}catch{}else isSingleEditInput(args.edits)&&(args.edits=[args.edits]);let legacy=args;if(typeof legacy.oldText!="string"||typeof legacy.newText!="string")return args;let edits=Array.isArray(legacy.edits)?[...legacy.edits]:[];edits.push({oldText:legacy.oldText,newText:legacy.newText});let{oldText:_oldText,newText:_newText,...rest}=legacy;return{...rest,edits}}function validateEditInput(input2){if(!Array.isArray(input2.edits)||input2.edits.length===0)throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");return{path:input2.path,edits:input2.edits}}function createEditToolDefinition(cwd,options){let ops=options?.operations??defaultEditOperations;return{name:"edit",label:"edit",description:"Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.",promptSnippet:editToolSystemPromptContribution.snippet,promptGuidelines:[...editToolSystemPromptContribution.guidelines],parameters:editSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},prepareArguments:prepareEditArguments,async execute(_toolCallId,input2,signal,_onUpdate,ctx){let{path:path14,edits}=validateEditInput(input2),absolutePath=resolveToCwd(path14,ctx?.cwd||cwd);return withFileMutationQueue(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};throwIfAborted();try{await ops.access(absolutePath)}catch(error){throwIfAborted();let errorMessage9=error instanceof Error&&"code"in error?`Error code: ${error.code}`:String(error);throw new Error(`Could not edit file: ${path14}. ${errorMessage9}.`)}throwIfAborted();let rawContent=(await ops.readFile(absolutePath)).toString("utf-8");throwIfAborted();let{bom,text:content}=splitBom(rawContent),originalEnding=detectLineEnding(content),normalizedContent=normalizeToLF(content),{baseContent,newContent}=applyEditsToNormalizedContent(normalizedContent,edits,path14);throwIfAborted();let finalContent=bom+restoreLineEndings(newContent,originalEnding);await ops.writeFile(absolutePath,finalContent),throwIfAborted();let diffResult=generateDiffString(baseContent,newContent),patch=generateUnifiedPatch(path14,baseContent,newContent);return{content:[{type:"text",text:`Successfully replaced ${edits.length} block(s) in ${path14}.`}],details:{diff:diffResult.diff,patch,firstChangedLine:diffResult.firstChangedLine}}})},...editRenderers}}function createEditTool(cwd,options){return wrapToolDefinition(createEditToolDefinition(cwd,options))}import{createInterface as createInterface2}from"node:readline";import{spawn as spawn4}from"child_process";import path8 from"path";import{spawnSync as spawnSync4}from"child_process";import{chmodSync as chmodSync2,createWriteStream,existsSync as existsSync11,mkdirSync as mkdirSync6,readdirSync as readdirSync7,renameSync,rmSync as rmSync2}from"fs";import{arch,platform}from"os";import{join as join20}from"path";import{Readable}from"stream";import{pipeline}from"stream/promises";var TOOLS_DIR=getBinDir(),NETWORK_TIMEOUT_MS2=1e4,DOWNLOAD_TIMEOUT_MS=12e4;function isOfflineModeEnabled2(){let value=process.env.PI_OFFLINE;return value?value==="1"||value.toLowerCase()==="true"||value.toLowerCase()==="yes":!1}var TOOLS={fd:{name:"fd",repo:"sharkdp/fd",binaryName:"fd",systemBinaryNames:["fd","fdfind"],tagPrefix:"v",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`fd-v${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null},rg:{name:"ripgrep",repo:"BurntSushi/ripgrep",binaryName:"rg",tagPrefix:"",getAssetName:(version2,plat,architecture)=>plat==="darwin"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-apple-darwin.tar.gz`:plat==="linux"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-unknown-linux-musl.tar.gz`:plat==="win32"?`ripgrep-${version2}-${architecture==="arm64"?"aarch64":"x86_64"}-pc-windows-msvc.zip`:null}};function commandExists(cmd){try{let result2=spawnSync4(cmd,["--version"],{stdio:"pipe"});return result2.error===void 0||result2.error===null}catch{return!1}}function getToolPath(tool){let config=TOOLS[tool];if(!config)return null;let localPath=join20(TOOLS_DIR,config.binaryName+(platform()==="win32"?".exe":""));if(existsSync11(localPath))return localPath;let systemBinaryNames=config.systemBinaryNames??[config.binaryName];for(let systemBinaryName of systemBinaryNames)if(commandExists(systemBinaryName))return systemBinaryName;return null}async function getLatestVersion(repo){let response=await fetchWithRetry(`https://github.com/${repo}/releases/latest`,{headers:{"User-Agent":getPiUserAgent(VERSION)},redirect:"manual"},{timeoutMs:NETWORK_TIMEOUT_MS2});try{await response.body?.cancel()}catch{}let location=response.status>=300&&response.status<400?response.headers.get("location"):null;if(!location)throw new Error(`Failed to resolve latest ${repo} release: HTTP ${response.status} without redirect`);let tag=new URL(location,"https://github.com").pathname.split("/").pop();if(!tag||!location.includes("/releases/tag/"))throw new Error(`Failed to resolve latest ${repo} release: unexpected redirect to ${location}`);return decodeURIComponent(tag).replace(/^v/,"")}async function downloadFile(url,dest){let response=await fetchWithRetry(url,void 0,{timeoutMs:DOWNLOAD_TIMEOUT_MS});if(!response.ok)throw new Error(`Download failed with HTTP ${response.status}: ${url}`);if(!response.body)throw new Error("No response body");let fileStream=createWriteStream(dest);await pipeline(Readable.fromWeb(response.body),fileStream)}function findBinaryRecursively(rootDir,binaryFileName){let stack=[rootDir];for(;stack.length>0;){let currentDir=stack.pop();if(!currentDir)continue;let entries=readdirSync7(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join20(currentDir,entry.name);if(entry.isFile()&&entry.name===binaryFileName)return fullPath;entry.isDirectory()&&stack.push(fullPath)}}return null}function formatSpawnFailure(result2){if(result2.error?.message)return result2.error.message;let stderr=result2.stderr?.toString().trim();if(stderr)return stderr;let stdout=result2.stdout?.toString().trim();return stdout||`exit status ${result2.status??"unknown"}`}function runExtractionCommand(command,args){let result2=spawnSync4(command,args,{stdio:"pipe"});return!result2.error&&result2.status===0?null:`${command}: ${formatSpawnFailure(result2)}`}function extractTarGzArchive(archivePath,extractDir,assetName){let failure=runExtractionCommand("tar",["xzf",archivePath,"-C",extractDir]);if(failure)throw new Error(`Failed to extract ${assetName}: ${failure}`)}function getWindowsTarCommand(){let systemRoot=process.env.SystemRoot;if(systemRoot){let systemTar=join20(systemRoot,"System32","tar.exe");if(existsSync11(systemTar))return systemTar}return"tar.exe"}function extractZipArchive(archivePath,extractDir,assetName){let failures=[];if(platform()==="win32"){let tarFailure=runExtractionCommand(getWindowsTarCommand(),["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure);let powershellFailure=runExtractionCommand("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-ExecutionPolicy","Bypass","-Command","& { param($archive, $destination) $ErrorActionPreference = 'Stop'; Expand-Archive -LiteralPath $archive -DestinationPath $destination -Force }",archivePath,extractDir]);if(!powershellFailure)return;failures.push(powershellFailure)}else{let unzipFailure=runExtractionCommand("unzip",["-q",archivePath,"-d",extractDir]);if(!unzipFailure)return;failures.push(unzipFailure);let tarFailure=runExtractionCommand("tar",["xf",archivePath,"-C",extractDir]);if(!tarFailure)return;failures.push(tarFailure)}throw new Error(`Failed to extract ${assetName}: ${failures.join("; ")}`)}async function downloadTool(tool){let config=TOOLS[tool];if(!config)throw new Error(`Unknown tool: ${tool}`);let plat=platform(),architecture=arch(),version2=tool==="fd"&&plat==="darwin"&&architecture==="x64"?"10.3.0":await getLatestVersion(config.repo),assetName=config.getAssetName(version2,plat,architecture);if(!assetName)throw new Error(`Unsupported platform: ${plat}/${architecture}`);mkdirSync6(TOOLS_DIR,{recursive:!0});let downloadUrl=`https://github.com/${config.repo}/releases/download/${config.tagPrefix}${version2}/${assetName}`,archivePath=join20(TOOLS_DIR,assetName),binaryExt=plat==="win32"?".exe":"",binaryPath=join20(TOOLS_DIR,config.binaryName+binaryExt);await downloadFile(downloadUrl,archivePath);let extractDir=join20(TOOLS_DIR,`extract_tmp_${config.binaryName}_${process.pid}_${Date.now()}_${Math.random().toString(36).slice(2,10)}`);mkdirSync6(extractDir,{recursive:!0});try{if(assetName.endsWith(".tar.gz"))extractTarGzArchive(archivePath,extractDir,assetName);else if(assetName.endsWith(".zip"))extractZipArchive(archivePath,extractDir,assetName);else throw new Error(`Unsupported archive format: ${assetName}`);let binaryFileName=config.binaryName+binaryExt,extractedDir=join20(extractDir,assetName.replace(/\.(tar\.gz|zip)$/,"")),extractedBinary=[join20(extractedDir,binaryFileName),join20(extractDir,binaryFileName)].find(candidate=>existsSync11(candidate));if(extractedBinary||(extractedBinary=findBinaryRecursively(extractDir,binaryFileName)??void 0),extractedBinary)renameSync(extractedBinary,binaryPath);else throw new Error(`Binary not found in archive: expected ${binaryFileName} under ${extractDir}`);plat!=="win32"&&chmodSync2(binaryPath,493)}finally{rmSync2(archivePath,{force:!0}),rmSync2(extractDir,{recursive:!0,force:!0})}return binaryPath}var TERMUX_PACKAGES={fd:"fd",rg:"ripgrep"};async function ensureTool(tool,onStatus){let existingPath=getToolPath(tool);if(existingPath)return existingPath;let config=TOOLS[tool];if(config){if(isOfflineModeEnabled2()){onStatus?.({type:"warning",message:`${config.name} not found. Offline mode enabled, skipping download.`});return}if(platform()==="android"){let pkgName=TERMUX_PACKAGES[tool]??tool;onStatus?.({type:"warning",message:`${config.name} not found. Install with: pkg install ${pkgName}`});return}onStatus?.({type:"info",message:`${config.name} not found. Downloading...`});try{let path14=await downloadTool(tool);return onStatus?.({type:"info",message:`${config.name} installed to ${path14}`}),path14}catch(e){let messages=[];for(let current=e,depth=0;current instanceof Error&&depth<5;current=current.cause,depth++)messages.includes(current.message)||messages.push(current.message);onStatus?.({type:"warning",message:`Failed to download ${config.name}: ${messages.length>0?messages.join(": "):String(e)}`});return}}}function formatFindCall(args,theme2){let pattern=str(args?.pattern),rawPath=str(args?.path),path14=rawPath!==null?shortenPath2(rawPath||"."):null,limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("find"))+" "+(pattern===null?invalidArg:theme2.fg("accent",pattern||""))+theme2.fg("toolOutput",` in ${path14===null?invalidArg:path14}`);return limit!==void 0&&(text2+=theme2.fg("toolOutput",` (limit ${limit})`)),text2}function formatFindResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
951
922
|
`),maxLines=options.expanded?lines.length:20,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
952
923
|
${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
953
924
|
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
@@ -955,11 +926,11 @@ ${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
|
955
926
|
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var findRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatFindCall(args,theme2)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatFindResult(result2,options,theme2,context.showImages)),text2}};function toPosixPath3(value,pathModule=path8){return value.split(pathModule.sep).join("/")}function relativizeFindResultPath(resultPath,searchPath,pathModule=path8){let hadTrailingSeparator=resultPath.endsWith(pathModule.sep)||pathModule.sep==="\\"&&resultPath.endsWith("/"),posixPath=(pathModule.isAbsolute(resultPath)?pathModule.relative(searchPath,resultPath):resultPath).split(pathModule.sep).join("/");return hadTrailingSeparator&&!posixPath.endsWith("/")?`${posixPath}/`:posixPath}function matchesFindResultPath(resultPath,searchPath,pattern,pathModule=path8){let normalizedResult=resultPath.replace(/\r$/,"").trim();if(!normalizedResult)return!1;let candidate=pathModule.isAbsolute(pattern)?toPosixPath3(normalizedResult,pathModule):toPosixPath3(pathModule.relative(searchPath,normalizedResult),pathModule),candidateWithDirectoryMarker=(normalizedResult.endsWith("/")||normalizedResult.endsWith("\\"))&&!candidate.endsWith("/")?`${candidate}/`:candidate;return minimatch(candidateWithDirectoryMarker,toPosixPath3(pattern,pathModule),{dot:!0,nocase:!/[A-Z]/u.test(pattern)})}var findSchema=typebox_exports.Object({pattern:typebox_exports.String({description:"Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'"}),path:typebox_exports.Optional(typebox_exports.String({description:"Directory to search in (default: current directory)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of results (default: 1000)"}))}),findToolSystemPromptContribution={snippet:"Find files by glob pattern (respects .gitignore)",guidelines:[]},DEFAULT_LIMIT=1e3,defaultFindOperations={exists:pathExists,glob:()=>[]};function createFindToolDefinition(cwd,options){let customOps=options?.operations;return{name:"find",label:"find",description:`Search for files by glob pattern. Returns matching file paths relative to the search directory. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} results or ${51200/1024}KB (whichever is hit first).`,promptSnippet:findToolSystemPromptContribution.snippet,parameters:findSchema,async execute(_toolCallId,{pattern,path:searchDir,limit},signal,_onUpdate,ctx){return new Promise((resolve20,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let settled=!1,stopChild,settle=fn=>{settled||(settled=!0,signal?.removeEventListener("abort",onAbort),stopChild=void 0,fn())},onAbort=()=>{stopChild?.(),settle(()=>reject(new Error("Operation aborted")))};signal?.addEventListener("abort",onAbort,{once:!0}),(async()=>{try{let searchPath=resolveToCwd(searchDir||".",ctx?.cwd||cwd),effectiveLimit=limit??DEFAULT_LIMIT,ops=customOps??defaultFindOperations;if(customOps?.glob){if(!await ops.exists(searchPath)){settle(()=>reject(new Error(`Path not found: ${searchPath}`)));return}if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let results=await ops.glob(pattern,searchPath,{ignore:["**/node_modules/**","**/.git/**"],limit:effectiveLimit});if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}if(results.length===0){settle(()=>resolve20({content:[{type:"text",text:"No files found matching pattern"}],details:void 0}));return}let relativized=results.map(p=>relativizeFindResultPath(p,searchPath)),resultLimitReached=relativized.length>=effectiveLimit,rawOutput=relativized.join(`
|
|
956
927
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),resultOutput=truncation.content,details={},notices=[];resultLimitReached&&(notices.push(`${effectiveLimit} results limit reached`),details.resultLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(resultOutput+=`
|
|
957
928
|
|
|
958
|
-
[${notices.join(". ")}]`),settle(()=>resolve20({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}));return}let fdPath=await ensureTool("fd");if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}if(!fdPath){settle(()=>reject(new Error("fd is not available and could not be downloaded")));return}let args=["--glob","--color=never","--hidden"],needsWindowsPathFilter=process.platform==="win32"&&pattern.includes("/"),insideGitRepo=!1;for(let current=searchPath;;){if(await pathExists(path8.join(current,".git"))){insideGitRepo=!0;break}let parent=path8.dirname(current);if(parent===current)break;current=parent}insideGitRepo||args.push("--no-require-git"),needsWindowsPathFilter||args.push("--max-results",String(effectiveLimit));let effectivePattern=pattern;pattern.includes("/")&&(needsWindowsPathFilter?effectivePattern="**":(args.push("--full-path"),!pattern.startsWith("/")&&!pattern.startsWith("**/")&&pattern!=="**"&&(effectivePattern=`**/${pattern}`)),process.platform==="win32"&&(effectivePattern=effectivePattern.replaceAll("/",String.raw`[/\\]`))),args.push("--",effectivePattern,searchPath);let child=
|
|
929
|
+
[${notices.join(". ")}]`),settle(()=>resolve20({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}));return}let fdPath=await ensureTool("fd");if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}if(!fdPath){settle(()=>reject(new Error("fd is not available and could not be downloaded")));return}let args=["--glob","--color=never","--hidden"],needsWindowsPathFilter=process.platform==="win32"&&pattern.includes("/"),insideGitRepo=!1;for(let current=searchPath;;){if(await pathExists(path8.join(current,".git"))){insideGitRepo=!0;break}let parent=path8.dirname(current);if(parent===current)break;current=parent}insideGitRepo||args.push("--no-require-git"),needsWindowsPathFilter||args.push("--max-results",String(effectiveLimit));let effectivePattern=pattern;pattern.includes("/")&&(needsWindowsPathFilter?effectivePattern="**":(args.push("--full-path"),!pattern.startsWith("/")&&!pattern.startsWith("**/")&&pattern!=="**"&&(effectivePattern=`**/${pattern}`)),process.platform==="win32"&&(effectivePattern=effectivePattern.replaceAll("/",String.raw`[/\\]`))),args.push("--",effectivePattern,searchPath);let child=spawn4(fdPath,args,{stdio:["ignore","pipe","pipe"]}),rl=createInterface2({input:child.stdout}),stderr="",lines=[];stopChild=()=>{child.killed||child.kill()};let cleanup=()=>{rl.close()};child.stderr?.on("data",chunk=>{stderr+=chunk.toString()}),rl.on("line",line=>{needsWindowsPathFilter&&(lines.length>=effectiveLimit||!matchesFindResultPath(line,searchPath,pattern))||(lines.push(line),needsWindowsPathFilter&&lines.length>=effectiveLimit&&stopChild?.())}),child.on("error",error=>{cleanup(),settle(()=>reject(new Error(`Failed to run fd: ${error.message}`)))}),child.on("close",code=>{if(cleanup(),signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let output=lines.join(`
|
|
959
930
|
`);if(code!==0){let errorMsg=stderr.trim()||`fd exited with code ${code}`;if(!output){settle(()=>reject(new Error(errorMsg)));return}}if(!output){settle(()=>resolve20({content:[{type:"text",text:"No files found matching pattern"}],details:void 0}));return}let relativized=[];for(let rawLine of lines){let line=rawLine.replace(/\r$/,"").trim();line&&relativized.push(relativizeFindResultPath(line,searchPath))}let resultLimitReached=relativized.length>=effectiveLimit,rawOutput=relativized.join(`
|
|
960
931
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),resultOutput=truncation.content,details={},notices=[];resultLimitReached&&(notices.push(`${effectiveLimit} results limit reached. Use limit=${effectiveLimit*2} for more, or refine pattern`),details.resultLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(resultOutput+=`
|
|
961
932
|
|
|
962
|
-
[${notices.join(". ")}]`),settle(()=>resolve20({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}))})}catch(e){if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let error=e instanceof Error?e:new Error(String(e));settle(()=>reject(error))}})()})},...findRenderers}}function createFindTool(cwd,options){return wrapToolDefinition(createFindToolDefinition(cwd,options))}import{readFile as fsReadFile2,stat as fsStat}from"node:fs/promises";import{createInterface as createInterface3}from"node:readline";import{spawn as
|
|
933
|
+
[${notices.join(". ")}]`),settle(()=>resolve20({content:[{type:"text",text:resultOutput}],details:Object.keys(details).length>0?details:void 0}))})}catch(e){if(signal?.aborted){settle(()=>reject(new Error("Operation aborted")));return}let error=e instanceof Error?e:new Error(String(e));settle(()=>reject(error))}})()})},...findRenderers}}function createFindTool(cwd,options){return wrapToolDefinition(createFindToolDefinition(cwd,options))}import{readFile as fsReadFile2,stat as fsStat}from"node:fs/promises";import{createInterface as createInterface3}from"node:readline";import{spawn as spawn5}from"child_process";import path9 from"path";function formatGrepCall(args,theme2){let pattern=str(args?.pattern),rawPath=str(args?.path),path14=rawPath!==null?shortenPath2(rawPath||"."):null,glob=str(args?.glob),limit=args?.limit,invalidArg=invalidArgText(theme2),text2=theme2.fg("toolTitle",theme2.bold("grep"))+" "+(pattern===null?invalidArg:theme2.fg("accent",`/${pattern||""}/`))+theme2.fg("toolOutput",` in ${path14===null?invalidArg:path14}`);glob&&(text2+=theme2.fg("toolOutput",` (${glob})`));let flags=[];return args?.ignoreCase===!0&&flags.push("-i"),args?.literal===!0&&flags.push("-F"),typeof args?.context=="number"&&flags.push(`-C ${args.context}`),flags.length>0&&(text2+=theme2.fg("toolOutput",` (${flags.join(" ")})`)),limit!==void 0&&(text2+=theme2.fg("toolOutput",` limit ${limit}`)),text2}function formatGrepResult(result2,options,theme2,showImages){let output=getTextOutput(result2,showImages).trim(),text2="";if(output){let lines=output.split(`
|
|
963
934
|
`),maxLines=options.expanded?lines.length:15,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
964
935
|
${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
965
936
|
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
@@ -967,7 +938,7 @@ ${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
|
967
938
|
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var grepRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatGrepCall(args,theme2)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatGrepResult(result2,options,theme2,context.showImages)),text2}};var grepSchema=typebox_exports.Object({pattern:typebox_exports.String({description:"Search pattern (regex or literal string)"}),path:typebox_exports.Optional(typebox_exports.String({description:"Directory or file to search (default: current directory)"})),glob:typebox_exports.Optional(typebox_exports.String({description:"Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'"})),ignoreCase:typebox_exports.Optional(typebox_exports.Boolean({description:"Case-insensitive search (default: false)"})),literal:typebox_exports.Optional(typebox_exports.Boolean({description:"Treat pattern as literal string instead of regex (default: false)"})),context:typebox_exports.Optional(typebox_exports.Number({description:"Number of lines to show before and after each match (default: 0)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of matches to return (default: 100)"}))}),grepToolSystemPromptContribution={snippet:"Search file contents for patterns (respects .gitignore)",guidelines:[]},DEFAULT_LIMIT2=100,defaultGrepOperations={isDirectory:async p=>(await fsStat(p)).isDirectory(),readFile:p=>fsReadFile2(p,"utf-8")};function createGrepToolDefinition(cwd,options){let customOps=options?.operations;return{name:"grep",label:"grep",description:`Search file contents for a pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT2} matches or ${51200/1024}KB (whichever is hit first). Long lines are truncated to ${500} chars.`,promptSnippet:grepToolSystemPromptContribution.snippet,parameters:grepSchema,async execute(_toolCallId,{pattern,path:searchDir,glob,ignoreCase,literal,context,limit},signal,_onUpdate,ctx){return new Promise((resolve20,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let settled=!1,settle=fn=>{settled||(settled=!0,fn())};(async()=>{try{let rgPath2=await ensureTool("rg");if(!rgPath2){settle(()=>reject(new Error("ripgrep (rg) is not available and could not be downloaded")));return}let searchPath=resolveToCwd(searchDir||".",ctx?.cwd||cwd),ops=customOps??defaultGrepOperations,isDirectory;try{isDirectory=await ops.isDirectory(searchPath)}catch{settle(()=>reject(new Error(`Path not found: ${searchPath}`)));return}let contextValue=context&&context>0?context:0,effectiveLimit=Math.max(1,limit??DEFAULT_LIMIT2),formatPath=filePath=>{if(isDirectory){let relative13=path9.relative(searchPath,filePath);if(relative13&&!relative13.startsWith(".."))return relative13.replace(/\\/g,"/")}return path9.basename(filePath)},fileCache=new Map,getFileLines=async filePath=>{let lines=fileCache.get(filePath);if(!lines){try{lines=(await ops.readFile(filePath)).replace(/\r\n/g,`
|
|
968
939
|
`).replace(/\r/g,`
|
|
969
940
|
`).split(`
|
|
970
|
-
`)}catch{lines=[]}fileCache.set(filePath,lines)}return lines},args=["--no-config","--json","--line-number","--color=never","--hidden"];ignoreCase&&args.push("--ignore-case"),literal&&args.push("--fixed-strings"),glob&&args.push("--glob",glob),args.push("--",pattern,searchPath);let child=
|
|
941
|
+
`)}catch{lines=[]}fileCache.set(filePath,lines)}return lines},args=["--no-config","--json","--line-number","--color=never","--hidden"];ignoreCase&&args.push("--ignore-case"),literal&&args.push("--fixed-strings"),glob&&args.push("--glob",glob),args.push("--",pattern,searchPath);let child=spawn5(rgPath2,args,{stdio:["ignore","pipe","pipe"]}),rl=createInterface3({input:child.stdout}),stderr="",matchCount=0,matchLimitReached=!1,linesTruncated=!1,aborted=!1,killedDueToLimit=!1,outputLines=[],cleanup=()=>{rl.close(),signal?.removeEventListener("abort",onAbort)},stopChild=(dueToLimit=!1)=>{child.killed||(killedDueToLimit=dueToLimit,child.kill())},onAbort=()=>{aborted=!0,stopChild()};signal?.addEventListener("abort",onAbort,{once:!0}),child.stderr?.on("data",chunk=>{stderr+=chunk.toString()});let formatBlock=async(filePath,lineNumber)=>{let relativePath=formatPath(filePath),lines=await getFileLines(filePath);if(!lines.length)return[`${relativePath}:${lineNumber}: (unable to read file)`];let block=[],start=contextValue>0?Math.max(1,lineNumber-contextValue):lineNumber,end=contextValue>0?Math.min(lines.length,lineNumber+contextValue):lineNumber;for(let current=start;current<=end;current++){let sanitized=(lines[current-1]??"").replace(/\r/g,""),isMatchLine=current===lineNumber,{text:truncatedText,wasTruncated}=truncateLine(sanitized);wasTruncated&&(linesTruncated=!0),isMatchLine?block.push(`${relativePath}:${current}: ${truncatedText}`):block.push(`${relativePath}-${current}- ${truncatedText}`)}return block},matches=[];rl.on("line",line=>{if(!line.trim()||matchCount>=effectiveLimit)return;let event;try{event=JSON.parse(line)}catch{return}if(event.type==="match"){matchCount++;let filePath=event.data?.path?.text,lineNumber=event.data?.line_number,lineText=event.data?.lines?.text;filePath&&typeof lineNumber=="number"&&matches.push({filePath,lineNumber,lineText}),matchCount>=effectiveLimit&&(matchLimitReached=!0,stopChild(!0))}}),child.on("error",error=>{cleanup(),settle(()=>reject(new Error(`Failed to run ripgrep: ${error.message}`)))}),child.on("close",async code=>{if(cleanup(),aborted){settle(()=>reject(new Error("Operation aborted")));return}if(!killedDueToLimit&&code!==0&&code!==1){let errorMsg=stderr.trim()||`ripgrep exited with code ${code}`;settle(()=>reject(new Error(errorMsg)));return}if(matchCount===0){settle(()=>resolve20({content:[{type:"text",text:"No matches found"}],details:void 0}));return}for(let match2 of matches)if(contextValue===0&&match2.lineText!==void 0){let relativePath=formatPath(match2.filePath),sanitized=match2.lineText.replace(/\r\n/g,`
|
|
971
942
|
`).replace(/\r/g,"").replace(/\n$/,""),{text:truncatedText,wasTruncated}=truncateLine(sanitized);wasTruncated&&(linesTruncated=!0),outputLines.push(`${relativePath}:${match2.lineNumber}: ${truncatedText}`)}else{let block=await formatBlock(match2.filePath,match2.lineNumber);outputLines.push(...block)}let rawOutput=outputLines.join(`
|
|
972
943
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),output=truncation.content,details={},notices=[];matchLimitReached&&(notices.push(`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit*2} for more, or refine pattern`),details.matchLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),linesTruncated&&(notices.push(`Some lines truncated to ${500} chars. Use read tool to see full lines`),details.linesTruncated=!0),notices.length>0&&(output+=`
|
|
973
944
|
|
|
@@ -979,10 +950,39 @@ ${displayLines.map(line=>theme2.fg("toolOutput",line)).join(`
|
|
|
979
950
|
${theme2.fg("warning",`[Truncated: ${warnings.join(", ")}]`)}`}return text2}var lsRenderers={renderCall(args,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsCall(args,theme2,context.cwd)),text2},renderResult(result2,options,theme2,context){let text2=context.lastComponent??new Text("",0,0);return text2.setText(formatLsResult(result2,options,theme2,context.showImages)),text2}};var lsSchema=typebox_exports.Object({path:typebox_exports.Optional(typebox_exports.String({description:"Directory to list (default: current directory)"})),limit:typebox_exports.Optional(typebox_exports.Number({description:"Maximum number of entries to return (default: 500)"}))}),lsToolSystemPromptContribution={snippet:"List directory contents",guidelines:[]},DEFAULT_LIMIT3=500,defaultLsOperations={exists:pathExists,stat:fsStat2,readdir:fsReaddir};function createLsToolDefinition(cwd,options){let ops=options?.operations??defaultLsOperations;return{name:"ls",label:"ls",description:`List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT3} entries or ${51200/1024}KB (whichever is hit first).`,promptSnippet:lsToolSystemPromptContribution.snippet,parameters:lsSchema,async execute(_toolCallId,{path:path14,limit},signal,_onUpdate,ctx){return new Promise((resolve20,reject)=>{if(signal?.aborted){reject(new Error("Operation aborted"));return}let onAbort=()=>reject(new Error("Operation aborted"));signal?.addEventListener("abort",onAbort,{once:!0}),(async()=>{try{let dirPath=resolveToCwd(path14||".",ctx?.cwd||cwd),effectiveLimit=limit??DEFAULT_LIMIT3;if(!await ops.exists(dirPath)){reject(new Error(`Path not found: ${dirPath}`));return}if(!(await ops.stat(dirPath)).isDirectory()){reject(new Error(`Not a directory: ${dirPath}`));return}let entries;try{entries=await ops.readdir(dirPath)}catch(e){reject(new Error(`Cannot read directory: ${e.message}`));return}entries.sort((a,b2)=>a.toLowerCase().localeCompare(b2.toLowerCase()));let results=[],entryLimitReached=!1;for(let entry of entries){if(results.length>=effectiveLimit){entryLimitReached=!0;break}let fullPath=nodePath.join(dirPath,entry),suffix="";try{(await ops.stat(fullPath)).isDirectory()&&(suffix="/")}catch{continue}results.push(entry+suffix)}if(signal?.removeEventListener("abort",onAbort),results.length===0){resolve20({content:[{type:"text",text:"(empty directory)"}],details:void 0});return}let rawOutput=results.join(`
|
|
980
951
|
`),truncation=truncateHead(rawOutput,{maxLines:Number.MAX_SAFE_INTEGER}),output=truncation.content,details={},notices=[];entryLimitReached&&(notices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit*2} for more`),details.entryLimitReached=effectiveLimit),truncation.truncated&&(notices.push(`${formatSize(51200)} limit reached`),details.truncation=truncation),notices.length>0&&(output+=`
|
|
981
952
|
|
|
982
|
-
[${notices.join(". ")}]`),resolve20({content:[{type:"text",text:output}],details:Object.keys(details).length>0?details:void 0})}catch(e){signal?.removeEventListener("abort",onAbort),reject(e)}})()})},...lsRenderers}}function createLsTool(cwd,options){return wrapToolDefinition(createLsToolDefinition(cwd,options))}var
|
|
983
|
-
|
|
953
|
+
[${notices.join(". ")}]`),resolve20({content:[{type:"text",text:output}],details:Object.keys(details).length>0?details:void 0})}catch(e){signal?.removeEventListener("abort",onAbort),reject(e)}})()})},...lsRenderers}}function createLsTool(cwd,options){return wrapToolDefinition(createLsToolDefinition(cwd,options))}function truncateToVisualLines(text2,maxVisualLines,width,paddingX=0,keep="end"){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=keep==="start"?allVisualLines.slice(0,maxVisualLines):allVisualLines.slice(-maxVisualLines),skippedCount=allVisualLines.length-maxVisualLines;return{visualLines:truncatedLines,skippedCount}}var VisualLinePreview=class{constructor(options){this.options=options}render(width){if(this.cachedLines===void 0||this.cachedWidth!==width){let{text:text2,maxVisualLines,keep,formatHint}=this.options,preview=truncateToVisualLines(text2,maxVisualLines,width,0,keep),lines=preview.visualLines;if(preview.skippedCount>0){let hint=truncateToWidth(formatHint(preview.skippedCount),width,"...");this.cachedLines=keep==="start"?[...lines,hint]:[hint,...lines]}else this.cachedLines=lines;this.cachedWidth=width}return this.cachedLines}invalidate(){this.cachedWidth=void 0,this.cachedLines=void 0}};import{constants as constants6}from"node:fs";import{access as fsAccess2}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn6}from"child_process";import{closeSync as closeSync2,openSync as openSync2,writeSync as writeSync2}from"node:fs";import{open as open3}from"node:fs/promises";import{randomBytes}from"node:crypto";import{createWriteStream as createWriteStream2}from"node:fs";import{writeFile}from"node:fs/promises";import{tmpdir as tmpdir2}from"node:os";import{join as join21}from"node:path";var OUTPUT_FILE_MODE=384;function createOutputFilePath(prefix,extension){return join21(tmpdir2(),`${prefix}-${randomBytes(8).toString("hex")}${extension}`)}async function writeOutputFile(prefix,extension,data){let path14=createOutputFilePath(prefix,extension);return await writeFile(path14,data,{mode:OUTPUT_FILE_MODE,flag:"wx"}),path14}function createOutputFileStream(prefix,extension){let path14=createOutputFilePath(prefix,extension);return{path:path14,stream:createWriteStream2(path14,{mode:OUTPUT_FILE_MODE,flags:"wx"})}}function byteLength(text2){return Buffer.byteLength(text2,"utf-8")}var OutputAccumulator=class{constructor(options={}){if(this.decoder=new TextDecoder,this.rawChunks=[],this.tailText="",this.tailBytes=0,this.tailStartsAtLineBoundary=!0,this.totalRawBytes=0,this.totalDecodedBytes=0,this.completedLines=0,this.totalLines=0,this.currentLineBytes=0,this.hasOpenLine=!1,this.finished=!1,this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"pi-output",options.persistFromStart){let path14=createOutputFilePath(this.tempFilePrefix,".log");this.tempFileFd=openSync2(path14,"wx",384),this.tempFilePath=path14}}append(data){if(this.finished)throw new Error("Cannot append to a finished output accumulator");if(this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),this.tempFileFd!==void 0){let offset=0;for(;offset<data.length;){let written=writeSync2(this.tempFileFd,data,offset,data.length-offset);if(written===0)throw new Error("Output file write made no progress");offset+=written}}else this.tempFileStream||this.shouldUseTempFile()?(this.ensureTempFile(),this.tempFileStream?.write(data)):data.length>0&&this.rawChunks.push(data)}finish(){this.finished||(this.finished=!0,this.appendDecodedText(this.decoder.decode()),this.shouldUseTempFile()&&this.ensureTempFile())}snapshot(options={}){let maxBytes=Math.min(this.maxBytes,options.maxBytes??this.maxBytes),tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}getTotalBytes(){return this.totalRawBytes}async closeTempFile(){if(this.tempFileFd!==void 0){let fd=this.tempFileFd;this.tempFileFd=void 0,closeSync2(fd)}if(!this.tempFileStream)return;let stream2=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve20,reject)=>{let onError=error=>{stream2.off("finish",onFinish),reject(error)},onFinish=()=>{stream2.off("error",onError),resolve20()};stream2.once("error",onError),stream2.once("finish",onFinish),stream2.end()})}async readFullOutput(maxBytes){if(!this.tempFilePath)return{content:new TextDecoder().decode(Buffer.concat(this.rawChunks)),truncated:!1};let file=await open3(this.tempFilePath,"r");try{let size=(await file.stat()).size;if(size<=maxBytes)return{content:new TextDecoder().decode(await file.readFile()),truncated:!1};let headBytes=Math.floor(maxBytes/2),tailBytes=maxBytes-headBytes,head=Buffer.alloc(headBytes),tail2=Buffer.alloc(tailBytes);await file.read(head,0,headBytes,0),await file.read(tail2,0,tailBytes,size-tailBytes);let headText=new TextDecoder().decode(head,{stream:!0}),tailStart=0;for(;tailStart<tail2.length&&(tail2[tailStart]&192)===128;)tailStart++;let tailText=new TextDecoder().decode(tail2.subarray(tailStart)),omitted=size-headBytes-tailBytes;return{content:`${headText}
|
|
954
|
+
|
|
955
|
+
[... ${omitted} bytes omitted ...]
|
|
956
|
+
|
|
957
|
+
${tailText}`,truncated:!0}}finally{await file.close()}}getLastLineBytes(){return this.currentLineBytes}appendDecodedText(text2){if(text2.length===0)return;let bytes=byteLength(text2);this.totalDecodedBytes+=bytes,this.tailText+=text2,this.tailBytes+=bytes,this.tailBytes>this.maxRollingBytes*2&&this.trimTail();let newlines=0,lastNewline=-1;for(let i=text2.indexOf(`
|
|
958
|
+
`);i!==-1;i=text2.indexOf(`
|
|
959
|
+
`,i+1))newlines++,lastNewline=i;if(newlines===0)this.currentLineBytes+=bytes,this.hasOpenLine=!0;else{this.completedLines+=newlines;let tail2=text2.slice(lastNewline+1);this.currentLineBytes=byteLength(tail2),this.hasOpenLine=tail2.length>0}this.totalLines=this.completedLines+(this.hasOpenLine?1:0)}trimTail(){let buffer=Buffer.from(this.tailText,"utf-8");if(buffer.length<=this.maxRollingBytes){this.tailBytes=buffer.length;return}let start=buffer.length-this.maxRollingBytes;for(;start<buffer.length&&(buffer[start]&192)===128;)start++;this.tailStartsAtLineBoundary=start===0?this.tailStartsAtLineBoundary:buffer[start-1]===10,this.tailText=buffer.subarray(start).toString("utf-8"),this.tailBytes=byteLength(this.tailText)}getSnapshotText(){if(this.tailStartsAtLineBoundary)return this.tailText;let firstNewline=this.tailText.indexOf(`
|
|
960
|
+
`);return firstNewline===-1?this.tailText:this.tailText.slice(firstNewline+1)}shouldUseTempFile(){return this.totalRawBytes>this.maxBytes||this.totalDecodedBytes>this.maxBytes||this.totalLines>this.maxLines}ensureTempFile(){if(this.tempFilePath)return;let{path:path14,stream:stream2}=createOutputFileStream(this.tempFilePrefix,".log");this.tempFilePath=path14,this.tempFileStream=stream2;for(let chunk of this.rawChunks)this.tempFileStream.write(chunk);this.rawChunks=[]}};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)]}},shellTimerHooked=Symbol("shellTimerHooked");function ensureShellTimer(context){startToolTimer(context);let state2=context.state;if(state2[shellTimerHooked])return;state2[shellTimerHooked]=!0;let previousDispose=state2.dispose;state2.dispose=()=>{try{previousDispose?.call(state2)}finally{clearInterval(state2.interval),state2.interval=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(`
|
|
961
|
+
`)}function formatFullShellCall(command,timeout,config){let commandDisplay=command===null?invalidArgText(theme):command?styleShellCommand(command,config):theme.fg("toolOutput","...");return formatShellPrompt(config.prompt)+commandDisplay+formatShellTimeout(timeout)}function fitCollapsedShellCall(body2,timeout,width,suffix,config){let prompt=formatShellPrompt(config.prompt),timeoutSuffix=formatShellTimeout(timeout),bodyWidth=Math.max(0,width-visibleWidth(prompt)-visibleWidth(suffix)-visibleWidth(timeoutSuffix)),fittedBody=truncateToWidth(body2,bodyWidth,"");return truncateToWidth(prompt+fittedBody+suffix+timeoutSuffix,width,"\u2026")}function formatTruncatedShellCall(command,timeout,width,config){if(command===null)return truncateToWidth(formatFullShellCall(command,timeout,config),width,"\u2026");if(!command)return formatFullShellCall(command,timeout,config);let physicalLines=command.split(/\r?\n/).filter(line=>line.trim()),firstNonEmptyLine=physicalLines[0]?.trim()??command.trim(),hiddenLines=Math.max(0,physicalLines.length-1),suffix=hiddenLines>0?theme.fg("muted",` (+${hiddenLines} line${hiddenLines===1?"":"s"})`):theme.fg("muted"," \u2026");return fitCollapsedShellCall(styleShellCommand(firstNonEmptyLine,config),timeout,width,suffix,config)}function rebuildBashResultRenderComponent(component,result2,options,showImages,timerText,submittedAsBackground){component.clear();let background=result2.details?.background,output=background?.kind==="background"?`${submittedAsBackground?"Running in the background":"Moved to background"} \xB7 ${background.taskId}`:getTextOutput(result2,showImages).trim(),truncation=result2.details?.truncation,fullOutputPath=result2.details?.fullOutputPath;if(!options.isPartial&&truncation?.truncated&&fullOutputPath&&output.endsWith("]")){let footerStart=output.lastIndexOf(`
|
|
962
|
+
|
|
963
|
+
[`);footerStart!==-1&&output.slice(footerStart).includes(fullOutputPath)&&(output=output.slice(0,footerStart).trimEnd())}if(output){let styledOutput=output.split(`
|
|
964
|
+
`).map(line=>theme.fg("toolOutput",line)).join(`
|
|
965
|
+
`);options.expanded?component.addChild(new Text(`
|
|
966
|
+
${styledOutput}`,0,0)):(component.addChild(new Spacer(1)),component.addChild(new VisualLinePreview({text:styledOutput,maxVisualLines:BASH_PREVIEW_LINES,keep:"end",formatHint:hidden=>theme.fg("muted",`... (${hidden} earlier lines,`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`})))}if(truncation?.truncated||fullOutputPath){let warnings=[];fullOutputPath&&warnings.push(`Full output: ${fullOutputPath}`),truncation?.truncated&&(truncation.truncatedBy==="lines"?warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`):warnings.push(`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes??51200)} limit)`)),component.addChild(new Text(`
|
|
967
|
+
${theme.fg("warning",`[${warnings.join(". ")}]`)}`,0,0))}timerText&&component.addChild(new Text(`
|
|
968
|
+
${theme.fg("muted",timerText)}`,0,0))}function createShellRenderers(config){return{renderCall(args,_theme,context){ensureShellTimer(context);let component=context.lastComponent??new BashCallRenderComponent(config);return component.update(args,context.expanded),component},renderResult(result2,options,_theme,context){ensureShellTimer(context);let timerText=toolTimerText(context,options.isPartial),component=context.lastComponent??new Container,submitted=context.args?.background===!0;return rebuildBashResultRenderComponent(component,result2,options,context.showImages,timerText,submitted),component.invalidate(),component}}}var MAX_TIMEOUT_MS=2147483647,STRUCTURED_OUTPUT_MAX_BYTES=1024*1024,MAX_TIMEOUT_SECONDS=MAX_TIMEOUT_MS/1e3;function resolveTimeoutMs(timeout){if(timeout===void 0)return;if(!Number.isFinite(timeout)||timeout<=0)throw new Error("Invalid timeout: must be a finite number of seconds");let timeoutMs=timeout*1e3;if(timeoutMs>MAX_TIMEOUT_MS)throw new Error(`Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`);return timeoutMs}var bashSchema=typebox_exports.Object({command:typebox_exports.String({description:"Shell command to execute"}),timeout:typebox_exports.Optional(typebox_exports.Number({description:"Timeout in seconds (optional, no default timeout)"}))}),bashToolSystemPromptContribution={snippet:"Execute bash commands (ls, grep, find, etc.)",guidelines:["You can inspect PI_* environment variables for current model and session details."]},bashOutputSchema=typebox_exports.Object({output:typebox_exports.String({description:"Combined stdout and stderr, possibly truncated"}),truncated:typebox_exports.Boolean(),full_output_path:typebox_exports.Optional(typebox_exports.String({description:"Full output, when truncated"})),exit_code:typebox_exports.Number(),wall_time_seconds:typebox_exports.Number()});function createLocalShellOperations(shellName,resolveShellConfig){return{exec:async(command,cwd,{onData,signal,timeout,env:env2})=>{let timeoutMs=resolveTimeoutMs(timeout);if(signal?.aborted)throw new Error("aborted");let shellConfig=resolveShellConfig();try{await fsAccess2(cwd,constants6.F_OK)}catch{throw new Error(`Working directory does not exist: ${cwd}
|
|
969
|
+
Cannot execute ${shellName} commands.`)}let commandFromStdin=shellConfig.commandTransport==="stdin",child=spawn6(shellConfig.shell,commandFromStdin?shellConfig.args:[...shellConfig.args,command],{cwd,detached:process.platform!=="win32",env:env2??getShellEnv(),stdio:[commandFromStdin?"pipe":"ignore","pipe","pipe"],windowsHide:!0});commandFromStdin&&(child.stdin?.on("error",()=>{}),child.stdin?.end(command)),child.pid&&trackDetachedChildPid(child.pid);let timedOut=!1,timeoutHandle,onAbort=()=>{child.pid&&killProcessTree(child.pid)};try{timeoutMs!==void 0&&(timeoutHandle=setTimeout(()=>{timedOut=!0,child.pid&&killProcessTree(child.pid)},timeoutMs)),child.stdout?.on("data",onData),child.stderr?.on("data",onData),signal&&(signal.aborted?onAbort():signal.addEventListener("abort",onAbort,{once:!0}));let exitCode=await waitForChildProcess(child);if(signal?.aborted)throw new Error("aborted");if(timedOut)throw new Error(`timeout:${timeout}`);let signalCode=child.signalCode;return{exitCode:exitCode??(signalCode?128+(osConstants.signals[signalCode]??0):1)}}finally{child.pid&&untrackDetachedChildPid(child.pid),timeoutHandle&&clearTimeout(timeoutHandle),signal&&signal.removeEventListener("abort",onAbort)}}}}function resolveSpawnContext(command,cwd,spawnHook,exposeSessionEnvironment,ctx){let env2={...getShellEnv()};if(delete env2.PI_SESSION_ID,delete env2.PI_SESSION_FILE,delete env2.PI_PROVIDER,delete env2.PI_MODEL,delete env2.PI_REASONING_LEVEL,exposeSessionEnvironment&&ctx){let model=ctx.model;env2.PI_SESSION_ID=ctx.sessionManager.getSessionId();let sessionFile=ctx.sessionManager.getSessionFile();sessionFile&&(env2.PI_SESSION_FILE=sessionFile),model&&(env2.PI_PROVIDER=model.provider,env2.PI_MODEL=model.id),ctx.thinkingLevel&&(env2.PI_REASONING_LEVEL=ctx.thinkingLevel)}let baseContext={command,cwd,env:env2};return spawnHook?spawnHook(baseContext):baseContext}var bashToolConfig={name:"bash",label:"bash",shellName:"bash",prompt:"$",promptSnippet:bashToolSystemPromptContribution.snippet,promptGuidelines:bashToolSystemPromptContribution.guidelines,tempFilePrefix:"pi-bash"};var CMD_NUL_REDIRECT_REGEX=/(\d?&?>+\s*)[Nn][Uu][Ll](?=\s|$|[|&;)\n])/g;function rewriteCmdNulRedirects(command){return command.replace(CMD_NUL_REDIRECT_REGEX,"$1/dev/null")}function normalizeLocalBashCommand(command,platform3=process.platform){return platform3==="win32"?rewriteCmdNulRedirects(command):command}function createLocalBashOperations(options){let operations=createLocalShellOperations("bash",()=>getShellConfig(options?.shellPath));return{exec:(command,cwd,execOptions)=>operations.exec(normalizeLocalBashCommand(command),cwd,execOptions)}}import{unlink as unlink2}from"node:fs/promises";var MAX_BACKGROUND_OUTPUT_BYTES=20*1024*1024;function shellFailure(error){return error instanceof Error&&error.message==="aborted"?{status:"cancelled",error:"Command aborted"}:error instanceof Error&&error.message.startsWith("timeout:")?{status:"timeout",error:`Command timed out after ${error.message.split(":")[1]} seconds`}:{status:"failed",error:boundText(error instanceof Error?error.message:String(error),4096)}}function formatOutput(output,snapshot,managed,emptyText){let truncation=snapshot.truncation,text2=snapshot.content||emptyText,details=managed?{fullOutputPath:snapshot.fullOutputPath}:void 0;if(truncation.truncated){details={truncation,fullOutputPath:snapshot.fullOutputPath};let startLine=truncation.totalLines-truncation.outputLines+1,endLine=truncation.totalLines;if(truncation.lastLinePartial){let lastLineSize=formatSize(output.getLastLineBytes());text2+=`
|
|
970
|
+
|
|
971
|
+
[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${snapshot.fullOutputPath}]`}else truncation.truncatedBy==="lines"?text2+=`
|
|
972
|
+
|
|
973
|
+
[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${snapshot.fullOutputPath}]`:text2+=`
|
|
974
|
+
|
|
975
|
+
[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(truncation.maxBytes)} limit). Full output: ${snapshot.fullOutputPath}]`}return{text:text2,details}}async function runShellCommand(options){let{operations,context,managed,signal,timeout}=options,output=new OutputAccumulator({tempFilePrefix:options.tempFilePrefix,persistFromStart:!!managed}),startedAt=performance.now(),outputError,acceptingOutput=!0,unsubscribe,updateTimer,updateDirty=!1,lastUpdateAt=0,failOutput=error=>{if(!outputError){outputError=error instanceof Error?error:new Error(String(error));try{managed&&managed.control.requestCancel()}catch{}}},checkOutputLimit=()=>{managed?.control.mode==="background"&&output.getTotalBytes()>MAX_BACKGROUND_OUTPUT_BYTES&&failOutput(new Error("Background command exceeded the 20 MiB output limit"))},snapshot=()=>output.snapshot({persistIfTruncated:!0,maxBytes:managed?.control.mode==="background"?40*1024:void 0}),publish=snapshot2=>{let result2={content:snapshot2?[{type:"text",text:snapshot2.content}]:[],details:snapshot2?{truncation:snapshot2.truncation.truncated?snapshot2.truncation:void 0,fullOutputPath:snapshot2.fullOutputPath}:void 0};managed?managed.control.publish(result2):options.onUpdate?.(result2)},emitOutputUpdate=()=>{!managed&&!options.onUpdate||!updateDirty||(updateDirty=!1,lastUpdateAt=Date.now(),publish(snapshot()))},clearUpdateTimer=()=>{updateTimer&&clearTimeout(updateTimer),updateTimer=void 0},scheduleOutputUpdate=()=>{if(!managed&&!options.onUpdate)return;updateDirty=!0;let delay2=BASH_UPDATE_THROTTLE_MS-(Date.now()-lastUpdateAt);delay2<=0?(clearUpdateTimer(),emitOutputUpdate()):updateTimer??=setTimeout(()=>{updateTimer=void 0,emitOutputUpdate()},delay2)},handleData=data=>{if(!(!acceptingOutput||outputError))try{if(managed?.control.mode==="background"&&output.getTotalBytes()+data.length>MAX_BACKGROUND_OUTPUT_BYTES){let remaining=Math.max(0,MAX_BACKGROUND_OUTPUT_BYTES-output.getTotalBytes());output.append(data.subarray(0,remaining)),failOutput(new Error("Background command exceeded the 20 MiB output limit"))}else output.append(data);scheduleOutputUpdate()}catch(error){if(!managed)throw error;failOutput(error)}};try{if(managed){let path14=output.snapshot().fullOutputPath,cleanup=async()=>{await output.closeTempFile(),await unlink2(path14).catch(error=>{if(error.code!=="ENOENT")throw error})};try{managed.control.setOutputPath(path14,cleanup)}catch(error){throw await cleanup(),error}unsubscribe=managed.control.onModeChange(checkOutputLimit)}publish();let failure,exitCode;try{if(signal?.aborted)throw new Error("aborted");let execution=operations.exec(context.command,context.cwd,{onData:handleData,signal,timeout,env:context.env});managed?.control.accept(),{exitCode}=await execution,exitCode===null?failure={status:"failed",error:"Command terminated without an exit code"}:exitCode!==0&&(failure={status:"failed",error:`Command exited with code ${exitCode}`})}catch(error){failure=shellFailure(error)}acceptingOutput=!1,output.finish(),clearUpdateTimer(),managed?publish(snapshot()):emitOutputUpdate();let final=snapshot();await output.closeTempFile(),outputError&&(failure={status:"failed",error:boundText(outputError.message,4096)});let{text:text2,details}=formatOutput(output,final,!!managed,failure?"":"(no output)"),fullOutput=typeof exitCode=="number"&&!outputError?await output.readFullOutput(1024*1024):void 0;return{status:failure?.status,error:failure?.error,...exitCode!==void 0?{exitCode}:{},result:{...fullOutput&&typeof exitCode=="number"?{structuredContent:{output:fullOutput.content,truncated:fullOutput.truncated,...fullOutput.truncated&&final.fullOutputPath?{full_output_path:final.fullOutputPath}:{},exit_code:exitCode,wall_time_seconds:Math.round((performance.now()-startedAt)/100)/10},...failure?{isError:!0}:{}}:{},content:[{type:"text",text:failure?`${text2?`${text2}
|
|
976
|
+
|
|
977
|
+
`:""}${failure.error}`:text2}],details}}}finally{acceptingOutput=!1,unsubscribe?.(),clearUpdateTimer(),await output.closeTempFile()}}var bashSchema2=typebox_exports.Object({command:typebox_exports.String({description:"Shell command to execute"}),timeout:typebox_exports.Optional(typebox_exports.Number({description:"Timeout in seconds (optional, no default timeout)"})),background:typebox_exports.Optional(typebox_exports.Boolean({description:"true returns a managed task ID immediately and runs the command in the background, and you are notified when it completes \u2014 do not poll for its result; omit or false to block until exit"}))}),bashToolSystemPromptContribution2={snippet:"Execute bash commands, foreground or background",guidelines:["You can inspect PI_* environment variables for current model and session details."]},bashOutputSchema2=typebox_exports.Union([typebox_exports.Object({output:typebox_exports.String({description:"Combined stdout and stderr, up to 1 MiB, keeping head and tail when truncated."}),truncated:typebox_exports.Boolean(),full_output_path:typebox_exports.Optional(typebox_exports.String()),exit_code:typebox_exports.Number(),wall_time_seconds:typebox_exports.Number()}),typebox_exports.Object({task_id:typebox_exports.String(),status:typebox_exports.String()})]);function shellToolResult(completion,managed){let status=completion.status;if(completion.result.structuredContent)return completion.result;if(status==="failed"||status==="timeout"||status==="cancelled"){let text2=completion.result.content.filter(part=>part.type==="text").map(part=>part.text).join(`
|
|
978
|
+
`),message=completion.error?text2||completion.error:`${text2?`${text2}
|
|
979
|
+
|
|
980
|
+
`:""}Command ${status}`;throw managed?new TaskExecutionError(message,status):new Error(message)}return completion.result}function createShellToolDefinition(cwd,config,options){let ops=options.operations,commandPrefix=options?.commandPrefix,exposeSessionEnvironment=options?.exposeSessionEnvironment??!0,spawnHook=options?.spawnHook;return{name:config.name,label:config.label,description:`Execute a ${config.shellName} command in the current working directory. Returns stdout and stderr, truncated to the last ${2e3} lines or ${51200/1024}KB (whichever is hit first); the full output is saved to a temp file. Optionally provide a timeout in seconds (no default). Choose the mode per call: foreground (default) blocks until the command exits \u2014 use it when your next step needs the output; background: true returns immediately with a task ID \u2014 use it for long-running work (builds, servers, watchers, big test suites) or when you have independent work to continue. A handoff is not completion: the result arrives later as an automatic completion notification; meanwhile use tasks read to inspect output, tasks wait with an ID for one task or without one for any running task, and tasks kill to stop it. Steering interrupts only a wait, never execution. Background output is limited to 20 MiB; an expired tasks wait window never stops the command.`,promptSnippet:config.promptSnippet,promptGuidelines:exposeSessionEnvironment&&config.promptGuidelines?[...config.promptGuidelines]:void 0,parameters:bashSchema2,outputSchema:bashOutputSchema2,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(toolCallId,{command,timeout,background},parentSignal,originalUpdate,ctx){let host=ctx?.tasks;if(host?.closed)throw new Error("Task service is closed");let run=async managed=>{let signal=managed?.control.signal??parentSignal;try{if(managed){if(signal?.aborted)throw new Error("Command aborted");resolveTimeoutMs(timeout)}let resolvedCommand=commandPrefix?`${commandPrefix}
|
|
981
|
+
${command}`:command,spawnContext=resolveSpawnContext(resolvedCommand,ctx?.cwd||cwd,spawnHook,exposeSessionEnvironment,ctx);return await runShellCommand({operations:ops,context:spawnContext,tempFilePrefix:config.tempFilePrefix,timeout,signal,onUpdate:originalUpdate,managed})}catch(error){throw managed?new TaskExecutionError(error instanceof Error?error.message:String(error),managed.control.signal.aborted?"cancelled":"failed"):error}};if(!host){if(background)throw new Error("Background execution is not available in this host. No command was started.");return shellToolResult(await run(),!1)}let outcome=await host.execute({kind:config.name,title:command,toolCallId,command,cwd:ctx?.cwd||cwd,background,signal:parentSignal,onUpdate:originalUpdate,run:control=>run({control})});if(outcome.kind==="result")return shellToolResult(outcome,!0);let tail2=`Task ID: ${outcome.task.id}. Status: ${outcome.task.status}. 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 tasks read to inspect output, tasks wait only when your next step is blocked on a result (one ID or any running task; prefer foreground next time in that case), or tasks kill to stop it.`,handoff=background===!0?`Command handed to background. ${tail2}`:`Command moved to the background while it was running, by the user. The execution continues unchanged \u2014 no restart, and a supplied timeout is still measured from command startup. Output produced so far is already in the log, so tasks read now returns partial output, not a fresh start. ${tail2}`;return{structuredContent:{task_id:outcome.task.id,status:outcome.task.status},content:[{type:"text",text:`${handoff}${outcome.task.outputPath?`
|
|
982
|
+
Full output: ${outcome.task.outputPath}`:""}`}],details:{background:{kind:"background",taskId:outcome.task.id},fullOutputPath:outcome.task.outputPath}}},...createShellRenderers(config)}}var bashToolConfig2={name:"bash",label:"bash",shellName:"bash",prompt:"$",promptSnippet:bashToolSystemPromptContribution2.snippet,promptGuidelines:bashToolSystemPromptContribution2.guidelines,tempFilePrefix:"pi-bash"};function createBashToolDefinition(cwd,options){return createShellToolDefinition(cwd,bashToolConfig2,{...options,operations:options?.operations??createLocalBashOperations({shellPath:options?.shellPath})})}function createBashTool(cwd,options){let definition=createBashToolDefinition(cwd,options),tool=wrapToolDefinition(definition);return Object.assign(tool,{promptSnippet:definition.promptSnippet,promptGuidelines:definition.promptGuidelines}),tool}var UTF8_OUTPUT_PREFIX=`try { [Console]::OutputEncoding=[System.Text.Encoding]::UTF8 } catch {}
|
|
983
|
+
`,powershellToolSystemPromptContribution={snippet:"Execute PowerShell commands, foreground or background",guidelines:["You can inspect PI_* environment variables for current model and session details."]};function createLocalPowerShellOperations(){let operations=createLocalShellOperations("PowerShell",getPowerShellConfig);return{exec:(command,cwd,options)=>operations.exec(`${UTF8_OUTPUT_PREFIX}${command}`,cwd,options)}}var powershellToolConfig={name:"powershell",label:"powershell",shellName:"PowerShell",prompt:"PS>",promptSnippet:powershellToolSystemPromptContribution.snippet,promptGuidelines:powershellToolSystemPromptContribution.guidelines,tempFilePrefix:"pi-powershell"};function createPowerShellToolDefinition(cwd,options){return createShellToolDefinition(cwd,powershellToolConfig,{...options,operations:options?.operations??createLocalPowerShellOperations()})}function createPowerShellTool(cwd,options){let definition=createPowerShellToolDefinition(cwd,options),tool=wrapToolDefinition(definition);return Object.assign(tool,{promptSnippet:definition.promptSnippet,promptGuidelines:definition.promptGuidelines}),tool}import{constants as constants7}from"fs";import{access as fsAccess3,readFile as fsReadFile3}from"fs/promises";function baseMimeType(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function normalizeSupportedImageMimeType(mimeType){switch(baseMimeType(mimeType)){case"image/png":return"image/png";case"image/jpeg":case"image/jpg":return"image/jpeg";case"image/gif":return"image/gif";case"image/webp":return"image/webp";default:return null}}async function normalizeImage(bytes,mimeType){let normalizedMimeType=normalizeSupportedImageMimeType(mimeType);if(normalizedMimeType)return{bytes,mimeType:normalizedMimeType};let pngBytes=await convertImageBytesToPng(bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png",convertedFrom:baseMimeType(mimeType)}:null}function conversionHint(from,to){if(!(!from||from===to))return`[Image converted from ${from} to ${to}.]`}async function processImage(bytes,mimeType,options){let autoResizeImages=options?.autoResizeImages??!0,normalized=await normalizeImage(bytes,mimeType);if(!normalized)return{ok:!1,message:"[Image omitted: could not be converted to a supported inline image format.]"};if(autoResizeImages){let resized=await resizeImage(normalized.bytes,normalized.mimeType,options?.resizeOptions);if(!resized)return{ok:!1,message:"[Image omitted: could not be resized below the inline image size limit.]"};let hints2=[],convertedHint2=conversionHint(normalized.convertedFrom,resized.mimeType);convertedHint2&&hints2.push(convertedHint2);let dimensionNote=formatDimensionNote(resized);return dimensionNote&&hints2.push(dimensionNote),{ok:!0,data:resized.data,mimeType:resized.mimeType,hints:hints2}}let hints=[],convertedHint=conversionHint(normalized.convertedFrom,normalized.mimeType);return convertedHint&&hints.push(convertedHint),{ok:!0,data:Buffer.from(normalized.bytes).toString("base64"),mimeType:normalized.mimeType,hints}}import{basename as basename6,dirname as dirname12,isAbsolute as isAbsolute3,relative as relative4,resolve as resolvePath2,sep as sep6}from"node:path";var COMPACT_RESOURCE_FILE_NAMES=new Set(["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"]);function styledReadLineRange(args,theme2){let range2=formatReadLineRange(args?.offset,args?.limit);return range2?theme2.fg("warning",range2):""}function formatReadCall(args,theme2,cwd){let pathDisplay=renderToolPath(str(args?.file_path??args?.path),theme2,cwd);return`${theme2.fg("toolTitle",theme2.bold("read"))} ${pathDisplay}${styledReadLineRange(args,theme2)}`}function trimTrailingEmptyLines(lines){let end=lines.length;for(;end>0&&lines[end-1]==="";)end--;return lines.slice(0,end)}function toPosixPath4(filePath){return filePath.split(sep6).join("/")}function getPiDocsClassification(absolutePath){let packageRoot=dirname12(getReadmePath()),relativePath=relative4(resolvePath2(packageRoot),resolvePath2(absolutePath));if(relativePath===""||relativePath===".."||relativePath.startsWith(`..${sep6}`)||isAbsolute3(relativePath))return;let label=toPosixPath4(relativePath);if(label==="README.md"||label.startsWith("docs/")||label.startsWith("examples/"))return{kind:"docs",label}}function getCompactReadClassification(args,cwd){let rawPath=str(args?.file_path??args?.path);if(!rawPath)return;let absolutePath=resolveToCwd(rawPath,cwd),fileName=basename6(absolutePath);if(fileName==="SKILL.md")return{kind:"skill",label:basename6(dirname12(absolutePath))||fileName};let docsClassification=getPiDocsClassification(absolutePath);if(docsClassification)return docsClassification;if(COMPACT_RESOURCE_FILE_NAMES.has(fileName))return{kind:"resource",label:formatPathRelativeToCwdOrAbsolute(absolutePath,cwd)}}function formatCompactReadCall(classification,args,theme2){let expandHint2=theme2.fg("dim",` (${keyText("app.tools.expand")} to expand)`);return classification.kind==="skill"?theme2.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme2.fg("customMessageText",classification.label)+styledReadLineRange(args,theme2)+expandHint2:theme2.fg("toolTitle",theme2.bold(`read ${classification.kind}`))+" "+theme2.fg("accent",classification.label)+styledReadLineRange(args,theme2)+expandHint2}function formatReadResult(args,result2,options,theme2,showImages,_cwd,isError){let rawPath=str(args?.file_path??args?.path),output=getTextOutput(result2,showImages),lang=!isError&&rawPath?getLanguageFromPath(rawPath):void 0,renderedLines=lang?highlightCode(replaceTabs2(output),lang):output.split(`
|
|
984
984
|
`),lines=trimTrailingEmptyLines(renderedLines),maxLines=options.expanded?lines.length:10,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines,text2=`
|
|
985
|
-
${displayLines.map(line=>lang?
|
|
985
|
+
${displayLines.map(line=>lang?replaceTabs2(line):theme2.fg("toolOutput",replaceTabs2(line))).join(`
|
|
986
986
|
`)}`;remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
987
987
|
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`);let truncation=result2.details?.truncation;return truncation?.truncated&&(truncation.firstLineExceedsLimit?text2+=`
|
|
988
988
|
${theme2.fg("warning",`[First line exceeds ${formatSize(truncation.maxBytes??51200)} limit]`)}`:truncation.truncatedBy==="lines"?text2+=`
|
|
@@ -1002,33 +1002,18 @@ ${nonVisionImageNote}`),content=[{type:"text",text:textNote}]}}else{let allLines
|
|
|
1002
1002
|
[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(51200)} limit). Use offset=${nextOffset} to continue.]`,details={truncation}}else if(userLimitedLines!==void 0&&startLine+userLimitedLines<allLines.length){let remaining=allLines.length-(startLine+userLimitedLines),nextOffset=startLine+userLimitedLines+1;outputText=`${truncation.content}
|
|
1003
1003
|
|
|
1004
1004
|
[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`}else outputText=truncation.content;content=[{type:"text",text:outputText}]}if(aborted)return;signal?.removeEventListener("abort",onAbort),resolve20({content,details})}catch(error){signal?.removeEventListener("abort",onAbort),aborted||reject(error)}})()}).then(result2=>({...result2,structuredContent:toReadOutput(result2.content)}))},...readRenderers}}function createReadTool(cwd,options){return wrapToolDefinition(createReadToolDefinition(cwd,options))}import{mkdir as fsMkdir,writeFile as fsWriteFile2}from"fs/promises";import{dirname as dirname13}from"path";var WriteCallRenderComponent=class extends Text{constructor(){super("",0,0)}},WRITE_PARTIAL_FULL_HIGHLIGHT_LINES=50;function highlightSingleLine(line,lang){return highlightCode(line,lang)[0]??""}function refreshWriteHighlightPrefix(cache){let prefixCount=Math.min(WRITE_PARTIAL_FULL_HIGHLIGHT_LINES,cache.normalizedLines.length);if(prefixCount===0)return;let prefixSource=cache.normalizedLines.slice(0,prefixCount).join(`
|
|
1005
|
-
`),prefixHighlighted=highlightCode(prefixSource,cache.lang);for(let i=0;i<prefixCount;i++)cache.highlightedLines[i]=prefixHighlighted[i]??highlightSingleLine(cache.normalizedLines[i]??"",cache.lang)}function rebuildWriteHighlightCacheFull(rawPath,fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0;if(!lang)return;let displayContent=normalizeDisplayText(fileContent),normalized=
|
|
1006
|
-
`),highlightedLines:highlightCode(normalized,lang)}}function updateWriteHighlightCacheIncremental(cache,rawPath,fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0;if(!lang)return;if(!cache||cache.lang!==lang||cache.rawPath!==rawPath||!fileContent.startsWith(cache.rawContent))return rebuildWriteHighlightCacheFull(rawPath,fileContent);if(fileContent.length===cache.rawContent.length)return cache;let deltaRaw=fileContent.slice(cache.rawContent.length),deltaDisplay=normalizeDisplayText(deltaRaw),deltaNormalized=
|
|
1005
|
+
`),prefixHighlighted=highlightCode(prefixSource,cache.lang);for(let i=0;i<prefixCount;i++)cache.highlightedLines[i]=prefixHighlighted[i]??highlightSingleLine(cache.normalizedLines[i]??"",cache.lang)}function rebuildWriteHighlightCacheFull(rawPath,fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0;if(!lang)return;let displayContent=normalizeDisplayText(fileContent),normalized=replaceTabs2(displayContent);return{rawPath,lang,rawContent:fileContent,normalizedLines:normalized.split(`
|
|
1006
|
+
`),highlightedLines:highlightCode(normalized,lang)}}function updateWriteHighlightCacheIncremental(cache,rawPath,fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0;if(!lang)return;if(!cache||cache.lang!==lang||cache.rawPath!==rawPath||!fileContent.startsWith(cache.rawContent))return rebuildWriteHighlightCacheFull(rawPath,fileContent);if(fileContent.length===cache.rawContent.length)return cache;let deltaRaw=fileContent.slice(cache.rawContent.length),deltaDisplay=normalizeDisplayText(deltaRaw),deltaNormalized=replaceTabs2(deltaDisplay);cache.rawContent=fileContent,cache.normalizedLines.length===0&&(cache.normalizedLines.push(""),cache.highlightedLines.push(""));let segments=deltaNormalized.split(`
|
|
1007
1007
|
`),lastIndex=cache.normalizedLines.length-1;cache.normalizedLines[lastIndex]+=segments[0],cache.highlightedLines[lastIndex]=highlightSingleLine(cache.normalizedLines[lastIndex],cache.lang);for(let i=1;i<segments.length;i++)cache.normalizedLines.push(segments[i]),cache.highlightedLines.push(highlightSingleLine(segments[i],cache.lang));return refreshWriteHighlightPrefix(cache),cache}function trimTrailingEmptyLines2(lines){let end=lines.length;for(;end>0&&lines[end-1]==="";)end--;return lines.slice(0,end)}function formatWriteCall(args,options,theme2,cache,cwd){let rawPath=str(args?.file_path??args?.path),fileContent=str(args?.content),pathDisplay=renderToolPath(rawPath,theme2,cwd),text2=`${theme2.fg("toolTitle",theme2.bold("write"))} ${pathDisplay}`;if(fileContent===null)text2+=`
|
|
1008
1008
|
|
|
1009
|
-
${theme2.fg("error","[invalid content arg - expected string]")}`;else if(fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0,renderedLines=lang?cache?.highlightedLines??highlightCode(
|
|
1009
|
+
${theme2.fg("error","[invalid content arg - expected string]")}`;else if(fileContent){let lang=rawPath?getLanguageFromPath(rawPath):void 0,renderedLines=lang?cache?.highlightedLines??highlightCode(replaceTabs2(normalizeDisplayText(fileContent)),lang):normalizeDisplayText(fileContent).split(`
|
|
1010
1010
|
`),lines=trimTrailingEmptyLines2(renderedLines),totalLines=lines.length,maxLines=options.expanded?lines.length:10,displayLines=lines.slice(0,maxLines),remaining=lines.length-maxLines;text2+=`
|
|
1011
1011
|
|
|
1012
|
-
${displayLines.map(line=>lang?line:theme2.fg("toolOutput",
|
|
1012
|
+
${displayLines.map(line=>lang?line:theme2.fg("toolOutput",replaceTabs2(line))).join(`
|
|
1013
1013
|
`)}`,remaining>0&&(text2+=`${theme2.fg("muted",`
|
|
1014
1014
|
... (${remaining} more lines, ${totalLines} total,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`)}return text2}function formatWriteResult(result2,theme2){if(!result2.isError)return;let output=result2.content.filter(c=>c.type==="text").map(c=>c.text||"").join(`
|
|
1015
1015
|
`);if(output)return`
|
|
1016
|
-
${theme2.fg("error",output)}`}var writeRenderers={renderCall(args,theme2,context){let renderArgs=args,rawPath=str(renderArgs?.file_path??renderArgs?.path),fileContent=str(renderArgs?.content),component=context.lastComponent??new WriteCallRenderComponent;return fileContent!==null?component.cache=context.argsComplete?rebuildWriteHighlightCacheFull(rawPath,fileContent):updateWriteHighlightCacheIncremental(component.cache,rawPath,fileContent):component.cache=void 0,component.setText(formatWriteCall(renderArgs,{expanded:context.expanded,isPartial:context.isPartial},theme2,component.cache,context.cwd)),component},renderResult(result2,_options,theme2,context){let output=formatWriteResult({...result2,isError:context.isError},theme2);if(!output){let component=context.lastComponent??new Container;return component.clear(),component}let text2=context.lastComponent??new Text("",0,0);return text2.setText(output),text2}};var writeSchema=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to write (relative or absolute)"}),content:typebox_exports.String({description:"Content to write to the file"})}),writeToolSystemPromptContribution={snippet:"Create or overwrite files",guidelines:["Use write only for new files or complete rewrites."]},defaultWriteOperations={writeFile:(path14,content)=>fsWriteFile2(path14,content,"utf-8"),mkdir:dir=>fsMkdir(dir,{recursive:!0}).then(()=>{})};function createWriteToolDefinition(cwd,options){let ops=options?.operations??defaultWriteOperations;return{name:"write",label:"write",description:"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",promptSnippet:writeToolSystemPromptContribution.snippet,promptGuidelines:[...writeToolSystemPromptContribution.guidelines],parameters:writeSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_toolCallId,{path:path14,content},signal,_onUpdate,ctx){let absolutePath=resolveToCwd(path14,ctx?.cwd||cwd),dir=dirname13(absolutePath);return withFileMutationQueue(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};return throwIfAborted(),await ops.mkdir(dir),throwIfAborted(),await ops.writeFile(absolutePath,content),throwIfAborted(),{content:[{type:"text",text:`Successfully wrote to ${path14}`}],details:void 0}})},...writeRenderers}}function createWriteTool(cwd,options){return wrapToolDefinition(createWriteToolDefinition(cwd,options))}function
|
|
1017
|
-
`)}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function fileNameOf(path14){return path14.replace(/\\/g,"/").split("/").at(-1)??path14}var RESULT_EXPAND_LIMIT=4e3,WAIT_REFRESH_MS=1e3;function scheduleWaitRefresh(context,pending){let state2=context.state;if(state2!==void 0){if(pending){state2.dispose=()=>scheduleWaitRefresh(context,!1),state2.refreshTimer===void 0&&(state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,context.invalidate()},WAIT_REFRESH_MS),state2.refreshTimer.unref?.());return}state2.refreshTimer!==void 0&&(clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0),state2.waitStartedAt=void 0}}function capForTranscript(text2,limit){return text2.length>limit?`\u2026${text2.slice(-limit)}`:text2}function renderTasksCall(args,theme2,context){switch(args.action){case"read":{let mode=args.mode??"tail",size=args.bytes!==void 0?` ${formatSize(args.bytes)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks read "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",` ${mode}${size}`)}`,0,0)}case"wait":return renderWaitCall(args,theme2,context);case"kill":return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks kill "))}${theme2.fg("accent",args.taskId??"")}`,0,0);case"list":return new Text(theme2.fg("toolTitle",theme2.bold("tasks list")),0,0);default:{let action=typeof args.action=="string"?` ${theme2.fg("dim",args.action)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks"))}${action}`,0,0)}}}function renderWaitCall(args,theme2,context){let taskId=typeof args.taskId=="string"?args.taskId.trim():"",pending=context.executionStarted===!0&&context.isPartial===!0&&context.state!==void 0;if(scheduleWaitRefresh(context,pending),!pending){let ms=args.waitMs!==void 0?` ${formatDuration(clampWaitMs(args.waitMs))}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks wait "))}${theme2.fg("accent",taskId||"any")}${theme2.fg("muted",ms)}`,0,0)}let state2=context.state;state2.waitStartedAt===void 0&&(state2.waitStartedAt=Date.now());let elapsed=`waiting ${formatDuration(Date.now()-state2.waitStartedAt)}/${formatDuration(clampWaitMs(args.waitMs))}`;return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks wait "))}${theme2.fg("accent",taskId||"any")} ${theme2.fg("muted",elapsed)}`,0,0)}function renderTasksResult(result2,options,theme2,context){context.args?.action==="wait"&&!options.isPartial&&scheduleWaitRefresh(context,!1);let details=result2.details,summary=details&&!context.isError?resultSummaryLine(details,theme2,options.expanded):void 0;if(summary===void 0){let text2=result2.content.find(part=>part.type==="text")?.text??"";return new Text(theme2.fg("toolOutput",text2.trimEnd()),0,0)}let container=new Container;if(container.addChild(new TruncatedText(summary,1,0)),options.expanded){let text2=result2.content.find(part=>part.type==="text")?.text??"";container.addChild(new Text("",0,0)),container.addChild(new Text(theme2.fg("toolOutput",capForTranscript(text2,RESULT_EXPAND_LIMIT).trimEnd()),1,0))}return container}function resultSummaryLine(details,theme2,expanded){let shownPath=path14=>expanded?path14:fileNameOf(path14);switch(details.action){case"read":{let size=details.sliceBytes!==details.totalBytes?`${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`:formatSize(details.totalBytes);return`${theme2.fg("muted","\u2192 ")}${theme2.fg("accent",details.taskId)}${theme2.fg("muted",`${details.status?` ${statusName(details.status)} \xB7`:""} ${size}${details.outputPath?` \xB7 ${shownPath(details.outputPath)}`:""}`)}`}case"wait":{let outcome=details.outcome??(details.timedOut?"timed_out":"settled");if(outcome==="no_tasks")return theme2.fg("muted","\u2192 No background tasks running");let taskId=details.taskId??"any";if(outcome==="interrupted"){let running=details.running?` \xB7 ${details.running} still running`:"";return`${theme2.fg(statusColor("cancelled"),statusGlyph("cancelled"))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` wait interrupted after ${formatDuration(details.waitedMs)}${running}`)}`}if(outcome==="timed_out"){let status2=details.status??"running",running=details.taskId?formatSize(details.totalBytes):`${details.running??0} still running`;return`${theme2.fg(statusColor(status2),statusGlyph(status2))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` ${statusName(status2)} \xB7 wait ended after ${formatDuration(details.waitedMs)} \xB7 ${running}`)}`}let status=details.status??"completed",exit=exitSuffix(details.exitCode,", ");return`${theme2.fg(statusColor(status),statusGlyph(status))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` ${statusName(status)}${exit} \xB7 waited ${formatDuration(details.waitedMs)} \xB7 +${formatSize(details.deltaBytes)}`)}`}case"kill":{let status=details.status??(details.requested?"stopping":"cancelled");return`${theme2.fg(statusColor(status),statusGlyph(status))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` ${statusName(status)}${details.requested?" \xB7 cancellation requested":""}`)}`}case"list":{let hidden=details.hidden>0?` \xB7 ${details.hidden} more finished`:"",omitted=details.foregroundOmitted?` \xB7 ${details.foregroundOmitted} foreground omitted`:"";return theme2.fg("muted",`${details.running} running \xB7 ${details.finished} finished${hidden}${omitted}`)}default:return}}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?`
|
|
1018
|
-
${omitted} foreground ${omitted===1?"execution":"executions"} omitted \u2014 foreground work is delivered inline in the transcript.`:""}function lookupFailure(background,id,error){if(!(error instanceof TaskLookupError))return error instanceof Error?error:new Error(String(error));if(error.kind==="ambiguous"){let lines2=error.matches.map(task=>describeTaskLine(task)).join(`
|
|
1019
|
-
`);return new Error(`Ambiguous task ID "${id}" matches ${error.matches.length} tasks:
|
|
1020
|
-
${lines2}`)}let{tasks,foregroundOmitted}=listedTasks(background),active=tasks.filter(task=>!isTaskTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isTaskTerminal(task.status))),shown=[...active,...finished].slice(0,LOOKUP_LIST_LIMIT);if(shown.length===0)return new Error(`No task "${id}" in this session. No background tasks in this session.`);let lines=shown.map(task=>describeTaskLine(task)).join(`
|
|
1021
|
-
`);return new Error(`No task "${id}" in this session. IDs from other sessions are not valid here.
|
|
1022
|
-
Current background tasks:
|
|
1023
|
-
${lines}${foregroundOmissionNote(foregroundOmitted)}`)}function rangeText(slice,sinceBytes){let from=slice.fromByte??0,to=from+Buffer.byteLength(slice.text),floor=sinceBytes===void 0||sinceBytes>slice.totalBytes?0:sinceBytes;return[`bytes ${from}\u2013${to} of ${slice.totalBytes}`,sinceBytes!==void 0&&from>floor?`skipped ${from-floor} bytes after sinceBytes ${floor}`:"",`next sinceBytes ${to}`].filter(Boolean).join(" \xB7 ")}function readText(header2,slice){let boundedField=(text2,maxBytes)=>truncateHead(boundText(sanitizeBinaryOutput(text2),maxBytes),{maxBytes,maxLines:100}).content;return[boundedField(header2,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(`
|
|
1024
|
-
`)}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 ${rangeText(slice)}]`,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)}}function activeBackgroundTasks(background){return background.list().filter(task=>task.mode==="background"&&!isTaskTerminal(task.status))}function stillRunningText(tasks){return tasks.length>0?`
|
|
1025
|
-
|
|
1026
|
-
[still_running]
|
|
1027
|
-
${tasks.map(task=>describeTaskLine(task)).join(`
|
|
1028
|
-
`)}`:""}function emptyWaitDetails(outcome,waitedMs,running){return{action:"wait",outcome,timedOut:outcome==="timed_out",exitCode:void 0,waitedMs,deltaBytes:0,totalBytes:0,deltaTruncated:!1,outputPath:"",running}}async function runWaitAny(background,input2,signal,onReady,interruptSignal){let candidates=activeBackgroundTasks(background);if(candidates.length===0)return result("No background tasks are running, so there is nothing to wait for. Finished tasks report back via automatic notification.",emptyWaitDetails("no_tasks",0,0));let releases=candidates.map(task=>background.holdDelivery(task.id)),start=Date.now();try{let task=await background.waitAny(clampWaitMs(input2.waitMs),signal,interruptSignal),ids=new Set(candidates.map(candidate=>candidate.id)),running=activeBackgroundTasks(background).filter(candidate=>ids.has(candidate.id));if(!task){let interrupted=!background.closed&&interruptSignal?.aborted===!0,outcome=interrupted?"interrupted":"timed_out",note=background.closed?"The host closed; execution state is unconfirmed.":interrupted?"New steering input ended this wait early. Read the new input before deciding what to do next; no task was stopped.":"The wait window expired; running tasks continue. Prefer other work over waiting again.";return result(`${note}${stillRunningText(running)}`,emptyWaitDetails(outcome,Date.now()-start,running.length))}let slice=await background.read(task.id,{bytes:32768});return signal?.throwIfAborted(),onReady?.(task.id),result(`${readText(`[${describeTaskLine(task)} \xB7 waitAny settled \xB7 ${rangeText(slice)}]`,slice)}${stillRunningText(running)}`,{action:"wait",outcome:"settled",taskId:task.id,status:task.status,kind:task.kind,timedOut:!1,exitCode:task.exitCode,waitedMs:Date.now()-start,deltaBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,deltaTruncated:slice.truncated,outputPath:task.outputPath??"",running:running.length})}finally{for(let release2 of releases)release2()}}async function runWait(background,input2,signal,onReady,interruptSignal){if(!input2.taskId?.trim()){if(input2.sinceBytes!==void 0)throw new Error("action 'wait' without 'taskId' does not accept 'sinceBytes'; offsets belong to one task.");return runWaitAny(background,input2,signal,onReady,interruptSignal)}let id=requireTaskId(input2);try{let release2=background.holdDelivery(id);try{let start=Date.now(),task=await background.wait(id,clampWaitMs(input2.waitMs),signal,interruptSignal),settled=isTaskTerminal(task.status),interrupted=!settled&&!background.closed&&interruptSignal?.aborted===!0,timedOut=!settled&&!interrupted,outcome=settled?"settled":interrupted?"interrupted":"timed_out",waitedMs=Date.now()-start;if(interrupted)return result(`[${describeTaskLine(task)} \xB7 interrupted by steering; execution continues]
|
|
1029
|
-
Read the new input before deciding whether to wait again; the task was not stopped.`,{action:"wait",outcome,taskId:task.id,status:task.status,kind:task.kind,timedOut:!1,exitCode:task.exitCode,waitedMs,deltaBytes:0,totalBytes:0,deltaTruncated:!1,outputPath:task.outputPath??""});let windowNote=background.closed?" \xB7 host closed; execution state unconfirmed":timedOut?" \xB7 wait window expired; execution continues":"",sinceBytes=clampSinceBytes(input2.sinceBytes),slice=await background.read(id,{bytes:32768,sinceBytes});return signal?.throwIfAborted(),settled&&onReady?.(task.id),result(readText(`[${describeTaskLine(task)}${windowNote} \xB7 ${rangeText(slice,sinceBytes)}]`,slice),{action:"wait",outcome,taskId:task.id,status:task.status,kind:task.kind,timedOut,exitCode:task.exitCode,waitedMs,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=>!isTaskTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isTaskTerminal(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(`
|
|
1030
|
-
`)}${hidden>0?`
|
|
1031
|
-
${hidden} more records not shown.`:""}${foregroundOmissionNote(foregroundOmitted)}`:`No background tasks. Start work through its owning tool with background: true.${foregroundOmissionNote(foregroundOmitted)}`,{action:"list",running:active.length,finished:finished.length,shown:shown.length,hidden,...foregroundOmitted>0?{foregroundOmitted}:{}})}function createTasksToolDefinition(onWaitResult,waitInterruptSignal){return{name:"tasks",label:"tasks",description:TASKS_TOOL_DESCRIPTION,promptSnippet:TASKS_PROMPT_SNIPPET,promptGuidelines:TASKS_PROMPT_GUIDELINES,parameters:tasksSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_id,params,signal,_onUpdate,ctx){try{switch(params.action){case"read":return await runRead(ctx.tasks,params);case"wait":return await runWait(ctx.tasks,params,signal,taskId=>onWaitResult?.(_id,taskId),waitInterruptSignal?.());case"kill":return runKill(ctx.tasks,params);case"list":return runList(ctx.tasks)}}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(boundedText(message))}},renderCall:renderTasksCall,renderResult:renderTasksResult}}function createAllToolDefinitions(cwd,options){return{tasks:createTasksToolDefinition(),read:createReadToolDefinition(cwd,options?.read),bash:createBashToolDefinition(cwd,options?.bash),powershell:createPowerShellToolDefinition(cwd,options?.powershell),edit:createEditToolDefinition(cwd,options?.edit),write:createWriteToolDefinition(cwd,options?.write),grep:createGrepToolDefinition(cwd,options?.grep),find:createFindToolDefinition(cwd,options?.find),ls:createLsToolDefinition(cwd,options?.ls)}}function createCodingTools(cwd,options){return[createReadTool(cwd,options?.read),createBashTool(cwd,options?.bash),createEditTool(cwd,options?.edit),createWriteTool(cwd,options?.write)]}function createReadOnlyTools(cwd,options){return[createReadTool(cwd,options?.read),createGrepTool(cwd,options?.grep),createFindTool(cwd,options?.find),createLsTool(cwd,options?.ls)]}import{readFileSync as readFileSync11}from"node:fs";import{basename as basename9,dirname as dirname17}from"node:path";function sleep3(ms,signal){return new Promise((resolve20,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve20,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}async function normalizeToolResultImages(content,options){if(!content.some(block=>block.type==="image"))return content;let autoResizeImages=options?.autoResizeImages??!0,normalized=[],changed2=!1;for(let block of content){if(block.type!=="image"){normalized.push(block);continue}let processed=await processImage(Buffer.from(block.data,"base64"),block.mimeType,{autoResizeImages,resizeOptions:options?.resizeOptions});if(!processed.ok){normalized.push(block);continue}if(processed.data===block.data&&processed.mimeType===block.mimeType&&processed.hints.length===0){normalized.push(block);continue}normalized.push({type:"image",data:processed.data,mimeType:processed.mimeType}),processed.hints.length>0&&normalized.push({type:"text",text:processed.hints.join(`
|
|
1016
|
+
${theme2.fg("error",output)}`}var writeRenderers={renderCall(args,theme2,context){let renderArgs=args,rawPath=str(renderArgs?.file_path??renderArgs?.path),fileContent=str(renderArgs?.content),component=context.lastComponent??new WriteCallRenderComponent;return fileContent!==null?component.cache=context.argsComplete?rebuildWriteHighlightCacheFull(rawPath,fileContent):updateWriteHighlightCacheIncremental(component.cache,rawPath,fileContent):component.cache=void 0,component.setText(formatWriteCall(renderArgs,{expanded:context.expanded,isPartial:context.isPartial},theme2,component.cache,context.cwd)),component},renderResult(result2,_options,theme2,context){let output=formatWriteResult({...result2,isError:context.isError},theme2);if(!output){let component=context.lastComponent??new Container;return component.clear(),component}let text2=context.lastComponent??new Text("",0,0);return text2.setText(output),text2}};var writeSchema=typebox_exports.Object({path:typebox_exports.String({description:"Path to the file to write (relative or absolute)"}),content:typebox_exports.String({description:"Content to write to the file"})}),writeToolSystemPromptContribution={snippet:"Create or overwrite files",guidelines:["Use write only for new files or complete rewrites."]},defaultWriteOperations={writeFile:(path14,content)=>fsWriteFile2(path14,content,"utf-8"),mkdir:dir=>fsMkdir(dir,{recursive:!0}).then(()=>{})};function createWriteToolDefinition(cwd,options){let ops=options?.operations??defaultWriteOperations;return{name:"write",label:"write",description:"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",promptSnippet:writeToolSystemPromptContribution.snippet,promptGuidelines:[...writeToolSystemPromptContribution.guidelines],parameters:writeSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_toolCallId,{path:path14,content},signal,_onUpdate,ctx){let absolutePath=resolveToCwd(path14,ctx?.cwd||cwd),dir=dirname13(absolutePath);return withFileMutationQueue(absolutePath,async()=>{let throwIfAborted=()=>{if(signal?.aborted)throw new Error("Operation aborted")};return throwIfAborted(),await ops.mkdir(dir),throwIfAborted(),await ops.writeFile(absolutePath,content),throwIfAborted(),{content:[{type:"text",text:`Successfully wrote to ${path14}`}],details:void 0}})},...writeRenderers}}function createWriteTool(cwd,options){return wrapToolDefinition(createWriteToolDefinition(cwd,options))}function createAllToolDefinitions(cwd,options){return{read:createReadToolDefinition(cwd,options?.read),bash:createBashToolDefinition(cwd,options?.bash),powershell:createPowerShellToolDefinition(cwd,options?.powershell),edit:createEditToolDefinition(cwd,options?.edit),write:createWriteToolDefinition(cwd,options?.write),grep:createGrepToolDefinition(cwd,options?.grep),find:createFindToolDefinition(cwd,options?.find),ls:createLsToolDefinition(cwd,options?.ls)}}function createCodingTools(cwd,options){return[createReadTool(cwd,options?.read),createBashTool(cwd,options?.bash),createEditTool(cwd,options?.edit),createWriteTool(cwd,options?.write)]}function createReadOnlyTools(cwd,options){return[createReadTool(cwd,options?.read),createGrepTool(cwd,options?.grep),createFindTool(cwd,options?.find),createLsTool(cwd,options?.ls)]}import{readFileSync as readFileSync11}from"node:fs";import{basename as basename9,dirname as dirname17}from"node:path";function sleep3(ms,signal){return new Promise((resolve20,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve20,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}async function normalizeToolResultImages(content,options){if(!content.some(block=>block.type==="image"))return content;let autoResizeImages=options?.autoResizeImages??!0,normalized=[],changed2=!1;for(let block of content){if(block.type!=="image"){normalized.push(block);continue}let processed=await processImage(Buffer.from(block.data,"base64"),block.mimeType,{autoResizeImages,resizeOptions:options?.resizeOptions});if(!processed.ok){normalized.push(block);continue}if(processed.data===block.data&&processed.mimeType===block.mimeType&&processed.hints.length===0){normalized.push(block);continue}normalized.push({type:"image",data:processed.data,mimeType:processed.mimeType}),processed.hints.length>0&&normalized.push({type:"text",text:processed.hints.join(`
|
|
1032
1017
|
`)}),changed2=!0}return changed2?normalized:content}import{join as join22}from"node:path";var UNKNOWN_PROVIDER="unknown";function getProviderLoginHelp(){return["Use /login to log into a provider via OAuth or API key. See:",` ${join22(getDocsPath(),"providers.md")}`,` ${join22(getDocsPath(),"models.md")}`].join(`
|
|
1033
1018
|
`)}function formatNoModelsAvailableMessage(){return`No models available. ${getProviderLoginHelp()}`}function formatNoModelSelectedMessage(){return`No model selected.
|
|
1034
1019
|
|
|
@@ -1078,7 +1063,7 @@ ${modelText(snapshot.command,8192,128)}`),snapshot.cwd&&header2.push(`cwd: ${sin
|
|
|
1078
1063
|
|
|
1079
1064
|
${guidance}`:"",remaining=Math.min(MODEL_OUTPUT_BYTES,TASK_RESULT_BYTES-Buffer.byteLength(prefix)-Buffer.byteLength(suffix)),lines=MODEL_LINES-prefix.split(`
|
|
1080
1065
|
`).length-(guidance?3:0),output=snapshot.output.text?snapshot.output:{text:"No text result.",truncated:!1};return prefix+modelTail(output,remaining,lines)+suffix}function taskCompletionMessage(task){let details=taskCompletionSnapshot(task);return{role:"custom",customType:"task-completion",display:!0,content:notificationText(details),details,timestamp:Date.now()}}var TaskDelivery=class{constructor(options){this.disposed=!1,this.pauses=0,this.failures=new Set,this.waits=new Map,this.options=options}get service(){return this.options.service()}warn(event,message){this.options.warn(event,message)}pause(){this.pauses++;let releaseService=this.service.pause(),released=!1;return()=>{released||(released=!0,this.pauses--,releaseService(),this.schedule())}}retry(){this.failures.clear(),this.schedule()}schedule(){this.disposed||this.timer||this.delivery||(this.timer=setTimeout(()=>{this.timer=void 0,this.drain().catch(()=>this.warn("task_delivery","Background notification drain failed; delivery was not confirmed."))},0),this.timer.unref?.())}canDeliver(service){return!this.disposed&&service===this.service&&service.enabled&&this.pauses===0&&this.options.canDeliver()}async drain(){let service=this.service;if(this.delivery||!this.canDeliver(service))return;if(this.failures.size){let retained=new Set(service.list().map(task2=>task2.id));for(let id of this.failures)retained.has(id)||this.failures.delete(id)}let task=service.pendingNotifications().find(task2=>!this.failures.has(task2.id));if(!task)return;let message=taskCompletionMessage(task);if(!service.claimNotification(task.id))return;let delivery={id:task.id,service,message,phase:"pending"};this.delivery=delivery;let deliveryError;try{await this.options.deliver(delivery.message,()=>new Promise((resolve20,reject)=>{delivery.phase==="persisted"?resolve20():delivery.queued={resolve:resolve20,reject}}))}catch(error){deliveryError=error}finally{if(delivery.phase!=="persisted"){service.releaseNotification(task.id),service===this.service&&this.failures.add(task.id);let reason=deliveryError instanceof Error?`: ${deliveryError.message}`:"";this.warn("task_delivery",`Background completion delivery failed for ${task.id}${reason}; it will retry on the next input.`)}this.delivery=void 0;let current=this.service;this.canDeliver(current)&¤t.pendingNotifications().some(task2=>!this.failures.has(task2.id))&&this.schedule()}}messageStarted(message){let delivery=this.delivery;delivery?.message===message&&delivery.phase==="pending"&&(delivery.phase="started")}agentEnded(){this.releaseWaits();let delivery=this.delivery;delivery?.phase==="started"&&delivery.queued?.reject(new Error("the completion message was not persisted"))}queueCleared(){this.delivery?.queued?.reject(new Error("the completion message was dequeued before delivery"))}messagePersisted(message){let delivery=this.delivery;delivery?.message===message&&delivery.phase!=="persisted"&&(delivery.phase="persisted",delivery.service.markDelivered(delivery.id),delivery.queued?.resolve()),message.role==="toolResult"&&this.acknowledgeWait(message.toolCallId)}prepareWait(toolCallId,taskId){let service=this.service,task=service.get(taskId);task.mode!=="background"||!isTaskTerminal(task.status)||(this.waits.get(toolCallId)?.release(),this.waits.set(toolCallId,{service,taskId,release:service.holdDelivery(taskId)}))}acknowledgeWait(toolCallId){let receipt=this.waits.get(toolCallId);receipt&&(this.waits.delete(toolCallId),receipt.service.markDelivered(receipt.taskId),receipt.release())}releaseWaits(){for(let receipt of this.waits.values())receipt.release();this.waits.clear()}dispose(){this.disposed=!0,this.releaseWaits(),this.delivery?.queued?.reject(new Error("the session was disposed")),this.timer&&clearTimeout(this.timer),this.timer=void 0}};function taskLine(task){let title=boundText(task.title.replace(/\s+/gu," ").trim(),240);return boundText(`${task.id} ${task.kind} ${task.status} ${title}`,1024)}var TaskContextReminder=class{constructor(){this.pending=!1,this.projected=!1}compacted(){this.pending=!0,this.projected=!1}project(service,messages){if(!this.pending)return messages;let tasks=service.list().filter(task=>task.mode==="background"&&!isTaskTerminal(task.status));if(tasks.length===0)return this.reset(),messages;let reminder={role:"user",content:[{type:"text",text:["Context was compacted. These background tasks are still active; do not start duplicates.","Use tasks list/read/wait/kill to inspect or control them. Completion arrives automatically.",...tasks.map(taskLine)].join(`
|
|
1081
|
-
`)}],timestamp:Date.now()};return this.projected=!0,[...messages,reminder]}assistantCompleted(){this.projected&&this.reset()}reset(){this.pending=!1,this.projected=!1}};var TaskSession=class{constructor(options){this.enabled=!1,this.disposed=!1,this.generation=0,this.waitInterrupt=new AbortController,this.contextReminder=new TaskContextReminder,this.quarantine=[],this.options=options,this.delivery=new TaskDelivery({service:()=>this.service,canDeliver:options.canDeliver,deliver:options.deliver,warn:(event,message)=>this.warn(event,message)}),this._service=this.createService()}get service(){return this._service}get waitInterruptSignal(){return this.waitInterrupt.signal}interruptWaits(){let previous=this.waitInterrupt;this.waitInterrupt=new AbortController,previous.abort()}noteCompaction(){this.contextReminder.compacted()}projectContextReminder(messages){return this.contextReminder.project(this.service,messages)}noteAssistantCompleted(){this.contextReminder.assistantCompleted()}get quarantinedSettlements(){return structuredClone(this.quarantine)}setEnabled(enabled){this.enabled=enabled&&this.options.backgroundAllowed!==!1,this.service.setEnabled(this.enabled)}stoppedByTreeNavigation(targetId){let target=this.options.manager.getEntry(targetId);if(!target)return[];let leafId=target.type==="message"&&target.message.role==="user"||target.type==="custom_message"?target.parentId:targetId;return
|
|
1066
|
+
`)}],timestamp:Date.now()};return this.projected=!0,[...messages,reminder]}assistantCompleted(){this.projected&&this.reset()}reset(){this.pending=!1,this.projected=!1}};var TaskSession=class{constructor(options){this.enabled=!1,this.disposed=!1,this.generation=0,this.waitInterrupt=new AbortController,this.contextReminder=new TaskContextReminder,this.quarantine=[],this.options=options,this.delivery=new TaskDelivery({service:()=>this.service,canDeliver:options.canDeliver,deliver:options.deliver,warn:(event,message)=>this.warn(event,message)}),this._service=this.createService()}get service(){return this._service}get waitInterruptSignal(){return this.waitInterrupt.signal}interruptWaits(){let previous=this.waitInterrupt;this.waitInterrupt=new AbortController,previous.abort()}noteCompaction(){this.contextReminder.compacted()}projectContextReminder(messages){return this.contextReminder.project(this.service,messages)}noteAssistantCompleted(){this.contextReminder.assistantCompleted()}get quarantinedSettlements(){return structuredClone(this.quarantine)}setEnabled(enabled){this.enabled=enabled&&this.options.backgroundAllowed!==!1,this.service.setEnabled(this.enabled)}stoppedByTreeNavigation(targetId,service=this.service){let target=this.options.manager.getEntry(targetId);if(!target)return[];let leafId=target.type==="message"&&target.message.role==="user"||target.type==="custom_message"?target.parentId:targetId;return service.activeOutsideBranch(this.branchIds(leafId))}cancelOutsideBranch(leafId){return this.service.cancelOutsideBranch(this.branchIds(leafId))}branchIds(leafId){return new Set(leafId===null?[]:this.options.manager.getBranch(leafId).map(entry=>entry.id))}replaceService(){this.contextReminder.reset(),this.service.close(),this._service=this.createService(),this.delivery.retry()}createService(){let{manager,backgroundAllowed}=this.options,generation=++this.generation,sessionId=manager.getSessionId(),sessionFile=manager.getSessionFile(),waitInterruptSignal=()=>this.waitInterruptSignal,service=new TaskRuntime({enabled:this.enabled,backgroundAllowed,session:{get waitInterruptSignal(){return waitInterruptSignal()},prepareWait:(toolCallId,taskId)=>this.delivery.prepareWait(toolCallId,taskId),stoppedByTreeNavigation:targetId=>this.stoppedByTreeNavigation(targetId,service)},anchor:()=>manager.getLeafId(),onCleanupError:message=>this.warn("task_cleanup",message),onSettled:(task,usage)=>{let onBranch=manager.getSessionId()===sessionId&&(task.anchorId===null||manager.getBranch().some(entry=>entry.id===task.anchorId));if(this.disposed||this.service!==service||!onBranch){this.quarantineSettlement({sessionId,generation,task,usage},sessionFile);return}this.persistSettlement(task,usage)}});return this.restoreHistory(service),service.subscribe(()=>this.delivery.schedule()),service}restoreHistory(service=this.service){let records=[],toolResults=new Map;for(let entry of this.options.manager.getBranch())entry.type==="custom"&&entry.customType==="task-result"?records.push(entry.data):entry.type==="message"&&entry.message.role==="toolResult"&&toolResults.set(entry.message.toolCallId,entry.message.content);service.restoreHistory(records,toolResults)}quarantineSettlement(record,sessionFile){this.quarantine.push(structuredClone(record)),this.quarantine.length>32&&this.quarantine.shift();let persistence="Not persisted: only the latest 32 snapshots are retained in quarantinedTaskSettlements; late usage is not accounted in session totals.";if(sessionFile)try{mkdirSync8(dirname16(sessionFile),{recursive:!0}),appendFileSync4(`${sessionFile}.tasks-late.jsonl`,`${JSON.stringify({version:1,...record})}
|
|
1082
1067
|
`),persistence=`Saved diagnostic sidecar: ${sessionFile}.tasks-late.jsonl (not included in normal session totals).`}catch{persistence=`Sidecar write failed. ${persistence}`}this.warn("task_settlement_quarantined",`Late background settlement ${record.task.id} was quarantined. ${persistence}`)}persistSettlement(task,usage){let manager=this.options.manager,appended=[],append=(customType,data)=>{let entry=manager.getEntry(manager.appendCustomEntry(customType,data));entry&&appended.push(entry)};try{usage&&!manager.getEntries().some(entry=>getTaskUsageRecord(entry)?.taskId===task.id)&&append(TASK_USAGE_TYPE,{version:1,taskId:task.id,usage});let{result:_result,resultTruncated:_truncated,...metadata}=task,saved=task.mode==="foreground"?metadata:task;append("task-result",JSON.parse(JSON.stringify({version:TASK_HISTORY_VERSION,task:saved})))}finally{for(let entry of appended)try{this.options.onEntry(entry)}catch{}}}warn(event,message){try{this.options.onError(event,truncateHead(message,{maxBytes:4096,maxLines:32}).content)}catch{}}dispose(){this.disposed=!0,this.contextReminder.reset(),this.interruptWaits(),this.service.close(),this.delivery.dispose()}};function parseSkillBlock(text2){let match2=text2.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);return match2?{name:match2[1],location:match2[2],content:match2[3],userMessage:match2[4]?.trim()||void 0}:null}function withoutDeletedHeaders(headers){return headers?Object.fromEntries(Object.entries(headers).filter(entry=>entry[1]!==null)):void 0}function estimateMessagesTokens(messages){let tokens2=0;for(let message of messages)tokens2+=estimateTokens2(message);return tokens2}var AgentSession=class{constructor(config){this._eventListeners=[],this._isAgentRunActive=!1,this._agentRunAbortRequested=!1,this._steeringMessages=[],this._followUpMessages=[],this._pendingNextTurnMessages=[],this._pendingCustomMessages=[],this._compactionAbortController=void 0,this._autoCompactionAbortController=void 0,this._overflowRecoveryAttempted=!1,this._branchSummaryAbortController=void 0,this._retryAbortController=void 0,this._retryAttempt=0,this._bashAbortControllers=new Set,this._pendingBashMessages=[],this._turnIndex=0,this._entryIdsByMessage=new WeakMap,this._boundaryDispatchedMessages=new WeakSet,this._lastActivityOutcome="completed",this._isBeforeSettle=!1,this._abortDuringBeforeSettle=!1,this._isEmittingAgentSettled=!1,this._deferredSettledActions=[],this._baseToolDefinitions=new Map,this._pendingToolNames=new Set,this._allowlistFiltersMcp=!1,this._extensionMode="print",this._toolRegistry=new Map,this._hiddenDeclarations=new Set,this._toolDefinitions=new Map,this._toolPromptSnippets=new Map,this._toolPromptGuidelines=new Map,this._handleAgentEvent=async event=>{if(event.type==="message_start"&&this._tasksHost.delivery.messageStarted(event.message),event.type==="message_end"&&event.message.role==="assistant"&&event.message.stopReason!=="error"&&event.message.stopReason!=="aborted"&&this._tasksHost.noteAssistantCompleted(),event.type==="agent_start"&&this._agentRunAbortRequested&&this.agent.abort(),this._nestedToolCalls)if(event.type==="message_start"&&event.message.role==="toolResult"){let message=event.message,summary=this._nestedToolCalls.takeRecord(message.toolCallId);summary?.calls&&(message.nestedCalls=summary.calls),summary?.usage&&(message.usage=message.usage?combineUsage(message.usage,summary.usage):summary.usage)}else event.type==="agent_end"&&this._nestedToolCalls.clear();if(event.type==="message_start"&&event.message.role==="user"){this._overflowRecoveryAttempted=!1;let messageText=contentText(event.message.content,"");if(messageText){let steeringIndex=this._steeringMessages.indexOf(messageText);if(steeringIndex!==-1)this._steeringMessages.splice(steeringIndex,1),this._emitQueueUpdate();else{let followUpIndex=this._followUpMessages.indexOf(messageText);followUpIndex!==-1&&(this._followUpMessages.splice(followUpIndex,1),this._emitQueueUpdate())}}}if(await this._emitExtensionEvent(event),this._emit(event.type==="agent_end"?{...event,willRetry:this._willRetryAfterAgentEnd(event)}:event),event.type==="message_end"){let entryId;if(event.message.role==="custom"?entryId=this.sessionManager.appendCustomMessageEntry(event.message.customType,event.message.content,event.message.display,event.message.details):(event.message.role==="system"||event.message.role==="user"||event.message.role==="assistant"||event.message.role==="toolResult")&&(entryId=this.sessionManager.appendMessage(event.message)),entryId&&this._entryIdsByMessage.set(event.message,entryId),entryId&&this._messagePersisted(event.message),event.message.role==="assistant"){let assistantMsg=event.message;this._lastAssistantMessage=assistantMsg,assistantMsg.stopReason!=="error"&&assistantMsg.stopReason!=="length"&&(this._overflowRecoveryAttempted=!1),assistantMsg.stopReason!=="error"&&this._retryAttempt>0&&(this._emit({type:"auto_retry_end",success:!0,attempt:this._retryAttempt}),this._retryAttempt=0)}}event.type==="turn_end"&&this._flushPendingCustomMessages(),event.type==="agent_end"&&this._tasksHost.delivery.agentEnded()},this.agent=config.agent,this.sessionManager=config.sessionManager,this.settingsManager=config.settingsManager,this._tasksHost=new TaskSession({manager:this.sessionManager,backgroundAllowed:config.backgroundAllowed,canDeliver:()=>this.model===void 0||this.isCompacting?!1:this.isStreaming||this.pendingMessageCount===0&&!this.agent.hasQueuedMessages(),deliver:(message,waitForPersistence)=>this.isStreaming?(this.agent.steer(message),this._tasksHost.interruptWaits(),waitForPersistence()):this._startRun({messageType:"custom",message}),onEntry:entry=>this._emit({type:"entry_appended",entry}),onError:(event,error)=>this._extensionRunner?.emitError({extensionPath:"<background>",event,error})}),this._scopedModels=config.scopedModels??[],this._resourceLoader=config.resourceLoader,this._customTools=config.customTools??[],this._cwd=config.cwd,this._modelRuntime=config.modelRuntime,this._contextSource=config.contextSource,this._cacheWarmer=config.cacheWarmer,this._cacheWarmer&&(this._cacheWarmer.onWarmed=entry=>this._emit({type:"entry_appended",entry})),this._extensionRunnerRef=config.extensionRunnerRef,this._initialActiveToolNames=config.initialActiveToolNames,this._usesDefaultTools=config.usesDefaultTools??!1,this._defaultToolModifiers=config.defaultToolModifiers??[],config.allowedToolNames&&(this._allowedTools=createToolNameMatcher(config.allowedToolNames),this._allowlistFiltersMcp=config.allowedToolNames.length===0||config.allowedToolNames.some(entry=>entry.startsWith("mcp__"))),this._excludedTools=config.excludedToolNames?createToolNameMatcher(config.excludedToolNames):void 0,this._baseToolsOverride=config.baseToolsOverride,this._sessionStartEvent=config.sessionStartEvent??{type:"session_start",reason:"startup"},this._unsubscribeAgent=this.agent.subscribe(this._handleAgentEvent),this._installAgentToolHooks(),this._installAgentNextTurnRefresh(),this._installAgentRequestProjection(),this._installAgentBoundaryHooks(),this._installHiddenDeclarationsProjection(),this._installAgentForcedPromptProjection(),this._installTaskContextReminderProjection(),this._buildRuntime({activeToolNames:this._initialActiveToolNames,includeAllExtensionTools:!0}),this._usesDefaultTools&&this._restoreToolsFromTranscript(this._defaultToolModifiers)}get tasks(){return this._tasksHost.service}get quarantinedTaskSettlements(){return this._tasksHost.quarantinedSettlements}tasksStoppedByTreeNavigation(targetId){return this._tasksHost.stoppedByTreeNavigation(targetId)}pauseTaskNotifications(){return this._tasksHost.delivery.pause()}retryTaskNotifications(){this._tasksHost.delivery.retry()}async _withTasksPaused(operation){let resumeBackground=this.pauseTaskNotifications();try{return await operation()}finally{resumeBackground()}}get modelRuntime(){return this._modelRuntime}getContextSnapshot(){return captureContextSnapshot(this,this._contextSource)}async _getRequiredRequestAuth(model,signal){let result2;try{result2=await this._modelRuntime.getAuth(model,{signal})}catch(error){let cause=error instanceof Error?error.cause:void 0;throw cause instanceof Error&&cause.message==="authHeader requires a resolved API key"?new Error(formatNoApiKeyFoundMessage(model.provider)):error}if(result2&&(result2.auth.apiKey||result2.auth.headers))return{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env};throw this._modelRuntime.isUsingOAuth(model.provider)?new Error(`Authentication failed for "${model.provider}". Credentials may have expired or network is unavailable. Run '/login ${model.provider}' to re-authenticate.`):new Error(formatNoApiKeyFoundMessage(model.provider))}async _getSummarizationRequestAuth(selectedModel,signal){let{model,thinkingLevel}=isVirtualModel(selectedModel)?await this._modelRuntime.resolveModel(selectedModel,convertToLlm(this.messages),{reason:"direct",thinkingLevel:this.thinkingLevel,signal}):{model:selectedModel,thinkingLevel:this.thinkingLevel};if(this.agent.streamFunction===streamSimple)return{...await this._getRequiredRequestAuth(model,signal),thinkingLevel};try{let result2=await this._modelRuntime.getAuth(model,{signal});return result2?{model:result2.auth.baseUrl?{...model,baseUrl:result2.auth.baseUrl}:model,apiKey:result2.auth.apiKey,headers:withoutDeletedHeaders(result2.auth.headers),env:result2.env,thinkingLevel}:{model,thinkingLevel}}catch(error){if(signal?.aborted)throw error;return{model,thinkingLevel}}}_modelForMessage(message){let model=this.model;return model&&isVirtualModel(model)?this._modelRuntime.getPhysicalModel(message.provider,message.model):model?.provider===message.provider&&model.id===message.model?model:void 0}_recordSelection(){let model=this.model;if(!model)return;let getModel2=(provider,modelId)=>this._modelRuntime.getModel(provider,modelId),recorded=getBranchSelection(this.sessionManager.getBranch(),getModel2);if(!recorded||recorded.provider===model.provider&&recorded.modelId===model.id)return;let recordedModel=getModel2(recorded.provider,recorded.modelId);!isVirtualModel(model)&&!(recordedModel&&isVirtualModel(recordedModel))||this.sessionManager.appendModelChange(model.provider,model.id)}_limitsModel(){return this.routedModel?.model??this.model}_installAgentToolHooks(){this.agent.beforeToolCall=context=>this._beforeToolCall(context),this.agent.afterToolCall=context=>this._afterToolCall(context)}async _beforeToolCall({toolCall,args},parentToolCallId){let runner=this._extensionRunner;if(runner.hasHandlers("tool_call"))try{return await runner.emitToolCall({type:"tool_call",toolName:toolCall.name,toolCallId:toolCall.id,...parentToolCallId?{parentToolCallId}:{},input:args})}catch(err){throw err instanceof Error?err:new Error(`Extension failed, blocking execution: ${String(err)}`)}}async _afterToolCall({toolCall,args,result:result2,isError},parentToolCallId){let runner=this._extensionRunner,hookResult=runner.hasHandlers("tool_result")?await runner.emitToolResult({type:"tool_result",toolName:toolCall.name,toolCallId:toolCall.id,...parentToolCallId?{parentToolCallId}:{},input:args,content:result2.content,details:result2.details,...result2.structuredContent===void 0?{}:{structuredContent:result2.structuredContent},isError,usage:result2.usage}):void 0,content=hookResult?.content??result2.content??[],resizeOptions=this._limitsModel()?.inputLimits?.images?.resize,normalizedContent=await normalizeToolResultImages(content,{autoResizeImages:this.settingsManager.getImageAutoResize(),...resizeOptions?{resizeOptions}:{}});if(!(!hookResult&&normalizedContent===content))return{content:normalizedContent,details:hookResult?.details,structuredContent:hookResult?hookResult.structuredContent:result2.structuredContent,isError:hookResult?.isError??isError,usage:hookResult?.usage}}async _executeNestedToolCall(parentToolCallId,name,args,options){return this._nestedToolCalls??=new NestedToolCallRunner({getTools:()=>this._getCallableTools(),isSequential:()=>this.agent.toolExecution==="sequential",runToolCall:(toolCall,parentId,signal,onUpdate)=>{let assistantMessage=this._findLastAssistantMessage();return assistantMessage?runToolCall(toolCall,{tools:this._getCallableTools(),assistantMessage,context:{messages:this.agent.state.messages,tools:this.agent.state.tools},beforeToolCall:context=>this._beforeToolCall(context,parentId),afterToolCall:context=>this._afterToolCall(context,parentId),signal,onUpdate}):Promise.resolve({toolCall,result:{content:[{type:"text",text:"No assistant message issued this call"}],details:{}},isError:!0})},emit:async event=>{await this._extensionRunner.emit(event),this._emit(event)}}),this._nestedToolCalls.execute(parentToolCallId,name,args,options)}_exceedsCompactionThreshold(model,projection){return model.contextWindow<=0?!1:shouldCompact(estimateProjectedContextTokens(projection,this.sessionManager.getBranch()).tokens,model.contextWindow,this.settingsManager.getCompactionSettings(model))}async _compactBeforeNextAssistantResponse(context){let projection=this.sessionManager.buildSessionProjection(),model=this.model;return!model||isVirtualModel(model)||!this._exceedsCompactionThreshold(model,projection)?{...context,messages:projection.messages}:(await this._runAutoCompaction("threshold",!1),{...context,messages:this.sessionManager.buildSessionProjection().messages})}_installAgentRequestProjection(){let previousPrepareRequest=this.agent.prepareRequest;this.agent.prepareRequest=async(request,signal)=>{let failed=this._failedResponse;this._failedResponse=void 0;let prepare=async()=>{let projection2=this.sessionManager.buildSessionProjection(),canonicalContext={...request.context,messages:projection2.messages,tools:this.agent.state.tools.slice()},previous2=await previousPrepareRequest?.({...request,context:canonicalContext,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel},signal);return{previous:previous2,context:previous2?.context??canonicalContext,projection:projection2}},{previous,context,projection}=await prepare(),model=previous?.model??this.agent.state.model,thinkingLevel=previous?.thinkingLevel??this.agent.state.thinkingLevel;if(!isVirtualModel(model))return{...previous,context,model,thinkingLevel};let lastResponse=context.messages.findLastIndex(message=>message.role==="assistant"),userTurn=context.messages.slice(lastResponse+1).some(message=>message.role==="user"),state2=getVirtualModelState(this.sessionManager.getBranch(),model.provider,model.id),route=await this._modelRuntime.resolveModel(model,convertToLlm(context.messages),{reason:failed?"retry":userTurn?"user":"continuation",thinkingLevel,signal,failed,state:state2});if(route.state!==void 0&&route.state!==state2){let data={provider:model.provider,modelId:model.id,state:route.state},entry=this.sessionManager.getEntry(this.sessionManager.appendCustomEntry(VIRTUAL_MODEL_STATE_ENTRY,data));entry&&this._emit({type:"entry_appended",entry})}return this._exceedsCompactionThreshold(route.model,projection)&&(await this._runAutoCompaction("threshold",!1),{previous,context}=await prepare()),{...previous,context,model:route.model,thinkingLevel:route.thinkingLevel}}}async _dispatchTurnEndBoundary(message,toolResults){this._lastActivityOutcome=message.stopReason==="aborted"?"aborted":message.stopReason==="error"?"error":"completed";let messageEntryId=this._findPersistedMessageEntryId(message);if(!this._extensionRunner.hasHandlers("turn_end"))return!1;if(!messageEntryId)return this._extensionRunner.emitError({extensionPath:"<boundary>",event:"turn_end",error:"turn_end could not resolve the persisted assistant entry ID"}),!1;let toolResultEntryIds=toolResults.flatMap(result2=>{let entryId=this._findPersistedMessageEntryId(result2);return entryId?[entryId]:[]}),boundary=await this._extensionRunner.emitBoundary({type:"turn_end",turnIndex:this._turnIndex,message,toolResults,messageEntryId,toolResultEntryIds,outcome:this._lastActivityOutcome},entries=>this._buildBoundaryContext(entries,"turn_end"));return this._commitBoundaryDrafts(boundary.entries),boundary.continue&&!this._buildBoundaryContext([],"turn_end").canContinue?(this._reportInvalidBoundaryContinuation("turn_end"),!1):boundary.continue}_installAgentBoundaryHooks(){let previousFinishTurn=this.agent.finishTurn;this.agent.finishTurn=async(turn,signal)=>{this._boundaryDispatchedMessages.add(turn.message);let extensionContinue=await this._dispatchTurnEndBoundary(turn.message,turn.toolResults),previousDecision=await previousFinishTurn?.(turn,signal);if(previousDecision?.action==="end")return previousDecision;if(extensionContinue||previousDecision?.action==="continue")return{action:"continue"}}}_installAgentNextTurnRefresh(){let previousPrepareNextTurnWithContext=this.agent.prepareNextTurnWithContext??(this.agent.prepareNextTurn?async(_turn,signal)=>await this.agent.prepareNextTurn?.(signal):void 0);this.agent.prepareNextTurnWithContext=async(turn,signal)=>{let context=await this._compactBeforeNextAssistantResponse(turn.context),previousSnapshot=await previousPrepareNextTurnWithContext?.({...turn,context},signal),nextContext=previousSnapshot?.context??context,runOptions=this._runSystemPromptOptions??this._baseSystemPromptOptions,options=normalizeBuildSystemPromptOptions({...runOptions,selectedTools:this.getActiveToolNames(),toolSnippets:{...this._baseSystemPromptOptions.toolSnippets,...runOptions.toolSnippets},toolGuidelines:{...this._baseSystemPromptOptions.toolGuidelines,...runOptions.toolGuidelines}}),updateMessage=this._preparePromptAndToolLoadout(options,nextContext.messages);return this._runSystemPromptOptions=options,{...previousSnapshot,context:{...nextContext,tools:this.agent.state.tools.slice()},messages:updateMessage?[...previousSnapshot?.messages??[],updateMessage]:previousSnapshot?.messages,model:this.agent.state.model,thinkingLevel:this.agent.state.thinkingLevel}}}_refreshFinalizedContext(){let projection=this.sessionManager.buildSessionProjection();for(let entry of projection.entries)for(let message of entry.messages)this._entryIdsByMessage.set(message,entry.sourceEntry.id);this.agent.state.messages=projection.messages}_applyBoundaryDrafts(manager,drafts){let appended=[];for(let draft of drafts){let entryId;switch(draft.type){case"custom":entryId=manager.appendCustomEntry(draft.customType,draft.data);break;case"custom_message":entryId=manager.appendCustomMessageEntry(draft.customType,draft.content,draft.display,draft.details);break;case"context_edit":entryId=manager.appendContextEdit(draft.targetId,draft.replacement);break;case"compaction":{let tokensBefore=estimateProjectedContextTokens(manager.buildSessionProjection(),manager.getBranch()).tokens;entryId=manager.appendCompaction(draft.summary,draft.firstKeptEntryId,tokensBefore,draft.details,!0,draft.usage);break}}let entry=manager.getEntry(entryId);entry&&appended.push(entry)}return appended}_createBoundaryPreviewManager(drafts){let header2=this.sessionManager.getHeader();if(!header2)throw new Error("Session header is missing");let manager=SessionManager.inMemory(this._cwd,void 0,[header2,...this.sessionManager.getBranch()]);return this._applyBoundaryDrafts(manager,drafts),manager}_getPendingBoundaryMessages(){return[...this.agent.peekQueuedMessages(),...this._pendingCustomMessages]}_buildBoundaryContext(drafts,boundary){let projection=this._createBoundaryPreviewManager(drafts).buildSessionProjection(),pendingMessages=this._getPendingBoundaryMessages(),llmMessages=convertToLlm(projection.messages),finalRole=llmMessages[llmMessages.length-1]?.role,contextCanContinue=llmMessages.some(message=>message.role!=="system")&&finalRole!=="assistant",pendingCustomContext=this._pendingCustomMessages.length>0;return{contextEntries:projection.entries,contextMessages:projection.messages,llmMessages,pendingMessages,canContinue:contextCanContinue||pendingCustomContext||(boundary==="turn_end"?this.agent.hasQueuedMessages():finalRole==="assistant"&&this.agent.hasQueuedMessages())}}_commitBoundaryDrafts(drafts){let appended=this._applyBoundaryDrafts(this.sessionManager,drafts);this._refreshFinalizedContext();for(let entry of appended)this._emit({type:"entry_appended",entry})}_reportInvalidBoundaryContinuation(event){this._extensionRunner.emitError({extensionPath:"<boundary>",event,error:`${event} requested continuation without runnable model context`})}_emit(event){for(let l3 of this._eventListeners)l3(event)}_emitQueueUpdate(){this._emit({type:"queue_update",steering:[...this._steeringMessages],followUp:[...this._followUpMessages]})}async _emitSessionCompactFailed(event){this._extensionRunner.hasHandlers("session_compact_failed")&&await this._extensionRunner.emit({type:"session_compact_failed",...event})}_getIdleWaitPromise(){return this._idleWaitPromise||(this._idleWaitPromise=new Promise(resolve20=>{this._resolveIdleWait=resolve20})),this._idleWaitPromise}_resolveIdleWaitIfIdle(){if(!this.isIdle||!this._resolveIdleWait)return;let resolve20=this._resolveIdleWait;this._idleWaitPromise=void 0,this._resolveIdleWait=void 0,resolve20()}async _emitAgentSettled(){return this._withTasksPaused(()=>this._emitAgentSettledBody())}async _emitAgentSettledBody(){this._cacheWarmer?.onAgentSettled(),this._isAgentRunActive=!1,this._isEmittingAgentSettled=!0;try{let aborted=this._agentRunAbortRequested;await this._extensionRunner.emit({type:"agent_settled",aborted}),this._emit({type:"agent_settled",aborted})}finally{this._isEmittingAgentSettled=!1}let deferred=this._deferredSettledActions.splice(0);if(deferred.length>0){try{for(let action of deferred)await action()}finally{this._resolveIdleWaitIfIdle()}return}this._resolveIdleWaitIfIdle()}_messagePersisted(message){if(message.role==="custom"){let pendingIndex=this._pendingNextTurnMessages.indexOf(message);pendingIndex!==-1&&this._pendingNextTurnMessages.splice(pendingIndex,1)}this._tasksHost.delivery.messagePersisted(message)}_willRetryAfterAgentEnd(event){if(this._agentRunAbortRequested)return!1;let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled||this._retryAttempt>=settings2.maxRetries)return!1;for(let i=event.messages.length-1;i>=0;i--){let message=event.messages[i];if(message.role==="assistant")return this._isRetryableError(message)}return!1}_findPersistedMessageEntryId(message){let mapped=this._entryIdsByMessage.get(message);if(mapped)return mapped;for(let entry of[...this.sessionManager.getBranch()].reverse())if(entry.type==="message"&&entry.message===message)return entry.id;let messageIndex=this.agent.state.messages.indexOf(message);if(messageIndex<0)return;let projection=this.sessionManager.buildSessionProjection(),projectedIndex=0;for(let entry of projection.entries)for(let i=0;i<entry.messages.length;i++){if(projectedIndex===messageIndex)return this._entryIdsByMessage.set(message,entry.sourceEntry.id),entry.sourceEntry.id;projectedIndex++}}_omitRecoveryAttempt(message){let toolCallIds=new Set(message.content.flatMap(block=>block.type==="toolCall"?[block.id]:[])),entryId=this._findPersistedMessageEntryId(message),messages=this.agent.state.messages,index3=messages.findIndex(m2=>m2===message||entryId!==void 0&&this._entryIdsByMessage.get(m2)===entryId),toolResults=[];for(let m2 of index3<0?[]:messages.slice(index3+1)){if(m2.role==="assistant")break;m2.role==="toolResult"&&toolCallIds.has(m2.toolCallId)&&toolResults.push(m2)}let targets=[message,...toolResults],targetIds=targets.map(target=>this._findPersistedMessageEntryId(target));if(targets.some((target,index4)=>targetIds[index4]===void 0&&this.agent.state.messages.includes(target)))throw new Error("Cannot persist recovery omission because a projected message has no source entry");for(let targetId of targetIds){if(!targetId)continue;let editId=this.sessionManager.appendContextEdit(targetId,null),entry=this.sessionManager.getEntry(editId);entry&&this._emit({type:"entry_appended",entry})}this._refreshFinalizedContext()}_findLastAssistantMessage(){let messages=this.agent.state.messages;for(let i=messages.length-1;i>=0;i--){let msg=messages[i];if(msg.role==="assistant")return msg}}_replaceMessageInPlace(target,replacement){if(target===replacement)return;let targetRecord=target;for(let key of Object.keys(targetRecord))delete targetRecord[key];Object.assign(targetRecord,replacement)}async _emitExtensionEvent(event){if(event.type==="agent_start")this._turnIndex=0,await this._extensionRunner.emit({type:"agent_start"});else if(event.type==="agent_end")await this._extensionRunner.emit({type:"agent_end",messages:event.messages});else if(event.type==="turn_start"){let extensionEvent={type:"turn_start",turnIndex:this._turnIndex,timestamp:Date.now()};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="turn_end")event.message.role==="assistant"&&!this._boundaryDispatchedMessages.delete(event.message)&&await this._dispatchTurnEndBoundary(event.message,event.toolResults),this._turnIndex++;else if(event.type==="message_start"){let extensionEvent={type:"message_start",message:event.message};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_update"){let extensionEvent={type:"message_update",message:event.message,assistantMessageEvent:event.assistantMessageEvent};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="message_end"){let extensionEvent={type:"message_end",message:event.message},replacement=await this._extensionRunner.emitMessageEnd(extensionEvent);if(replacement){let normalized=(replacement.role==="user"||replacement.role==="assistant"||replacement.role==="toolResult"||replacement.role==="custom")&&replacement.content==null?{...replacement,content:[]}:replacement;this._replaceMessageInPlace(event.message,normalized)}}else if(event.type==="tool_execution_start"){let extensionEvent={type:"tool_execution_start",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_update"){let extensionEvent={type:"tool_execution_update",toolCallId:event.toolCallId,toolName:event.toolName,args:event.args,partialResult:event.partialResult};await this._extensionRunner.emit(extensionEvent)}else if(event.type==="tool_execution_end"){let extensionEvent={type:"tool_execution_end",toolCallId:event.toolCallId,toolName:event.toolName,result:event.result,isError:event.isError,...event.durationMs===void 0?{}:{durationMs:event.durationMs}};await this._extensionRunner.emit(extensionEvent)}}subscribe(listener){return this._eventListeners.push(listener),()=>{let index3=this._eventListeners.indexOf(listener);index3!==-1&&this._eventListeners.splice(index3,1)}}_disconnectFromAgent(){this._unsubscribeAgent&&(this._unsubscribeAgent(),this._unsubscribeAgent=void 0)}dispose(){this._tasksHost.dispose();try{this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this.abortBash(),this.agent.abort()}catch{}this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."),this._disconnectFromAgent(),this._eventListeners=[],this._cacheWarmer&&(this._cacheWarmer.onWarmed=void 0,this._cacheWarmer.cancel()),cleanupSessionResources(this.sessionId)}refreshContext(){this._refreshFinalizedContext()}get state(){return this.agent.state}get cacheWarmingStatus(){return this._cacheWarmer?.status}setCacheWarmingMode(mode){this.settingsManager.setCacheWarmingMode(mode),this._cacheWarmer?.onModeChanged()}get model(){return this.agent.state.model}get thinkingLevel(){return this.agent.state.thinkingLevel}get routedModel(){if(!this.model||!isVirtualModel(this.model))return;let latest=findLatestResponse(this.agent.state.messages),model=latest&&this._modelRuntime.getPhysicalModel(latest.provider,latest.model);return model&&{model,thinkingLevel:latest?.thinkingLevel}}get isStreaming(){return this._isAgentRunActive}get isIdle(){return!this._isAgentRunActive&&!this.isCompacting}get systemPrompt(){return buildSystemPrompt(this._runSystemPromptOptions??this._baseSystemPromptOptions)}get retryAttempt(){return this._retryAttempt}getActiveToolNames(){return this.agent.state.tools.map(t=>t.name)}getCallableToolNames(){return this._getCallableTools().map(t=>t.name)}getAllTools(){return Array.from(this._toolDefinitions.values()).map(({definition,sourceInfo})=>({name:definition.name,description:definition.description,parameters:definition.parameters,promptGuidelines:definition.promptGuidelines,exposure:this._getToolExposure(definition.name),...definition.namespace?{namespace:definition.namespace}:{},...definition.annotations?{annotations:{...definition.annotations}}:{},...definition.reachesTools?{reachesTools:definition.reachesTools}:{},sourceInfo}))}getToolDefinition(name){return this._toolDefinitions.get(name)?.definition}setActiveToolsByName(toolNames){let previous=this.getActiveToolNames();this._setActiveTools(toolNames);let active=new Set(this.getActiveToolNames());previous.some(name=>!active.has(name))&&this._pendingToolNames.clear()}_setActiveTools(toolNames){let tools=this._applyToolLoadout(toolNames);for(let tool of tools)this._pendingToolNames.delete(tool.name);this._rebuildSystemPrompt(tools.map(tool=>tool.name))}_isAllowedTool(name){return this._excludedTools?.(name)?!1:!this._allowedTools||this._allowedTools(name)?!0:!this._allowlistFiltersMcp&&isMcpToolName(name)}_isActivatable(name){return!this._allowedTools||this._allowedTools(name)||!isMcpToolName(name)?!0:this._getToolExposure(name)!=="direct"&&this._toolRegistry.has("tool_search")}_getToolExposure(name){return this._toolDefinitions.get(name)?.definition.exposure??"direct"}_getCallableTools(active=new Set(this.getActiveToolNames())){return[...this._toolRegistry.values()].filter(tool=>{let exposure=this._getToolExposure(tool.name);return exposure==="codemode"||exposure==="deferred"||exposure==="direct"&&active.has(tool.name)})}_applyToolLoadout(toolNames){let tools=[...new Set(toolNames)].flatMap(name=>{let tool=this._toolRegistry.get(name);return tool&&this._getToolExposure(name)!=="hidden"&&this._isActivatable(name)?[tool]:[]}),hooks=tools.flatMap(tool=>{let entry=this._toolDefinitions.get(tool.name);return entry?.definition.prepareLoadout?[entry]:[]}),hidden=new Set,declared=tools;if(hooks.length>0){let loadout={declared:tools,callable:this._getCallableTools(new Set(tools.map(tool=>tool.name))),registered:[...this._toolRegistry.values()],getExposure:name=>this._getToolExposure(name),getNamespace:name=>this._toolDefinitions.get(name)?.definition.namespace,getPromptGuidelines:name=>this._toolPromptGuidelines.get(name)??[]},descriptions=new Map;for(let{definition,sourceInfo}of hooks)try{let changes=definition.prepareLoadout?.(loadout);for(let[name,description]of Object.entries(changes?.descriptions??{}))descriptions.set(name,description);for(let name of changes?.hiddenDeclarations??[])hidden.add(name)}catch(error){this._extensionRunner.emitError({extensionPath:sourceInfo.path,event:"prepare_loadout",error:error instanceof Error?error.message:String(error),stack:error instanceof Error?error.stack:void 0})}declared=tools.map(tool=>{let description=descriptions.get(tool.name);return description===void 0?tool:{...tool,description}})}return this._hiddenDeclarations=hidden,this.agent.state.tools=declared,declared}get isCompacting(){return this._autoCompactionAbortController!==void 0||this._compactionAbortController!==void 0||this._branchSummaryAbortController!==void 0}get messages(){return this.agent.state.messages}get steeringMode(){return this.agent.steeringMode}get followUpMode(){return this.agent.followUpMode}get sessionFile(){return this.sessionManager.getSessionFile()}get sessionId(){return this.sessionManager.getSessionId()}get sessionName(){return this.sessionManager.getSessionName()}get scopedModels(){return this._scopedModels}setScopedModels(scopedModels){this._scopedModels=scopedModels}get promptTemplates(){return this._resourceLoader.getPrompts().prompts}_normalizePromptSnippet(text2){if(!text2)return;let oneLine2=text2.replace(/[\r\n]+/g," ").replace(/\s+/g," ").trim();return oneLine2.length>0?oneLine2:void 0}_normalizePromptGuidelines(guidelines){if(!guidelines||guidelines.length===0)return[];let unique=new Set;for(let guideline of guidelines){let normalized=guideline.trim();normalized.length>0&&unique.add(normalized)}return Array.from(unique)}_rebuildSystemPrompt(toolNames){let validToolNames=toolNames.filter(name=>this._toolRegistry.has(name)),toolSnippets={};for(let name of this._toolRegistry.keys()){let snippet=this._toolPromptSnippets.get(name);snippet&&(toolSnippets[name]=snippet)}let loaderSystemPrompt=this._resourceLoader.getSystemPrompt(),loaderAppendSystemPrompt=this._resourceLoader.getAppendSystemPrompt(),appendSystemPrompt=loaderAppendSystemPrompt.length>0?loaderAppendSystemPrompt.join(`
|
|
1083
1068
|
|
|
1084
1069
|
`):"",loadedSkills=this._resourceLoader.getSkills().skills,loadedContextFiles=this._resourceLoader.getAgentsFiles().agentsFiles;this._baseSystemPromptOptions=normalizeBuildSystemPromptOptions({cwd:this._cwd,skills:loadedSkills,contextFiles:loadedContextFiles,customPrompt:loaderSystemPrompt,appendSystemPrompt,selectedTools:validToolNames,hiddenTools:[...this._hiddenDeclarations],toolSnippets,toolGuidelines:Object.fromEntries(this._toolPromptGuidelines)})}_preparePromptAndToolLoadout(options,messages=this.agent.state.messages){options.selectedTools=this._applyToolLoadout(options.selectedTools).map(tool=>tool.name),options.hiddenTools=[...this._hiddenDeclarations];let sections=diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections??{},buildSystemPromptSections(options));return sections?{role:"system",content:"",sections,timestamp:Date.now()}:void 0}_installHiddenDeclarationsProjection(){let previousTransformContext=this.agent.transformContext;this.agent.transformContext=async(messages,signal)=>{let transformed=previousTransformContext?await previousTransformContext(messages,signal):messages,hidden=this._hiddenDeclarations;return hidden.size===0?transformed:transformed.map(message=>{if(message.role!=="system"||!message.toolsAdded&&!message.toolsRemoved)return message;let{toolsAdded,toolsRemoved,...rest}=message,added=toolsAdded?.filter(tool=>!hidden.has(tool.name))??[],removed=toolsRemoved?.filter(tool=>!hidden.has(tool.name))??[];return{...rest,...added.length>0?{toolsAdded:added}:{},...removed.length>0?{toolsRemoved:removed}:{}}})}}_installAgentForcedPromptProjection(){let previousTransformContext=this.agent.transformContext;this.agent.transformContext=async(messages,signal)=>{let transformed=previousTransformContext?await previousTransformContext(messages,signal):messages,forced=this._runSystemPromptOptions?.forceSystemPrompt;if(forced===void 0)return transformed;let current=getCurrentSystemMessage(transformed);return[{role:"system",content:forced,...current?.toolsAdded?{toolsAdded:current.toolsAdded}:{},timestamp:current?.timestamp??Date.now()},...transformed.filter(message=>message.role!=="system")]}}_installTaskContextReminderProjection(){let previousTransformContext=this.agent.transformContext;this.agent.transformContext=async(messages,signal)=>{let transformed=previousTransformContext?await previousTransformContext(messages,signal):messages;return this._tasksHost.projectContextReminder(transformed)}}_restoreToolsFromTranscript(modifiers2=[]){this._pendingToolNames.clear();let systemMessages=this.sessionManager.getBranch().flatMap(entry=>entry.type==="message"&&entry.message.role==="system"?[entry.message]:[]);if(systemMessages.length===0)return;let mentioned=new Set(systemMessages.flatMap(message=>[...message.toolsAdded??[],...message.toolsRemoved??[]]).map(tool=>tool.name)),newTools=[...this._toolRegistry.keys()].filter(name=>!mentioned.has(name)&&!this._baseToolDefinitions.has(name)&&this._isActivatedOnRegistration(name)),names2=applyToolModifiers([...getCurrentTools(systemMessages).map(tool=>tool.name),...newTools],modifiers2);this._pendingToolNames=new Set(names2.filter(name=>this._isAllowedTool(name))),this._setActiveTools(names2)}async _startRun(trigger,onStarted){this._isAgentRunActive=!0,this._agentRunAbortRequested=!1;let messages;try{messages=await this._prepareRun(trigger)}catch(error){throw this._isAgentRunActive=!1,this._flushPendingBashMessages(),this._flushPendingCustomMessages(),this._resolveIdleWaitIfIdle(),error}this._flushPendingBashMessages(),this._flushPendingCustomMessages(),onStarted?.(),this._failedResponse=void 0,this._recordSelection(),this._pendingToolNames.clear();try{for(await this.agent.prompt(messages);!this._agentRunAbortRequested;){if(await this._handlePostAgentRun()){if(this._agentRunAbortRequested)break;await this.agent.continue();continue}if(this._agentRunAbortRequested||!await this._runBeforeSettleBoundary()||this._agentRunAbortRequested)break;await this.agent.continue()}}finally{this._agentRunAbortRequested&&this._finishCancelledRetry(),this._failedResponse=void 0,this._runSystemPromptOptions=void 0,this._flushPendingBashMessages(),this._flushPendingCustomMessages(),await this._emitAgentSettled()}}async _prepareRun(trigger){let lastAssistant=this._findLastAssistantMessage();lastAssistant&&await this._checkCompaction(lastAssistant,!1);let selectedToolsBefore=this._baseSystemPromptOptions.selectedTools,result2=await this._extensionRunner.emitBeforeAgentStart(trigger,this._baseSystemPromptOptions);result2.systemPromptOptions.selectedTools.length!==selectedToolsBefore.length||result2.systemPromptOptions.selectedTools.some((name,index3)=>name!==selectedToolsBefore[index3])||(result2.systemPromptOptions.selectedTools=this.getActiveToolNames());let messages=[];if(trigger.messageType==="custom")messages.push(trigger.message);else{let normalized=await this._normalizePromptImages(trigger.images),text2=normalized.hints.length>0?`${trigger.prompt}
|
|
@@ -1091,7 +1076,7 @@ ${body2}
|
|
|
1091
1076
|
</skill>`;return args?`${skillBlock}
|
|
1092
1077
|
|
|
1093
1078
|
${args}`:skillBlock}catch(err){return this._extensionRunner.emitError({extensionPath:skill.filePath,event:"skill_expansion",error:err instanceof Error?err.message:String(err)}),text2}}async _queueUserInput(text2,images,behavior,source){text2.startsWith("/")&&this._throwIfExtensionCommand(text2);let processedInput=await this._runInputHandlers(text2,images,source,this.isStreaming?behavior:void 0);if(!processedInput)return"handled";let expandedText=this._expandSkillCommand(processedInput.text);return expandedText=expandPromptTemplate(expandedText,[...this.promptTemplates]),behavior==="steer"?await this._queueSteer(expandedText,processedInput.images):await this._queueFollowUp(expandedText,processedInput.images),"queued"}async steer(text2,images,options){return this._queueUserInput(text2,images,"steer",options?.source??"interactive")}async followUp(text2,images,options){return this._queueUserInput(text2,images,"followUp",options?.source??"interactive")}async _queueSteer(text2,images){this._steeringMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.steer({role:"user",content,timestamp:Date.now()}),this._tasksHost.interruptWaits()}async _queueFollowUp(text2,images){this._followUpMessages.push(text2),this._emitQueueUpdate();let content=[{type:"text",text:text2}];images&&content.push(...images),this.agent.followUp({role:"user",content,timestamp:Date.now()})}_throwIfExtensionCommand(text2){let spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);if(this._extensionRunner.getCommand(commandName))throw new Error(`Extension command "/${commandName}" cannot be queued. Use prompt() or execute the command when not streaming.`)}async sendCustomMessage(message,options){let appMessage={role:"custom",customType:message.customType,content:message.content??[],display:message.display,details:message.details,timestamp:Date.now()};if(options?.deliverAs==="nextTurn")this._pendingNextTurnMessages.push(appMessage);else if(this.isStreaming&&options?.triggerTurn!==!1)options?.deliverAs==="followUp"?this.agent.followUp(appMessage):(this.agent.steer(appMessage),this._tasksHost.interruptWaits());else if(options?.triggerTurn){if(this._isEmittingAgentSettled){this._deferredSettledActions.push(async()=>await this.sendCustomMessage(message,options));return}await this._startRun({messageType:"custom",message:appMessage})}else this.isStreaming?this._pendingCustomMessages.push(appMessage):this._appendCustomMessage(appMessage)}_appendCustomMessage(appMessage){this.sessionManager.appendCustomMessageEntry(appMessage.customType,appMessage.content,appMessage.display,appMessage.details),this._messagePersisted(appMessage),this._refreshFinalizedContext(),this._emit({type:"message_start",message:appMessage}),this._emit({type:"message_end",message:appMessage})}_flushPendingCustomMessages(){if(this._pendingCustomMessages.length===0)return;let pending=this._pendingCustomMessages;this._pendingCustomMessages=[];for(let appMessage of pending)this._appendCustomMessage(appMessage)}async sendUserMessage(content,options){let text2,images;if(typeof content=="string")text2=content;else{let textParts=[];images=[];for(let part of content)part.type==="text"?textParts.push(part.text):images.push(part);text2=textParts.join(`
|
|
1094
|
-
`),images.length===0&&(images=void 0)}await this.prompt(text2,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];return this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues(),this._tasksHost.delivery.queueCleared(),this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._isAgentRunActive&&(this._agentRunAbortRequested=!0),this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this._isBeforeSettle&&(this._abortDuringBeforeSettle=!0),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source})}async setModel(model,options={}){if(!await this._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model);this.agent.state.model=model,this.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model.provider,model.id),this._addPersistedDefaultToNonEmptyScope(model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;this._scopedModels=[...this._scopedModels,{model}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||this.settingsManager.setEnabledModels([...enabledModels,modelReference])}async cycleModel(direction="forward",options={}){return this._scopedModels.length>0?this._cycleScopedModel(direction,options):this._cycleAvailableModel(direction,options)}async _cycleScopedModel(direction,options){let availableIds=new Set(this._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=this._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=this.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return this.agent.state.model=next.model,this.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),this._addPersistedDefaultToNonEmptyScope(next.model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:this.thinkingLevel,isScoped:!0}}async _cycleAvailableModel(direction,options){let availableModels=this._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=this.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(nextModel);return this.agent.state.model=nextModel,this.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),this._addPersistedDefaultToNonEmptyScope(nextModel)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:this.thinkingLevel,isScoped:!1}}setThinkingLevel(level,options={}){let availableLevels=this.getAvailableThinkingLevels(),effectiveLevel=availableLevels.includes(level)?level:this._clampThinkingLevel(level,availableLevels),previousLevel=this.agent.state.thinkingLevel,isChanging=effectiveLevel!==previousLevel;this.agent.state.thinkingLevel=effectiveLevel,options.persist&&this.settingsManager.setDefaultThinkingLevel(level),isChanging&&(this.sessionManager.appendThinkingLevelChange(effectiveLevel),this._emit({type:"thinking_level_changed",level:effectiveLevel}),this._extensionRunner.emit({type:"thinking_level_select",level:effectiveLevel,previousLevel}))}cycleThinkingLevel(options={}){if(!this.supportsThinking())return;let levels=this.getAvailableThinkingLevels(),nextIndex=(levels.indexOf(this.thinkingLevel)+1)%levels.length,nextLevel=levels[nextIndex];return this.setThinkingLevel(nextLevel,options),nextLevel}getAvailableThinkingLevels(){return this.model?getSupportedThinkingLevels(this.model):[...THINKING_LEVEL_OPTIONS]}supportsThinking(){return!!this.model?.reasoning}_getThinkingLevelForModelSwitch(targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=this.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return this.settingsManager.getDefaultThinkingLevel()??this.thinkingLevel??DEFAULT_THINKING_LEVEL}_clampThinkingLevel(level,_availableLevels){return this.model?clampThinkingLevel(this.model,level):"off"}syncQueueModesFromSettings(){this.agent.steeringMode=this.settingsManager.getSteeringMode(),this.agent.followUpMode=this.settingsManager.getFollowUpMode()}setSteeringMode(mode){this.agent.steeringMode=mode,this.settingsManager.setSteeringMode(mode)}setFollowUpMode(mode){this.agent.followUpMode=mode,this.settingsManager.setFollowUpMode(mode)}async _runDefaultCompaction(preparation,model,customInstructions,signal,reason){let request=await this._getSummarizationRequestAuth(model,signal);return compact(preparation,request.model,request.apiKey,request.headers,customInstructions,signal,request.thinkingLevel,this.agent.streamFunction,request.env,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._withTasksPaused(()=>this._compactBody(customInstructions))}async _compactBody(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings2=this.settingsManager.getCompactionSettings(this.routedModel?.model??model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result2=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result2?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result2?.compaction&&(extensionCompaction=result2.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result2=await this._runDefaultCompaction(preparation,model,customInstructions,this._compactionAbortController.signal,"manual");summary=result2.summary,firstKeptEntryId=result2.firstKeptEntryId,tokensBefore=result2.tokensBefore,usage=result2.usage,details=result2.details}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage),this._tasksHost.noteCompaction();let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason:"manual",willRetry:!1});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage9=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage9,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0){let settings2=this.settingsManager.getCompactionSettings(this._modelForMessage(assistantMessage)??this.model);if(!settings2.enabled||skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let messageModel=this._modelForMessage(assistantMessage),sameModel=messageModel!==void 0,contextWindow=(messageModel??this.model)?.contextWindow??0,compactionEntry=getLatestCompactionEntry(this.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let currentProjection=this.sessionManager.buildSessionProjection(),assistantEntryId=this._findPersistedMessageEntryId(assistantMessage),assistantIsProjected=assistantEntryId===void 0||currentProjection.entries.some(entry=>entry.sourceEntry.id===assistantEntryId&&entry.messages.some(message=>message.role==="assistant")),branch=this.sessionManager.getBranch(),assistantIndex=assistantEntryId?branch.findIndex(entry=>entry.id===assistantEntryId):-1,entriesAfterAssistant=assistantIndex>=0?branch.slice(assistantIndex+1):[],hasPostAssistantContextEdit=entriesAfterAssistant.some(entry=>entry.type==="context_edit"),latestAssistantEdit=entriesAfterAssistant.filter(entry=>entry.type==="context_edit"&&entry.targetId===assistantEntryId).at(-1),assistantRetainedForExplicitRecovery=assistantEntryId===void 0||!entriesAfterAssistant.some(entry=>entry.type==="compaction")&&latestAssistantEdit?.replacement!==null,assistantUsageMatchesProjection=assistantIsProjected&&!hasPostAssistantContextEdit,explicitOverflow=assistantMessage.stopReason==="error"&&isContextOverflow(assistantMessage),contextOverflow=sameModel&&(explicitOverflow&&assistantRetainedForExplicitRecovery||assistantUsageMatchesProjection&&isContextOverflow(assistantMessage,contextWindow)),recoverableLength=sameModel&&assistantIsProjected&&isRecoverableLength(assistantMessage,messageModel.maxTokens);if(contextOverflow||recoverableLength){let willRetry=assistantMessage.stopReason!=="stop";if(!willRetry)return await this._runAutoCompaction("overflow",!1);if(this._overflowRecoveryAttempted){let errorMessage9=contextOverflow?"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.":"Truncated response recovery failed after one compact-and-retry attempt.";return this._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage9,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage);let retry=await this._runAutoCompaction("overflow",willRetry);return retry&&(this._failedResponse=assistantMessage),retry}let contextTokens,projection=currentProjection,hasContextEdits=projection.entries.some(entry=>entry.sourceEntry.type==="context_edit"),directContextTokens=assistantMessage.usage?calculateContextTokens(assistantMessage.usage):0;if(hasContextEdits)contextTokens=estimateProjectedContextTokens(projection,branch).tokens;else if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens2(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){return this._withTasksPaused(()=>this._runAutoCompactionBody(reason,willRetry))}async _runAutoCompactionBody(reason,willRetry){let model=this.model,settings2=this.settingsManager.getCompactionSettings(this.routedModel?.model??model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)return!1;abortController=new AbortController,this._autoCompactionAbortController=abortController,started=!0,this._emit({type:"compaction_start",reason}),abortController.signal.throwIfAborted();let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let extensionResult=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions:void 0,reason,willRetry,signal:abortController.signal});if(extensionResult?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");extensionResult?.compaction&&(extensionCompaction=extensionResult.compaction,fromExtension=!0)}abortController.signal.throwIfAborted();let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let compactResult=await this._runDefaultCompaction(preparation,model,void 0,abortController.signal,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage),this._tasksHost.noteCompaction();let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry});let result2={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result:result2,aborted:!1,willRetry}),willRetry?!0:this.agent.hasQueuedMessages()}catch(error){let message=error instanceof Error?error.message:"compaction failed",aborted=abortController?.signal.aborted===!0||cancelledByExtension;if(started){let errorMessage9=aborted?void 0:reason==="overflow"?`Context overflow recovery failed: ${message}`:`Auto-compaction failed: ${message}`;this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage9,aborted,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController===abortController&&(this._autoCompactionAbortController=void 0),this._resolveIdleWaitIfIdle()}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){return this._withTasksPaused(()=>this._bindExtensionsBody(bindings))}async _bindExtensionsBody(bindings){bindings.tasksEnabled!==void 0&&(this._tasksHost.setEnabled(bindings.tasksEnabled),this._refreshToolRegistry()),bindings.uiContext!==void 0&&(this._extensionUIContext=bindings.uiContext),bindings.mode!==void 0&&(this._extensionMode=bindings.mode),bindings.commandContextActions!==void 0&&(this._extensionCommandContextActions=bindings.commandContextActions),bindings.abortHandler!==void 0&&(this._extensionAbortHandler=bindings.abortHandler),bindings.shutdownHandler!==void 0&&(this._extensionShutdownHandler=bindings.shutdownHandler),bindings.onError!==void 0&&(this._extensionErrorListener=bindings.onError),this._applyExtensionBindings(this._extensionRunner),await this._extensionRunner.emit(this._sessionStartEvent),this._extensionRunner.reportUnhandledMcpServers(),await this.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup")}async extendResourcesFromExtensions(reason){if(!this._extensionRunner.hasHandlers("resources_discover"))return;let{skillPaths,promptPaths,themePaths}=await this._extensionRunner.emitResourcesDiscover(this._cwd,reason);if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:this.buildExtensionResourcePaths(skillPaths),promptPaths:this.buildExtensionResourcePaths(promptPaths),themePaths:this.buildExtensionResourcePaths(themePaths)};this._resourceLoader.extendResources(extensionPaths),this._rebuildSystemPrompt(this.getActiveToolNames())}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source=this.getExtensionSourceLabel(entry.extensionPath),baseDir=isSyntheticPath(entry.extensionPath)?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return isSyntheticPath(extensionPath)?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename9(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(err=>{runner.emitError({extensionPath:"<runtime>",event:"send_message",error:err instanceof Error?err.message:String(err)})})},sendUserMessage:(content,options)=>{this.sendUserMessage(content,options).catch(err=>{runner.emitError({extensionPath:"<runtime>",event:"send_user_message",error:err instanceof Error?err.message:String(err)})})},appendEntry:(customType,data)=>{let entryId=this.sessionManager.appendCustomEntry(customType,data),entry=this.sessionManager.getEntry(entryId);entry&&this._emit({type:"entry_appended",entry})},setSessionName:name=>{this.setSessionName(name)},getSessionName:()=>this.sessionManager.getSessionName(),setLabel:(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label)},getActiveTools:()=>this.getActiveToolNames(),getAllTools:()=>this.getAllTools(),getSettings:()=>this.settingsManager.getSettings(),setActiveTools:toolNames=>this.setActiveToolsByName(toolNames),refreshTools:()=>this._refreshToolRegistry(),getCommands,setModel:async model=>this._modelRuntime.hasConfiguredAuth(model.provider)?(await this.setModel(model),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{getTasks:()=>this.tasks,getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),getContextSnapshot:()=>this.getContextSnapshot(),compact:options=>{(async()=>{try{let result2=await this.compact(options?.customInstructions);options?.onComplete?.(result2)}catch(error){let err=error instanceof Error?error:new Error(String(error));options?.onError?.(err)}})()},getSystemPrompt:()=>this.systemPrompt,getSystemPromptOptions:()=>this._baseSystemPromptOptions,executeTool:(callerId,name,args,options)=>this._executeNestedToolCall(callerId,name,args,options),getCallableTools:()=>this._getCallableTools()},{registerProvider:(name,config)=>{this._modelRuntime.registerProvider(name,config),this._refreshCurrentModelFromRegistry()},registerNativeProvider:provider=>{this._modelRuntime.registerNativeProvider(provider),this._refreshCurrentModelFromRegistry()},unregisterProvider:name=>{this._modelRuntime.unregisterProvider(name),this._refreshCurrentModelFromRegistry()},registerVirtualModel:definition=>{this._modelRuntime.registerVirtualModel(definition),this._refreshCurrentModelFromRegistry()},unregisterVirtualModel:(provider,id)=>{this._modelRuntime.unregisterVirtualModel(provider,id),this._refreshCurrentModelFromRegistry()}})}_refreshToolRegistry(options){let previousActivatedOnRegistration=new Set([...this._toolRegistry.keys()].filter(name=>this._isActivatedOnRegistration(name))),previousActiveToolNames=this.getActiveToolNames(),allowedTools=this._allowedTools,allCustomTools=[...this._extensionRunner.getAllRegisteredTools(),...this._customTools.map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<sdk:${definition.name}>`,{source:"sdk"})}))].filter(tool=>this._isAllowedTool(tool.definition.name)),definitionRegistry=new Map(Array.from(this._baseToolDefinitions.entries()).filter(([name])=>this._isAllowedTool(name)).map(([name,definition])=>[name,{definition,sourceInfo:createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`,{source:"builtin"})}]));for(let tool of allCustomTools)definitionRegistry.set(tool.definition.name,{definition:tool.definition,sourceInfo:tool.sourceInfo});this._toolDefinitions=definitionRegistry,this._toolPromptSnippets=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let snippet=this._normalizePromptSnippet(definition.promptSnippet);return snippet?[definition.name,snippet]:void 0}).filter(entry=>entry!==void 0)),this._toolPromptGuidelines=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let guidelines=this._normalizePromptGuidelines(definition.promptGuidelines);return guidelines.length>0?[definition.name,guidelines]:void 0}).filter(entry=>entry!==void 0));let runner=this._extensionRunner,wrappedExtensionTools=wrapRegisteredTools(allCustomTools,runner),wrappedBuiltInTools=wrapRegisteredTools(Array.from(this._baseToolDefinitions.values()).filter(definition=>this._isAllowedTool(definition.name)).map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`,{source:"builtin"})})),runner),toolRegistry=new Map(wrappedBuiltInTools.map(tool=>[tool.name,tool]));for(let tool of wrappedExtensionTools)toolRegistry.set(tool.name,tool);this._toolRegistry=toolRegistry;let nextActiveToolNames=(options?.activeToolNames?[...options.activeToolNames]:[...previousActiveToolNames]).filter(name=>this._isAllowedTool(name));if(allowedTools)for(let toolName of this._toolRegistry.keys())allowedTools(toolName)&&this._isDeclarable(toolName)&&nextActiveToolNames.push(toolName);else if(options?.includeAllExtensionTools)for(let tool of wrappedExtensionTools)this._isActivatedOnRegistration(tool.name)&&nextActiveToolNames.push(tool.name);else if(!options?.activeToolNames)for(let toolName of this._toolRegistry.keys())!previousActivatedOnRegistration.has(toolName)&&this._isActivatedOnRegistration(toolName)&&nextActiveToolNames.push(toolName);nextActiveToolNames.push(...this._pendingToolNames),this.tasks.enabled&&this._initialActiveToolNames?.length!==0&&this._toolRegistry.has("tasks")&&this._isAllowedTool("tasks")&&nextActiveToolNames.push("tasks"),this._setActiveTools([...new Set(nextActiveToolNames)])}_isDeclarable(name){let exposure=this._getToolExposure(name);return exposure==="direct"||exposure==="model-only"}_isActivatedOnRegistration(name){return this._isDeclarable(name)&&this._toolDefinitions.get(name)?.definition.defaultActive!==!1}_buildRuntime(options){let autoResizeImages=this.settingsManager.getImageAutoResize(),shellCommandPrefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),baseToolDefinitions=this._baseToolsOverride?Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name,tool])=>[name,createToolDefinitionFromAgentTool(tool)])):createAllToolDefinitions(this._cwd,{read:{autoResizeImages},bash:{commandPrefix:shellCommandPrefix,shellPath}});this._baseToolDefinitions=new Map(Object.entries(baseToolDefinitions).map(([name,tool])=>[name,tool])),this._baseToolDefinitions.set("tasks",createTasksToolDefinition((callId,taskId)=>this._tasksHost.delivery.prepareWait(callId,taskId),()=>this._tasksHost.waitInterruptSignal));let extensionsResult=this._resourceLoader.getExtensions();if(options.flagValues)for(let[name,value]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value);this._extensionRunner=new ExtensionRunner(extensionsResult.extensions,extensionsResult.runtime,this._cwd,this.sessionManager,new ModelRegistry(this._modelRuntime)),this._extensionRunnerRef&&(this._extensionRunnerRef.current=this._extensionRunner),this._bindExtensionCore(this._extensionRunner),this._applyExtensionBindings(this._extensionRunner);let defaultActiveToolNames=this._baseToolsOverride?Object.keys(this._baseToolsOverride):["read","bash","edit","write"],baseActiveToolNames=options.activeToolNames??defaultActiveToolNames;this._refreshToolRegistry({activeToolNames:baseActiveToolNames,includeAllExtensionTools:options.includeAllExtensionTools})}async reload(options){return this._withTasksPaused(()=>this._reloadBody(options))}async _reloadBody(options){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();this.tasks.close(),await Promise.all([this.tasks.shutdown(),this.abort()]),await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate();let getDefaultTools=()=>this._usesDefaultTools?applyToolModifiers(this.settingsManager.getDefaultTools()??DEFAULT_TOOL_NAMES,this._defaultToolModifiers):[],previousDefaultTools=new Set(getDefaultTools());await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._tasksHost.replaceService();let addedDefaultTools=getDefaultTools().filter(name=>!previousDefaultTools.has(name));for(let name of this.getActiveToolNames())this._pendingToolNames.add(name);this._buildRuntime({activeToolNames:[...this.getActiveToolNames(),...addedDefaultTools],flagValues:previousFlagValues,includeAllExtensionTools:!0}),(this.tasks.enabled||this._extensionUIContext||this._extensionCommandContextActions||this._extensionShutdownHandler||this._extensionErrorListener)&&(await options?.beforeSessionStart?.(),await this._extensionRunner.emit({type:"session_start",reason:"reload"}),this._extensionRunner.reportUnhandledMcpServers(),await this.extendResourcesFromExtensions("reload"))}_isRetryableError(message){return isContextOverflow(message,(this._modelForMessage(message)??this.model)?.contextWindow??0)?!1:isRetryableAssistantError(message)}_summarizationRetryCallbacks(source){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage9)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage9})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}_finishCancelledRetry(){if(this._retryAttempt===0)return;let attempt2=this._retryAttempt;this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"})}async _prepareRetry(message){let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings2.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings2,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep3(delayMs,this._retryAbortController.signal)}catch{return this._finishCancelledRetry(),!1}finally{this._retryAbortController=void 0}return!0}abortRetry(){this._retryAbortController?.abort()}get isRetrying(){return this._retryAbortController!==void 0}get autoRetryEnabled(){return this.settingsManager.getRetryEnabled()}setAutoRetryEnabled(enabled){this.settingsManager.setRetryEnabled(enabled)}async executeBash(command,onChunk,options){let abortController=new AbortController;this._bashAbortControllers.add(abortController);let prefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),resolvedCommand=prefix?`${prefix}
|
|
1079
|
+
`),images.length===0&&(images=void 0)}await this.prompt(text2,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];return this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues(),this._tasksHost.delivery.queueCleared(),this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._isAgentRunActive&&(this._agentRunAbortRequested=!0),this.abortRetry(),this.abortCompaction(),this.abortBranchSummary(),this._isBeforeSettle&&(this._abortDuringBeforeSettle=!0),this.agent.abort(),await this.waitForIdle()}async waitForIdle(){this.isIdle||await this._getIdleWaitPromise()}async _emitModelSelect(nextModel,previousModel,source){modelsAreEqual(previousModel,nextModel)||await this._extensionRunner.emit({type:"model_select",model:nextModel,previousModel,source})}async setModel(model,options={}){if(!await this._modelRuntime.checkAuth(model.provider))throw new Error(`No API key for ${model.provider}/${model.id}`);let previousModel=this.model,thinkingLevel=this._getThinkingLevelForModelSwitch(model);this.agent.state.model=model,this.sessionManager.appendModelChange(model.provider,model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(model.provider,model.id),this._addPersistedDefaultToNonEmptyScope(model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(model,previousModel,"set")}_addPersistedDefaultToNonEmptyScope(model){if(this._scopedModels.length===0||this._scopedModels.some(scoped=>modelsAreEqual(scoped.model,model)))return;this._scopedModels=[...this._scopedModels,{model}];let enabledModels=this.settingsManager.getEnabledModels();if(!enabledModels?.length)return;let modelReference=`${model.provider}/${model.id}`;enabledModels.some(pattern=>pattern.toLowerCase()===modelReference.toLowerCase())||this.settingsManager.setEnabledModels([...enabledModels,modelReference])}async cycleModel(direction="forward",options={}){return this._scopedModels.length>0?this._cycleScopedModel(direction,options):this._cycleAvailableModel(direction,options)}async _cycleScopedModel(direction,options){let availableIds=new Set(this._modelRuntime.getAvailableSnapshot().map(model=>`${model.provider}\0${model.id}`)),scopedModels=this._scopedModels.filter(scoped=>availableIds.has(`${scoped.model.provider}\0${scoped.model.id}`));if(scopedModels.length<=1)return;let currentModel=this.model,currentIndex=scopedModels.findIndex(sm=>modelsAreEqual(sm.model,currentModel));currentIndex===-1&&(currentIndex=0);let len=scopedModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,next=scopedModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(next.model,next.thinkingLevel);return this.agent.state.model=next.model,this.sessionManager.appendModelChange(next.model.provider,next.model.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(next.model.provider,next.model.id),this._addPersistedDefaultToNonEmptyScope(next.model)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(next.model,currentModel,"cycle"),{model:next.model,thinkingLevel:this.thinkingLevel,isScoped:!0}}async _cycleAvailableModel(direction,options){let availableModels=this._modelRuntime.getAvailableSnapshot();if(availableModels.length<=1)return;let currentModel=this.model,currentIndex=availableModels.findIndex(m2=>modelsAreEqual(m2,currentModel));currentIndex===-1&&(currentIndex=0);let len=availableModels.length,nextIndex=direction==="forward"?(currentIndex+1)%len:(currentIndex-1+len)%len,nextModel=availableModels[nextIndex],thinkingLevel=this._getThinkingLevelForModelSwitch(nextModel);return this.agent.state.model=nextModel,this.sessionManager.appendModelChange(nextModel.provider,nextModel.id),options.persist&&(this.settingsManager.setDefaultModelAndProvider(nextModel.provider,nextModel.id),this._addPersistedDefaultToNonEmptyScope(nextModel)),this.setThinkingLevel(thinkingLevel),await this._emitModelSelect(nextModel,currentModel,"cycle"),{model:nextModel,thinkingLevel:this.thinkingLevel,isScoped:!1}}setThinkingLevel(level,options={}){let availableLevels=this.getAvailableThinkingLevels(),effectiveLevel=availableLevels.includes(level)?level:this._clampThinkingLevel(level,availableLevels),previousLevel=this.agent.state.thinkingLevel,isChanging=effectiveLevel!==previousLevel;this.agent.state.thinkingLevel=effectiveLevel,options.persist&&this.settingsManager.setDefaultThinkingLevel(level),isChanging&&(this.sessionManager.appendThinkingLevelChange(effectiveLevel),this._emit({type:"thinking_level_changed",level:effectiveLevel}),this._extensionRunner.emit({type:"thinking_level_select",level:effectiveLevel,previousLevel}))}cycleThinkingLevel(options={}){if(!this.supportsThinking())return;let levels=this.getAvailableThinkingLevels(),nextIndex=(levels.indexOf(this.thinkingLevel)+1)%levels.length,nextLevel=levels[nextIndex];return this.setThinkingLevel(nextLevel,options),nextLevel}getAvailableThinkingLevels(){return this.model?getSupportedThinkingLevels(this.model):[...THINKING_LEVEL_OPTIONS]}supportsThinking(){return!!this.model?.reasoning}_getThinkingLevelForModelSwitch(targetModel,explicitLevel){if(explicitLevel!==void 0)return explicitLevel;if(targetModel){let perModel=this.settingsManager.getModelThinkingLevel(targetModel.provider,targetModel.id);if(perModel!==void 0)return perModel}return this.settingsManager.getDefaultThinkingLevel()??this.thinkingLevel??DEFAULT_THINKING_LEVEL}_clampThinkingLevel(level,_availableLevels){return this.model?clampThinkingLevel(this.model,level):"off"}syncQueueModesFromSettings(){this.agent.steeringMode=this.settingsManager.getSteeringMode(),this.agent.followUpMode=this.settingsManager.getFollowUpMode()}setSteeringMode(mode){this.agent.steeringMode=mode,this.settingsManager.setSteeringMode(mode)}setFollowUpMode(mode){this.agent.followUpMode=mode,this.settingsManager.setFollowUpMode(mode)}async _runDefaultCompaction(preparation,model,customInstructions,signal,reason){let request=await this._getSummarizationRequestAuth(model,signal);return compact(preparation,request.model,request.apiKey,request.headers,customInstructions,signal,request.thinkingLevel,this.agent.streamFunction,request.env,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._withTasksPaused(()=>this._compactBody(customInstructions))}async _compactBody(customInstructions){await this.abort(),this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason:"manual"});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings2=this.settingsManager.getCompactionSettings(this.routedModel?.model??model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result2=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason:"manual",willRetry:!1,signal:this._compactionAbortController.signal});if(result2?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result2?.compaction&&(extensionCompaction=result2.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result2=await this._runDefaultCompaction(preparation,model,customInstructions,this._compactionAbortController.signal,"manual");summary=result2.summary,firstKeptEntryId=result2.firstKeptEntryId,tokensBefore=result2.tokensBefore,usage=result2.usage,details=result2.details}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage),this._tasksHost.noteCompaction();let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason:"manual",willRetry:!1});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage9=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason:"manual",result:void 0,aborted,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason:"manual",errorMessage:errorMessage9,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0){let settings2=this.settingsManager.getCompactionSettings(this._modelForMessage(assistantMessage)??this.model);if(!settings2.enabled||skipAbortedCheck&&assistantMessage.stopReason==="aborted")return!1;let messageModel=this._modelForMessage(assistantMessage),sameModel=messageModel!==void 0,contextWindow=(messageModel??this.model)?.contextWindow??0,compactionEntry=getLatestCompactionEntry(this.sessionManager.getBranch());if(compactionEntry!==null&&assistantMessage.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1;let currentProjection=this.sessionManager.buildSessionProjection(),assistantEntryId=this._findPersistedMessageEntryId(assistantMessage),assistantIsProjected=assistantEntryId===void 0||currentProjection.entries.some(entry=>entry.sourceEntry.id===assistantEntryId&&entry.messages.some(message=>message.role==="assistant")),branch=this.sessionManager.getBranch(),assistantIndex=assistantEntryId?branch.findIndex(entry=>entry.id===assistantEntryId):-1,entriesAfterAssistant=assistantIndex>=0?branch.slice(assistantIndex+1):[],hasPostAssistantContextEdit=entriesAfterAssistant.some(entry=>entry.type==="context_edit"),latestAssistantEdit=entriesAfterAssistant.filter(entry=>entry.type==="context_edit"&&entry.targetId===assistantEntryId).at(-1),assistantRetainedForExplicitRecovery=assistantEntryId===void 0||!entriesAfterAssistant.some(entry=>entry.type==="compaction")&&latestAssistantEdit?.replacement!==null,assistantUsageMatchesProjection=assistantIsProjected&&!hasPostAssistantContextEdit,explicitOverflow=assistantMessage.stopReason==="error"&&isContextOverflow(assistantMessage),contextOverflow=sameModel&&(explicitOverflow&&assistantRetainedForExplicitRecovery||assistantUsageMatchesProjection&&isContextOverflow(assistantMessage,contextWindow)),recoverableLength=sameModel&&assistantIsProjected&&isRecoverableLength(assistantMessage,messageModel.maxTokens);if(contextOverflow||recoverableLength){let willRetry=assistantMessage.stopReason!=="stop";if(!willRetry)return await this._runAutoCompaction("overflow",!1);if(this._overflowRecoveryAttempted){let errorMessage9=contextOverflow?"Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.":"Truncated response recovery failed after one compact-and-retry attempt.";return this._emit({type:"compaction_end",reason:"overflow",result:void 0,aborted:!1,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage9,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage);let retry=await this._runAutoCompaction("overflow",willRetry);return retry&&(this._failedResponse=assistantMessage),retry}let contextTokens,projection=currentProjection,hasContextEdits=projection.entries.some(entry=>entry.sourceEntry.type==="context_edit"),directContextTokens=assistantMessage.usage?calculateContextTokens(assistantMessage.usage):0;if(hasContextEdits)contextTokens=estimateProjectedContextTokens(projection,branch).tokens;else if(assistantMessage.stopReason==="error"||directContextTokens===0){let messages=this.agent.state.messages,estimate=estimateContextTokens2(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact(contextTokens,contextWindow,settings2)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){return this._withTasksPaused(()=>this._runAutoCompactionBody(reason,willRetry))}async _runAutoCompactionBody(reason,willRetry){let model=this.model,settings2=this.settingsManager.getCompactionSettings(this.routedModel?.model??model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings2);if(!preparation)return!1;abortController=new AbortController,this._autoCompactionAbortController=abortController,started=!0,this._emit({type:"compaction_start",reason}),abortController.signal.throwIfAborted();let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let extensionResult=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions:void 0,reason,willRetry,signal:abortController.signal});if(extensionResult?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");extensionResult?.compaction&&(extensionCompaction=extensionResult.compaction,fromExtension=!0)}abortController.signal.throwIfAborted();let summary,firstKeptEntryId,tokensBefore,usage,details;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let compactResult=await this._runDefaultCompaction(preparation,model,void 0,abortController.signal,reason);summary=compactResult.summary,firstKeptEntryId=compactResult.firstKeptEntryId,tokensBefore=compactResult.tokensBefore,usage=compactResult.usage,details=compactResult.details}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage),this._tasksHost.noteCompaction();let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry});let result2={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result:result2,aborted:!1,willRetry}),willRetry?!0:this.agent.hasQueuedMessages()}catch(error){let message=error instanceof Error?error.message:"compaction failed",aborted=abortController?.signal.aborted===!0||cancelledByExtension;if(started){let errorMessage9=aborted?void 0:reason==="overflow"?`Context overflow recovery failed: ${message}`:`Auto-compaction failed: ${message}`;this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage9}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage9,aborted,willRetry:!1,fromExtension})}return!1}finally{this._autoCompactionAbortController===abortController&&(this._autoCompactionAbortController=void 0),this._resolveIdleWaitIfIdle()}}setAutoCompactionEnabled(enabled){this.settingsManager.setCompactionEnabled(enabled)}get autoCompactionEnabled(){return this.settingsManager.getCompactionEnabled()}async bindExtensions(bindings){return this._withTasksPaused(()=>this._bindExtensionsBody(bindings))}async _bindExtensionsBody(bindings){bindings.tasksEnabled!==void 0&&(this._tasksHost.setEnabled(bindings.tasksEnabled),this._refreshToolRegistry()),bindings.uiContext!==void 0&&(this._extensionUIContext=bindings.uiContext),bindings.mode!==void 0&&(this._extensionMode=bindings.mode),bindings.commandContextActions!==void 0&&(this._extensionCommandContextActions=bindings.commandContextActions),bindings.abortHandler!==void 0&&(this._extensionAbortHandler=bindings.abortHandler),bindings.shutdownHandler!==void 0&&(this._extensionShutdownHandler=bindings.shutdownHandler),bindings.onError!==void 0&&(this._extensionErrorListener=bindings.onError),this._applyExtensionBindings(this._extensionRunner),await this._extensionRunner.emit(this._sessionStartEvent),this._extensionRunner.reportUnhandledMcpServers(),await this.extendResourcesFromExtensions(this._sessionStartEvent.reason==="reload"?"reload":"startup")}async extendResourcesFromExtensions(reason){if(!this._extensionRunner.hasHandlers("resources_discover"))return;let{skillPaths,promptPaths,themePaths}=await this._extensionRunner.emitResourcesDiscover(this._cwd,reason);if(skillPaths.length===0&&promptPaths.length===0&&themePaths.length===0)return;let extensionPaths={skillPaths:this.buildExtensionResourcePaths(skillPaths),promptPaths:this.buildExtensionResourcePaths(promptPaths),themePaths:this.buildExtensionResourcePaths(themePaths)};this._resourceLoader.extendResources(extensionPaths),this._rebuildSystemPrompt(this.getActiveToolNames())}buildExtensionResourcePaths(entries){return entries.map(entry=>{let source=this.getExtensionSourceLabel(entry.extensionPath),baseDir=isSyntheticPath(entry.extensionPath)?void 0:dirname17(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return isSyntheticPath(extensionPath)?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename9(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(err=>{runner.emitError({extensionPath:"<runtime>",event:"send_message",error:err instanceof Error?err.message:String(err)})})},sendUserMessage:(content,options)=>{this.sendUserMessage(content,options).catch(err=>{runner.emitError({extensionPath:"<runtime>",event:"send_user_message",error:err instanceof Error?err.message:String(err)})})},appendEntry:(customType,data)=>{let entryId=this.sessionManager.appendCustomEntry(customType,data),entry=this.sessionManager.getEntry(entryId);entry&&this._emit({type:"entry_appended",entry})},setSessionName:name=>{this.setSessionName(name)},getSessionName:()=>this.sessionManager.getSessionName(),setLabel:(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label)},getActiveTools:()=>this.getActiveToolNames(),getAllTools:()=>this.getAllTools(),getSettings:()=>this.settingsManager.getSettings(),setActiveTools:toolNames=>this.setActiveToolsByName(toolNames),refreshTools:()=>this._refreshToolRegistry(),getCommands,setModel:async model=>this._modelRuntime.hasConfiguredAuth(model.provider)?(await this.setModel(model),!0):!1,getThinkingLevel:()=>this.thinkingLevel,setThinkingLevel:level=>this.setThinkingLevel(level)},{getTasks:()=>this.tasks,getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),getContextSnapshot:()=>this.getContextSnapshot(),compact:options=>{(async()=>{try{let result2=await this.compact(options?.customInstructions);options?.onComplete?.(result2)}catch(error){let err=error instanceof Error?error:new Error(String(error));options?.onError?.(err)}})()},getSystemPrompt:()=>this.systemPrompt,getSystemPromptOptions:()=>this._baseSystemPromptOptions,executeTool:(callerId,name,args,options)=>this._executeNestedToolCall(callerId,name,args,options),getCallableTools:()=>this._getCallableTools()},{registerProvider:(name,config)=>{this._modelRuntime.registerProvider(name,config),this._refreshCurrentModelFromRegistry()},registerNativeProvider:provider=>{this._modelRuntime.registerNativeProvider(provider),this._refreshCurrentModelFromRegistry()},unregisterProvider:name=>{this._modelRuntime.unregisterProvider(name),this._refreshCurrentModelFromRegistry()},registerVirtualModel:definition=>{this._modelRuntime.registerVirtualModel(definition),this._refreshCurrentModelFromRegistry()},unregisterVirtualModel:(provider,id)=>{this._modelRuntime.unregisterVirtualModel(provider,id),this._refreshCurrentModelFromRegistry()}})}_refreshToolRegistry(options){let previousActivatedOnRegistration=new Set([...this._toolRegistry.keys()].filter(name=>this._isActivatedOnRegistration(name))),previousActiveToolNames=this.getActiveToolNames(),allowedTools=this._allowedTools,allCustomTools=[...this._extensionRunner.getAllRegisteredTools(),...this._customTools.map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`<sdk:${definition.name}>`,{source:"sdk"})}))].filter(tool=>this._isAllowedTool(tool.definition.name)),definitionRegistry=new Map(Array.from(this._baseToolDefinitions.entries()).filter(([name])=>this._isAllowedTool(name)).map(([name,definition])=>[name,{definition,sourceInfo:createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${name}`,{source:"builtin"})}]));for(let tool of allCustomTools)definitionRegistry.set(tool.definition.name,{definition:tool.definition,sourceInfo:tool.sourceInfo});this._toolDefinitions=definitionRegistry,this._toolPromptSnippets=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let snippet=this._normalizePromptSnippet(definition.promptSnippet);return snippet?[definition.name,snippet]:void 0}).filter(entry=>entry!==void 0)),this._toolPromptGuidelines=new Map(Array.from(definitionRegistry.values()).map(({definition})=>{let guidelines=this._normalizePromptGuidelines(definition.promptGuidelines);return guidelines.length>0?[definition.name,guidelines]:void 0}).filter(entry=>entry!==void 0));let runner=this._extensionRunner,wrappedExtensionTools=wrapRegisteredTools(allCustomTools,runner),wrappedBuiltInTools=wrapRegisteredTools(Array.from(this._baseToolDefinitions.values()).filter(definition=>this._isAllowedTool(definition.name)).map(definition=>({definition,sourceInfo:createSyntheticSourceInfo(`${BUILTIN_PATH_PREFIX}${definition.name}`,{source:"builtin"})})),runner),toolRegistry=new Map(wrappedBuiltInTools.map(tool=>[tool.name,tool]));for(let tool of wrappedExtensionTools)toolRegistry.set(tool.name,tool);this._toolRegistry=toolRegistry;let nextActiveToolNames=(options?.activeToolNames?[...options.activeToolNames]:[...previousActiveToolNames]).filter(name=>this._isAllowedTool(name));if(allowedTools)for(let toolName of this._toolRegistry.keys())allowedTools(toolName)&&this._isDeclarable(toolName)&&nextActiveToolNames.push(toolName);else if(options?.includeAllExtensionTools)for(let tool of wrappedExtensionTools)this._isActivatedOnRegistration(tool.name)&&nextActiveToolNames.push(tool.name);else if(!options?.activeToolNames)for(let toolName of this._toolRegistry.keys())!previousActivatedOnRegistration.has(toolName)&&this._isActivatedOnRegistration(toolName)&&nextActiveToolNames.push(toolName);nextActiveToolNames.push(...this._pendingToolNames),this._setActiveTools([...new Set(nextActiveToolNames)])}_isDeclarable(name){let exposure=this._getToolExposure(name);return exposure==="direct"||exposure==="model-only"}_isActivatedOnRegistration(name){return this._isDeclarable(name)&&this._toolDefinitions.get(name)?.definition.defaultActive!==!1}_buildRuntime(options){let autoResizeImages=this.settingsManager.getImageAutoResize(),shellCommandPrefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),baseToolDefinitions=this._baseToolsOverride?Object.fromEntries(Object.entries(this._baseToolsOverride).map(([name,tool])=>[name,createToolDefinitionFromAgentTool(tool)])):createAllToolDefinitions(this._cwd,{read:{autoResizeImages},bash:{commandPrefix:shellCommandPrefix,shellPath}});this._baseToolDefinitions=new Map(Object.entries(baseToolDefinitions).map(([name,tool])=>[name,tool]));let extensionsResult=this._resourceLoader.getExtensions();if(options.flagValues)for(let[name,value]of options.flagValues)extensionsResult.runtime.flagValues.set(name,value);this._extensionRunner=new ExtensionRunner(extensionsResult.extensions,extensionsResult.runtime,this._cwd,this.sessionManager,new ModelRegistry(this._modelRuntime)),this._extensionRunnerRef&&(this._extensionRunnerRef.current=this._extensionRunner),this._bindExtensionCore(this._extensionRunner),this._applyExtensionBindings(this._extensionRunner);let defaultActiveToolNames=this._baseToolsOverride?Object.keys(this._baseToolsOverride):["read","bash","edit","write"],baseActiveToolNames=options.activeToolNames??defaultActiveToolNames;this._refreshToolRegistry({activeToolNames:baseActiveToolNames,includeAllExtensionTools:options.includeAllExtensionTools})}async reload(options){return this._withTasksPaused(()=>this._reloadBody(options))}async _reloadBody(options){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();this.tasks.close(),await Promise.all([this.tasks.shutdown(),this.abort()]),await emitSessionShutdownEvent(oldRunner,{type:"session_shutdown",reason:"reload"}),oldRunner.invalidate();let getDefaultTools=()=>this._usesDefaultTools?applyToolModifiers(this.settingsManager.getDefaultTools()??DEFAULT_TOOL_NAMES,this._defaultToolModifiers):[],previousDefaultTools=new Set(getDefaultTools());await this.settingsManager.reload(),this.syncQueueModesFromSettings(),resetApiProviders(),await this._resourceLoader.reload(),this._tasksHost.replaceService();let addedDefaultTools=getDefaultTools().filter(name=>!previousDefaultTools.has(name));for(let name of this.getActiveToolNames())this._pendingToolNames.add(name);this._buildRuntime({activeToolNames:[...this.getActiveToolNames(),...addedDefaultTools],flagValues:previousFlagValues,includeAllExtensionTools:!0}),(this.tasks.enabled||this._extensionUIContext||this._extensionCommandContextActions||this._extensionShutdownHandler||this._extensionErrorListener)&&(await options?.beforeSessionStart?.(),await this._extensionRunner.emit({type:"session_start",reason:"reload"}),this._extensionRunner.reportUnhandledMcpServers(),await this.extendResourcesFromExtensions("reload"))}_isRetryableError(message){return isContextOverflow(message,(this._modelForMessage(message)??this.model)?.contextWindow??0)?!1:isRetryableAssistantError(message)}_summarizationRetryCallbacks(source){return{onRetryScheduled:(attempt2,maxAttempts,delayMs,errorMessage9)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage9})},onRetryAttemptStart:()=>{this._emit({type:"summarization_retry_attempt_start",...source})},onRetryFinished:()=>{this._emit({type:"summarization_retry_finished"})}}}_finishCancelledRetry(){if(this._retryAttempt===0)return;let attempt2=this._retryAttempt;this._retryAttempt=0,this._emit({type:"auto_retry_end",success:!1,attempt:attempt2,finalError:"Retry cancelled"})}async _prepareRetry(message){let settings2=this.settingsManager.getRetrySettings();if(!settings2.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings2.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings2,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings2.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep3(delayMs,this._retryAbortController.signal)}catch{return this._finishCancelledRetry(),!1}finally{this._retryAbortController=void 0}return!0}abortRetry(){this._retryAbortController?.abort()}get isRetrying(){return this._retryAbortController!==void 0}get autoRetryEnabled(){return this.settingsManager.getRetryEnabled()}setAutoRetryEnabled(enabled){this.settingsManager.setRetryEnabled(enabled)}async executeBash(command,onChunk,options){let abortController=new AbortController;this._bashAbortControllers.add(abortController);let prefix=this.settingsManager.getShellCommandPrefix(),shellPath=this.settingsManager.getShellPath(),resolvedCommand=prefix?`${prefix}
|
|
1095
1080
|
${command}`:command;try{let result2=await executeBashWithOperations(resolvedCommand,this.sessionManager.getCwd(),options?.operations??createLocalBashOperations({shellPath}),{onChunk:delta=>{onChunk?.(delta),this._emit({type:"bash_execution_update",id:options?.id,delta})},signal:abortController.signal});return this.recordBashResult(command,result2,options),result2}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result2,options){let bashMessage={role:"bashExecution",command,output:result2.output,exitCode:result2.exitCode,cancelled:result2.cancelled,truncated:result2.truncated,fullOutputPath:result2.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.sessionManager.appendMessage(bashMessage),this._refreshFinalizedContext())}abortBash(){for(let abortController of[...this._bashAbortControllers])abortController.abort()}get isBashRunning(){return this._bashAbortControllers.size>0}get hasPendingBashMessages(){return this._pendingBashMessages.length>0}_flushPendingBashMessages(){if(this._pendingBashMessages.length!==0){for(let bashMessage of this._pendingBashMessages)this.sessionManager.appendMessage(bashMessage);this._pendingBashMessages=[],this._refreshFinalizedContext()}}setSessionName(name){this.sessionManager.appendSessionInfo(name);let event={type:"session_info_changed",name:this.sessionManager.getSessionName()};this._emit(event),this._extensionRunner.emit(event)}async navigateTree(targetId,options={}){if(this.isStreaming)throw new Error("Wait for the current response to finish before navigating the session tree.");if(this.isCompacting)throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");let oldLeafId=this.sessionManager.getLeafId();if(targetId===oldLeafId)return{cancelled:!1};if(options.summarize&&!this.model)throw new Error("No model available for summarization");let targetEntry=this.sessionManager.getEntry(targetId);if(!targetEntry)throw new Error(`Entry ${targetId} not found`);let{entries:entriesToSummarize,commonAncestorId}=collectEntriesForBranchSummary(this.sessionManager,oldLeafId,targetId),customInstructions=options.customInstructions,replaceInstructions=options.replaceInstructions,label=options.label,preparation={targetId,oldLeafId,commonAncestorId,entriesToSummarize,userWantsSummary:options.summarize??!1,customInstructions,replaceInstructions,label},resumeBackground=this.pauseTaskNotifications();this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result2=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result2?.cancel)return{cancelled:!0};result2?.summary&&options.summarize&&(extensionSummary=result2.summary,fromExtension=!0),result2?.customInstructions!==void 0&&(customInstructions=result2.customInstructions),result2?.replaceInstructions!==void 0&&(replaceInstructions=result2.replaceInstructions),result2?.label!==void 0&&(label=result2.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let signal=this._branchSummaryAbortController.signal,branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result2=await generateBranchSummary(entriesToSummarize,{...await this._getSummarizationRequestAuth(this.model,signal),signal,customInstructions,replaceInstructions,reserveTokens:branchSummarySettings.reserveTokens,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),callbacks:this._summarizationRetryCallbacks({source:"branchSummary"})});if(result2.aborted)return{cancelled:!0,aborted:!0};if(result2.error)throw new Error(result2.error);summaryText=result2.summary,summaryUsage=result2.usage,summaryDetails={readFiles:result2.readFiles||[],modifiedFiles:result2.modifiedFiles||[]}}else extensionSummary&&(summaryText=extensionSummary.summary,summaryDetails=extensionSummary.details,summaryUsage=extensionSummary.usage);let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId,await this._tasksHost.cancelOutsideBranch(newLeafId);let summaryEntry;if(summaryText){let summaryId=this.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,fromExtension,summaryUsage);summaryEntry=this.sessionManager.getEntry(summaryId),label&&this.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?this.sessionManager.resetLeaf():this.sessionManager.branch(newLeafId);return label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label),this._tasksHost.restoreHistory(),this._refreshFinalizedContext(),this._restoreToolsFromTranscript(),await this._extensionRunner.emit({type:"session_tree",newLeafId:this.sessionManager.getLeafId(),oldLeafId,summaryEntry,fromExtension:summaryText?fromExtension:void 0}),{editorText,cancelled:!1,summaryEntry}}finally{this._branchSummaryAbortController=void 0,this._resolveIdleWaitIfIdle(),resumeBackground()}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result2=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text2=contentText(entry.message.content,"");text2&&result2.push({entryId:entry.id,text:text2})}return result2}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals(),entries=this.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries){if(entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++;else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c=>c.type==="toolCall").length)}}return{sessionFile:this.sessionFile,sessionId:this.sessionId,userMessages,assistantMessages,toolCalls,toolResults,totalMessages,tokens:{input:usageTotals.input,output:usageTotals.output,cacheRead:usageTotals.cacheRead,cacheWrite:usageTotals.cacheWrite,total:usageTotals.input+usageTotals.output+usageTotals.cacheRead+usageTotals.cacheWrite},cost:usageTotals.cost,contextUsage:this.getContextUsage()}}getContextUsage(){let model=this._limitsModel();if(!model)return;let contextWindow=model.contextWindow??0;if(contextWindow<=0)return;let projection=this.sessionManager.buildSessionProjection(),branch=this.sessionManager.getBranch(),latestCompaction=getLatestCompactionEntry(branch);if(latestCompaction){let projectedAssistants=new Set(projection.entries.flatMap(entry=>entry.messages.some(message=>message.role==="assistant"&&message.stopReason!=="aborted"&&message.stopReason!=="error"&&calculateContextTokens(message.usage)>0)?[entry.sourceEntry.id]:[])),compactionIndex=branch.findIndex(entry=>entry.id===latestCompaction.id);if(!branch.slice(compactionIndex+1).some(entry=>projectedAssistants.has(entry.id)))return{tokens:null,contextWindow,percent:null}}let estimate=estimateProjectedContextTokens(projection,branch),percent=estimate.tokens/contextWindow*100;return{tokens:estimate.tokens,contextWindow,percent}}async exportToHtml(outputPath,options={}){let themeName=[options.themeName,this.settingsManager.getTheme()].find(candidate=>candidate!==void 0&&getThemeByName(candidate)!==void 0),toolRenderer=createToolHtmlRenderer({getToolRenderers:name=>this._extensionRunner.resolveToolRenderers(name,()=>this.getToolDefinition(name)),theme,cwd:this.sessionManager.getCwd()});return await exportSessionToHtml(this.sessionManager,this.state,{outputPath,themeName,toolRenderer})}exportToJsonl(outputPath){return exportSessionToJsonl(this.sessionManager,outputPath)}async summarizeForBugReport(options){let model=this.model;if(!model)throw new Error("No model selected");return generateBugReportSummary({...await this._getSummarizationRequestAuth(model,options.signal),messages:this.messages,hint:options.hint,signal:options.signal,streamFn:this.agent.streamFunction,retry:this.settingsManager.getRetrySettings(),sessionId:this.sessionId})}getLastAssistantText(){let lastAssistant=this.messages.slice().reverse().find(m2=>{if(m2.role!=="assistant")return!1;let msg=m2;return!(msg.stopReason==="aborted"&&msg.content.length===0)});if(!lastAssistant)return;let text2="";for(let content of lastAssistant.content)content.type==="text"&&(text2+=content.text);return text2.trim()||void 0}createReplacedSessionContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()));return context.sendMessage=(message,options)=>this.sendCustomMessage(message,options),context.sendUserMessage=(content,options)=>this.sendUserMessage(content,options),context}hasExtensionHandlers(eventType){return this._extensionRunner.hasHandlers(eventType)}get extensionRunner(){return this._extensionRunner}};import{join as join30}from"node:path";var MAX_WARMING_AGE_MS=60*6e4,MAX_IDLE_WARMING_AGE_MS=30*6e4,CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS=.05,IDLE_CONTINUATION_PROBABILITY=.15;function getCacheWarmingDelayMs(ttlMs){if(!(ttlMs<=1e4))return Math.max(1,Math.floor(Math.min(ttlMs*.9,ttlMs-1e4)))}function getPromptCacheTtlMs(model,options){let retention=options?.cacheRetention??(getProviderEnvValue("PI_CACHE_RETENTION",options?.env)==="long"?"long":"short");if(retention==="none")return;let seconds=model.promptCache?.[retention];return seconds===void 0?void 0:seconds*1e3}function isReplayable(model,options){return!options?.reasoning||model.api!=="anthropic-messages"?!0:model.compat?.forceAdaptiveThinking===!0}function lastPromptTokens(entries){for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type==="message"&&entry.message.role==="assistant"){let usage=entry.message.usage;return usage.input+usage.cacheRead+usage.cacheWrite}}return 0}function price(model,tokens2){let usage={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},...tokens2};return calculateCost(model,usage).total}var CacheWarmer=class{constructor(models,sessionManager,getMode,decide=async event=>event.action){this.models=models,this.sessionManager=sessionManager,this.getMode=getMode,this.decide=decide,this.inactive={state:"inactive",reason:"waiting for first request"}}get status(){if(this.getMode()==="off")return{state:"inactive",reason:"cache warming disabled"};let run=this.run;if(!run)return this.inactive;if(!run.isCurrent())return{state:"inactive",reason:"conversation context changed"};let decision=this.evaluate(run),refreshing=run.timer===void 0;return!decision.economicsAvailable&&!refreshing?{state:"inactive",reason:"cache economics unavailable"}:{state:refreshing?"refreshing":"scheduled",nextWarmAt:run.nextWarmAt,decision,extensionOverride:run.extensionOverride}}start(request,isCurrent){if(this.clearRun(),this.getMode()==="off"){this.stop("cache warming disabled");return}if(!isReplayable(request.model,request.options)){this.stop("request cannot be replayed safely");return}let ttlMs=getPromptCacheTtlMs(request.model,request.options);if(ttlMs===void 0){this.stop(request.options.cacheRetention==="none"?"request disabled prompt caching":"cache lifetime unavailable");return}let delayMs=getCacheWarmingDelayMs(ttlMs);if(delayMs===void 0){this.stop("cache lifetime unavailable");return}this.run={...request,isCurrent,ttlMs,delayMs,refreshDeadlineAt:0,startedAt:Date.now(),controller:new AbortController,phase:"streaming",nextWarmAt:0,extensionOverride:!1},this.schedule(this.run)}onAgentSettled(){let run=this.run;if(!run)return;if(this.getMode()==="streaming"){this.stop("agent run settled");return}run.phase="idle";let deadline=run.startedAt+MAX_IDLE_WARMING_AGE_MS;(run.nextWarmAt>deadline||Date.now()>=deadline)&&this.stop("30-minute idle safety limit reached")}onModeChanged(){let run=this.run;if(!run)return;let reason=this.getModeStopReason(run);reason&&this.stop(reason)}cancel(){this.stop("inactive")}clearRun(){let run=this.run;run&&(this.run=void 0,run.timer&&clearTimeout(run.timer),run.controller.abort())}stop(reason,stopped){this.clearRun(),this.inactive={state:"inactive",reason,...stopped}}schedule(run){run.extensionOverride=!1,run.nextWarmAt=Date.now()+run.delayMs,run.refreshDeadlineAt=run.nextWarmAt+Math.floor((run.ttlMs-run.delayMs)/2);let deadline=run.startedAt+(run.phase==="idle"?MAX_IDLE_WARMING_AGE_MS:MAX_WARMING_AGE_MS);if(run.nextWarmAt>deadline||Date.now()>=deadline){this.stop(run.phase==="idle"?"30-minute idle safety limit reached":"one-hour safety limit reached");return}run.timer=setTimeout(()=>{this.refresh(run)},Math.max(0,run.nextWarmAt-Date.now())),run.timer.unref?.()}async refresh(run){if(run.timer=void 0,!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let decision=this.evaluate(run),{warmCost,missCost,continuationProbability}=decision,action=decision.action;try{action=await this.decide({type:"cache_warming_decision",warmCost,missCost,continuationProbability,action})}catch{}if(!this.validateRun(run)||this.refreshDeadlineMissed(run))return;let extensionOverride=action!==decision.action;if(action==="stop"){let reason=extensionOverride?"stopped by extension":decision.economicsAvailable?"expected savings below threshold":"cache economics unavailable";this.stop(reason,{decision,extensionOverride});return}run.extensionOverride=extensionOverride;try{let message=await this.models.streamSimple(run.model,run.context,{...run.options,maxTokens:1,maxRetries:0,signal:run.controller.signal}).result();if(!this.validateRun(run))return;if(message.stopReason!=="error"&&message.stopReason!=="aborted"){let entry=this.sessionManager.appendUsage("cache_warm",message.provider,message.responseModel??message.model,message.usage,extensionOverride?"extension override":void 0);this.onWarmed?.(entry)}}catch{}this.run===run&&this.schedule(run)}refreshDeadlineMissed(run){return Date.now()<=run.refreshDeadlineAt?!1:(this.stop("cache refresh deadline missed"),!0)}validateRun(run){if(this.run!==run)return!1;let reason=this.getModeStopReason(run)??(run.isCurrent()?void 0:"conversation context changed");return reason?(this.stop(reason),!1):!0}getModeStopReason(run){let mode=this.getMode();if(mode==="off")return"cache warming disabled";if(mode==="streaming"&&run.phase==="idle")return"agent run settled"}evaluate(run){let model=run.model,promptTokens=lastPromptTokens(this.sessionManager.getBranch()),cacheHitCost=price(model,{cacheRead:promptTokens}),cacheMissCost=price(model,model.cost.cacheWrite>0?{cacheWrite:promptTokens}:{input:promptTokens}),warmCost=price(model,{cacheRead:promptTokens,output:1}),missCost=Math.max(0,cacheMissCost-cacheHitCost),continuationProbability=run.phase==="idle"?IDLE_CONTINUATION_PROBABILITY:1,economicsAvailable=promptTokens>0&&(cacheHitCost>0||cacheMissCost>0),expectedSavings=continuationProbability*missCost-warmCost;return{phase:run.phase,warmCost,missCost,continuationProbability,expectedSavings,economicsAvailable,action:expectedSavings>=CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS?"warm":"stop"}}};function formatDollars(value){return value<0?`-$${Math.abs(value).toFixed(3)}`:`$${value.toFixed(3)}`}function formatCacheWarmingEconomics(decision){if(!decision.economicsAvailable)return"cache economics unavailable";let probability=Math.round(decision.continuationProbability*100),probabilityText=decision.phase==="streaming"?`${probability}% continuation probability while agent is running`:`${probability}% continuation probability`,comparison=decision.action==="warm"?">=":"<";return`${probabilityText}, expected savings ${formatDollars(decision.expectedSavings)} ${comparison} $${CACHE_WARMING_MINIMUM_EXPECTED_SAVINGS.toFixed(3)}`}function formatCacheWarmingDecisionTime(nextWarmAt,now){if(nextWarmAt===void 0||nextWarmAt<=now)return"Decision now";let remainingSeconds=Math.ceil((nextWarmAt-now)/1e3),hours=Math.floor(remainingSeconds/3600);remainingSeconds%=3600;let minutes=Math.floor(remainingSeconds/60),seconds=remainingSeconds%60,parts=[];return hours>0&&parts.push(`${hours}h`),minutes>0&&parts.push(`${minutes}m`),(seconds>0||parts.length===0)&&parts.push(`${seconds}s`),`Decision in ${parts.join(" ")}`}function formatCacheWarmingStatus(status,now=Date.now()){let decision=status.decision;if(!decision||status.state==="inactive"&&!decision.economicsAvailable&&!status.extensionOverride)return`Inactive (${status.reason??"unknown reason"})`;let details=status.extensionOverride?`extension override, ${formatCacheWarmingEconomics(decision)}`:`${formatCacheWarmingEconomics(decision)} -> ${decision.action}`;return status.state==="inactive"?`Stopped (${details})`:status.state==="refreshing"?`Warming cache (${details})`:`${formatCacheWarmingDecisionTime(status.nextWarmAt,now)} (${details})`}function formatCacheWarmingUsage(entry){let note=entry.note?` (${entry.note})`:"",cost=entry.usage.cost.total.toFixed(6).replace(/(\.\d{3}\d*?)0+$/,"$1");return`Cache warmed${note}: $${cost}`}function isTruthyEnvFlag(value){return value?value==="1"||value.toLowerCase()==="true"||value.toLowerCase()==="yes":!1}function isInstallTelemetryEnabled(settingsManager,telemetryEnv=process.env.PI_TELEMETRY){return telemetryEnv!==void 0?isTruthyEnvFlag(telemetryEnv):settingsManager.getEnableInstallTelemetry()}function getClientIdentity(settingsManager){return{userAgent:"detailed",version:VERSION,attribution:isInstallTelemetryEnabled(settingsManager)?PI_ATTRIBUTION:null}}import{existsSync as existsSync16,readdirSync as readdirSync9,readFileSync as readFileSync13,statSync as statSync11}from"node:fs";import{basename as basename10,dirname as dirname19,join as join27,relative as relative6,resolve as resolve9,sep as sep9}from"node:path";import{statSync as statSync9}from"node:fs";import{homedir as homedir8,userInfo}from"node:os";import{isAbsolute as isAbsolute4,join as join25,relative as relative5,sep as sep8}from"node:path";function samePath(left,right){return left!==void 0&&relative5(canonicalizePath(left),canonicalizePath(right))===""}function isPathInside(parent,child){let relativePath=relative5(canonicalizePath(parent),canonicalizePath(child));return relativePath!==""&&relativePath!==".."&&!relativePath.startsWith(`..${sep8}`)&&!isAbsolute4(relativePath)}function pathKey(value){let normalized=canonicalizePath(resolvePath(value));return process.platform==="win32"?normalized.replace(/^([A-Z]):/,(_2,drive)=>`${drive.toLowerCase()}:`):normalized}function fileIdentity(value){try{let stats=statSync9(value,{bigint:!0});return stats.ino===0n?void 0:`${stats.dev}:${stats.ino}`}catch{return}}function referToSameLocation(left,right){let leftKey=pathKey(left),rightKey=pathKey(right);if(leftKey===rightKey)return!0;if(process.platform!=="win32")return!1;let leftIdentity=fileIdentity(leftKey);return leftIdentity!==void 0&&leftIdentity===fileIdentity(rightKey)}function findPathKeys(record,path14){return process.platform!=="win32"?Object.hasOwn(record,path14)?[path14]:[]:Object.keys(record).filter(key=>referToSameLocation(key,path14))}function userAgentsSkillsDirMatcher(){let homes=[process.env.HOME||homedir8()];try{homes.push(userInfo().homedir)}catch{}let skillDirs=homes.map(home=>join25(pathKey(home),".agents","skills"));return dir=>skillDirs.some(skillDir=>referToSameLocation(skillDir,dir))}import{execFile,spawnSync as spawnSync5}from"child_process";import{existsSync as existsSync15,readFileSync as readFileSync12,statSync as statSync10,unwatchFile,watchFile}from"fs";import{dirname as dirname18,join as join26,resolve as resolve8}from"path";function findGitPaths(cwd){let dir=cwd;for(;;){let gitPath=join26(dir,".git");if(existsSync15(gitPath))try{let stat3=statSync10(gitPath);if(stat3.isFile()){let content=readFileSync12(gitPath,"utf8").trim();if(content.startsWith("gitdir: ")){let gitDir=resolve8(dir,content.slice(8).trim()),headPath=join26(gitDir,"HEAD");if(!existsSync15(headPath))return null;let commonDirPath=join26(gitDir,"commondir"),commonGitDir=existsSync15(commonDirPath)?resolve8(gitDir,readFileSync12(commonDirPath,"utf8").trim()):gitDir;return{repoDir:dir,commonGitDir,headPath}}}else if(stat3.isDirectory()){let headPath=join26(gitPath,"HEAD");return existsSync15(headPath)?{repoDir:dir,commonGitDir:gitPath,headPath}:null}}catch{return null}let parent=dirname18(dir);if(parent===dir)return null;dir=parent}}function resolveBranchWithGitSync(repoDir){let result2=spawnSync5("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8",stdio:["ignore","pipe","ignore"]});return(result2.status===0?result2.stdout.trim():"")||null}function resolveBranchWithGitAsync(repoDir){return new Promise(resolvePromise=>{execFile("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8"},(error,stdout)=>{if(error){resolvePromise(null);return}let branch=stdout.trim();resolvePromise(branch||null)})})}function isWslEnvironment(){return process.platform==="linux"&&!!(process.env.WSL_DISTRO_NAME||process.env.WSL_INTEROP)}function isWindowsMountedRepoPath(repoDir){return/^\/mnt\/[a-z](?:\/|$)/i.test(repoDir)}function shouldPollGitHead(repoDir){return isWslEnvironment()&&isWindowsMountedRepoPath(repoDir)}var FooterDataProvider=class _FooterDataProvider{static{this.WATCH_DEBOUNCE_MS=500}constructor(cwd){this.extensionStatuses=new Map,this.cachedBranch=void 0,this.gitPaths=void 0,this.headWatcher=null,this.headWatchFilePath=null,this.headWatchFileListener=null,this.reftableWatcher=null,this.reftableTablesListWatcher=null,this.reftableTablesListPath=null,this.branchChangeCallbacks=new Set,this.availableProviderCount=0,this.refreshTimer=null,this.gitWatcherRetryTimer=null,this.refreshInFlight=!1,this.refreshPending=!1,this.disposed=!1,this.cwd=cwd,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher()}getGitBranch(){return this.cachedBranch===void 0&&(this.cachedBranch=this.resolveGitBranchSync()),this.cachedBranch}getExtensionStatuses(){return this.extensionStatuses}onBranchChange(callback){return this.branchChangeCallbacks.add(callback),()=>this.branchChangeCallbacks.delete(callback)}setExtensionStatus(key,text2){text2===void 0?this.extensionStatuses.delete(key):this.extensionStatuses.set(key,text2)}clearExtensionStatuses(){this.extensionStatuses.clear()}getAvailableProviderCount(){return this.availableProviderCount}setAvailableProviderCount(count){this.availableProviderCount=count}setCwd(cwd){this.cwd!==cwd&&(this.cwd=cwd,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.cachedBranch=void 0,this.gitPaths=findGitPaths(cwd),this.setupGitWatcher(),this.notifyBranchChange())}dispose(){this.disposed=!0,this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null),this.clearGitWatchers(),this.branchChangeCallbacks.clear()}notifyBranchChange(){for(let cb of this.branchChangeCallbacks)cb()}scheduleRefresh(){if(!(this.disposed||this.refreshTimer)){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,this.refreshGitBranchAsync()},_FooterDataProvider.WATCH_DEBOUNCE_MS)}}async refreshGitBranchAsync(){if(!this.disposed){if(this.refreshInFlight){this.refreshPending=!0;return}this.refreshInFlight=!0;try{let nextBranch=await this.resolveGitBranchAsync();if(this.disposed)return;if(this.cachedBranch!==void 0&&this.cachedBranch!==nextBranch){this.cachedBranch=nextBranch,this.notifyBranchChange();return}this.cachedBranch=nextBranch}finally{this.refreshInFlight=!1,this.refreshPending&&!this.disposed&&(this.refreshPending=!1,this.scheduleRefresh())}}}resolveGitBranchSync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?resolveBranchWithGitSync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}async resolveGitBranchAsync(){try{if(!this.gitPaths)return null;let content=readFileSync12(this.gitPaths.headPath,"utf8").trim();if(content.startsWith("ref: refs/heads/")){let branch=content.slice(16);return branch===".invalid"?await resolveBranchWithGitAsync(this.gitPaths.repoDir)??"detached":branch}return"detached"}catch{return null}}clearGitWatchers(){closeWatcher(this.headWatcher),this.headWatcher=null,this.headWatchFilePath&&this.headWatchFileListener&&(unwatchFile(this.headWatchFilePath,this.headWatchFileListener),this.headWatchFilePath=null,this.headWatchFileListener=null),closeWatcher(this.reftableWatcher),this.reftableWatcher=null,closeWatcher(this.reftableTablesListWatcher),this.reftableTablesListWatcher=null,this.reftableTablesListPath&&(unwatchFile(this.reftableTablesListPath),this.reftableTablesListPath=null),this.gitWatcherRetryTimer&&(clearTimeout(this.gitWatcherRetryTimer),this.gitWatcherRetryTimer=null)}scheduleGitWatcherRetry(){this.disposed||this.gitWatcherRetryTimer||(this.gitWatcherRetryTimer=setTimeout(()=>{this.gitWatcherRetryTimer=null,this.setupGitWatcher()},FS_WATCH_RETRY_DELAY_MS))}handleGitWatcherError(){this.clearGitWatchers(),this.scheduleGitWatcherRetry()}setupGitWatcher(){if(this.clearGitWatchers(),!this.gitPaths)return;let pollGitHead=shouldPollGitHead(this.gitPaths.repoDir);if(this.headWatcher=watchWithErrorHandler(dirname18(this.gitPaths.headPath),(_eventType,filename)=>{(!filename||filename==="HEAD")&&this.scheduleRefresh()},()=>this.handleGitWatcherError()),pollGitHead&&(this.headWatchFilePath=this.gitPaths.headPath,this.headWatchFileListener=(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()},watchFile(this.headWatchFilePath,{interval:1e3},this.headWatchFileListener)),!this.headWatcher&&!pollGitHead)return;let reftableDir=join26(this.gitPaths.commonGitDir,"reftable");if(existsSync15(reftableDir)){if(this.reftableWatcher=watchWithErrorHandler(reftableDir,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableWatcher)return;let tablesListPath=join26(reftableDir,"tables.list");if(existsSync15(tablesListPath)){if(this.reftableTablesListPath=tablesListPath,this.reftableTablesListWatcher=watchWithErrorHandler(tablesListPath,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableTablesListWatcher)return;watchFile(tablesListPath,{interval:250},(current,previous)=>{(current.mtimeMs!==previous.mtimeMs||current.ctimeMs!==previous.ctimeMs||current.size!==previous.size)&&this.scheduleRefresh()})}}}};var HOST_PROVIDED_EXTENSION_PACKAGES=new Set(["@earendil-works/pi-agent-core","@earendil-works/pi-ai","@earendil-works/pi-coding-agent","@earendil-works/pi-tui","@mariozechner/pi-agent-core","@mariozechner/pi-ai","@mariozechner/pi-coding-agent","@mariozechner/pi-tui","@sinclair/typebox","typebox"]);function collectExtensionPackageWarnings(extensionPaths,metadataByPath){let warnings=[],packageRoots=new Set(extensionPaths.map(extensionPath=>metadataByPath.get(extensionPath)?.packageRoot).filter(packageRoot=>packageRoot!==void 0));for(let packageRoot of packageRoots){let packageJsonPath=join27(packageRoot,"package.json");if(!existsSync16(packageJsonPath))continue;let manifest=JSON.parse(stripBom(readFileSync13(packageJsonPath,"utf-8")));if(typeof manifest.dependencies!="object"||manifest.dependencies===null||Array.isArray(manifest.dependencies))continue;let hostDependencies=Object.keys(manifest.dependencies).filter(name=>HOST_PROVIDED_EXTENSION_PACKAGES.has(name)).sort();hostDependencies.length!==0&&warnings.push({path:packageJsonPath,warning:`Host-provided extension packages must be declared in peerDependencies with a "*" range, not dependencies: ${hostDependencies.join(", ")}. Installed copies can bypass the extension loader and create duplicate runtime modules.`})}return warnings}function mergeExtensionWarnings(result2,warnings){result2.warnings=[...new Map([...result2.warnings??[],...warnings].map(warning=>[warning.path,warning])).values()]}function isBuiltinExtension(input2){return typeof input2!="function"&&input2.builtin===!0}function omitReplacedExtensions(extensions,warnings){let names2=extension=>[...[...extension.tools.keys()].map(name=>`tool:${name}`),...[...extension.commands.keys()].map(name=>`command:${name}`),...[...extension.flags.keys()].map(name=>`flag:${name}`)],taken=new Map(extensions.filter(extension=>!extension.replaceable).flatMap(extension=>names2(extension).map(name=>[name,extension])));return extensions.filter(extension=>{if(!extension.replaceable)return!0;let replacement=names2(extension).map(name=>({name,extension:taken.get(name)})).find(value=>value.extension!==void 0);if(!replacement)return!0;if(extension.path.startsWith(BUILTIN_PATH_PREFIX)){let builtinName=extension.path.slice(BUILTIN_PATH_PREFIX.length),[kind,rawName]=replacement.name.split(":",2),registeredName=kind==="command"?`/${rawName}`:kind==="flag"?`--${rawName}`:rawName;warnings?.push({path:extension.path,warning:`Extension ${replacement.extension.path} registers ${kind} \`${registeredName}\`, so built-in extension \`${builtinName}\` was not loaded. To use \`${builtinName}\`, run \`pi config\` and make sure it is enabled under Built-in extensions, then disable or remove the existing extension. We recommend only having one or the other loaded at a time.`})}return!1})}function resolvePromptInput(input2,description){if(input2){if(existsSync16(input2))try{return stripBom(readFileSync13(input2,"utf-8"))}catch(error){return console.error(source_default.yellow(`Warning: Could not read ${description} file ${input2}: ${error}`)),input2}return input2}}function loadContextFileFromDir(dir){let candidates=["AGENTS.override.md","AGENTS.md","AGENTS.MD","CLAUDE.md","CLAUDE.MD"];for(let filename of candidates){let filePath=join27(dir,filename);if(existsSync16(filePath))try{if(!statSync11(filePath).isFile())continue;return{path:filePath,content:stripBom(readFileSync13(filePath,"utf-8"))}}catch(error){console.error(source_default.yellow(`Warning: Could not read ${filePath}: ${error}`))}}return null}function findShadowedContextFile(cwd){let gitPaths=findGitPaths(cwd);if(!gitPaths)return;let commonGitDir=canonicalizePath(gitPaths.commonGitDir),worktreeRoot=canonicalizePath(gitPaths.repoDir),mainRepoRoot=dirname19(commonGitDir);if(!isPathInside(mainRepoRoot,worktreeRoot)||!samePath(join27(mainRepoRoot,".git"),commonGitDir))return;let worktreeContextFile=loadContextFileFromDir(worktreeRoot);return worktreeContextFile?join27(mainRepoRoot,basename10(worktreeContextFile.path)):void 0}function loadProjectContextFiles(options){let resolvedCwd=resolvePath(options.cwd),resolvedAgentDir=resolvePath(options.agentDir),contextFiles=[],seenPaths=new Set,globalContext=loadContextFileFromDir(resolvedAgentDir);globalContext&&(contextFiles.push(globalContext),seenPaths.add(globalContext.path));let ancestorContextFiles=[],shadowedContextFile=findShadowedContextFile(resolvedCwd),currentDir=resolvedCwd;for(;;){let contextFile=loadContextFileFromDir(currentDir),isShadowed=shadowedContextFile!==void 0&&contextFile!==null&&relative6(join27(canonicalizePath(currentDir),basename10(contextFile.path)),shadowedContextFile)==="";contextFile&&!isShadowed&&!seenPaths.has(contextFile.path)&&(ancestorContextFiles.unshift(contextFile),seenPaths.add(contextFile.path));let parentDir=dirname19(currentDir);if(parentDir===currentDir)break;currentDir=parentDir}return contextFiles.push(...ancestorContextFiles),contextFiles}var DefaultResourceLoader=class{constructor(options){this.cwd=resolvePath(options.cwd),this.agentDir=resolvePath(options.agentDir),this.settingsManager=options.settingsManager??SettingsManager.create(this.cwd,this.agentDir),this.eventBus=options.eventBus??createEventBus();let factories=options.extensionFactories??[];this.extensionFactories=factories.filter(input2=>!isBuiltinExtension(input2)),this.builtinExtensions=new Map(factories.filter(isBuiltinExtension).map(input2=>[input2.name,input2])),this.packageManager=new DefaultPackageManager({cwd:this.cwd,agentDir:this.agentDir,settingsManager:this.settingsManager,builtinExtensions:[...this.builtinExtensions.keys()]}),this.additionalExtensionPaths=options.additionalExtensionPaths??[],this.additionalSkillPaths=options.additionalSkillPaths??[],this.additionalPromptTemplatePaths=options.additionalPromptTemplatePaths??[],this.additionalThemePaths=options.additionalThemePaths??[],this.noExtensions=options.noExtensions??!1,this.disabledBuiltinExtensions=new Set(options.disabledBuiltinExtensions),this.noSkills=options.noSkills??!1,this.noPromptTemplates=options.noPromptTemplates??!1,this.noThemes=options.noThemes??!1,this.noContextFiles=options.noContextFiles??!1,this.systemPromptSource=options.systemPrompt,this.appendSystemPromptSource=options.appendSystemPrompt,this.extensionsOverride=options.extensionsOverride,this.skillsOverride=options.skillsOverride,this.promptsOverride=options.promptsOverride,this.themesOverride=options.themesOverride,this.agentsFilesOverride=options.agentsFilesOverride,this.systemPromptOverride=options.systemPromptOverride,this.appendSystemPromptOverride=options.appendSystemPromptOverride,this.extensionsResult={extensions:[],errors:[],runtime:createExtensionRuntime()},this.skills=[],this.skillDiagnostics=[],this.prompts=[],this.promptDiagnostics=[],this.themes=[],this.themeDiagnostics=[],this.agentsFiles=[],this.appendSystemPrompt=[],this.appendSystemPromptSourcePaths=[],this.lastSkillPaths=[],this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map,this.resourceMetadataByPath=new Map,this.lastPromptPaths=[],this.lastThemePaths=[],this.loaded=!1}getExtensions(){return this.extensionsResult}getSkills(){return{skills:this.skills,diagnostics:this.skillDiagnostics}}getPrompts(){return{prompts:this.prompts,diagnostics:this.promptDiagnostics}}getThemes(){return{themes:this.themes,diagnostics:this.themeDiagnostics}}getAgentsFiles(){return{agentsFiles:this.agentsFiles}}getSystemPrompt(){return this.systemPrompt}getSystemPromptSource(){return this.systemPromptSourcePath?{path:this.systemPromptSourcePath}:void 0}getAppendSystemPrompt(){return this.appendSystemPrompt}getAppendSystemPromptSources(){return this.appendSystemPromptSourcePaths.map(path14=>({path:path14}))}extendResources(paths){let skillPaths=this.normalizeExtensionPaths(paths.skillPaths??[]),promptPaths=this.normalizeExtensionPaths(paths.promptPaths??[]),themePaths=this.normalizeExtensionPaths(paths.themePaths??[]);for(let entry of skillPaths)this.extensionSkillSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of promptPaths)this.extensionPromptSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));for(let entry of themePaths)this.extensionThemeSourceInfos.set(entry.path,createSourceInfo(entry.path,entry.metadata));skillPaths.length>0&&(this.lastSkillPaths=this.mergePaths(this.lastSkillPaths,skillPaths.map(entry=>entry.path)),this.updateSkillsFromPaths(this.lastSkillPaths,this.resourceMetadataByPath)),promptPaths.length>0&&(this.lastPromptPaths=this.mergePaths(this.lastPromptPaths,promptPaths.map(entry=>entry.path)),this.updatePromptsFromPaths(this.lastPromptPaths,this.resourceMetadataByPath)),themePaths.length>0&&(this.lastThemePaths=this.mergePaths(this.lastThemePaths,themePaths.map(entry=>entry.path)),this.updateThemesFromPaths(this.lastThemePaths,this.resourceMetadataByPath))}async loadProjectTrustExtensions(){return this.settingsManager.setProjectTrusted(!1),await this.settingsManager.reload(),this.loadCurrentExtensionSet({includeInlineFactories:!0})}async reload(options){resetTimings("extensions"),this.loaded&&clearExtensionCache();let preTrustExtensions;if(options?.resolveProjectTrust){preTrustExtensions=await this.loadProjectTrustExtensions();let projectTrusted=await options.resolveProjectTrust({extensionsResult:preTrustExtensions});this.settingsManager.setProjectTrusted(projectTrusted)}await this.settingsManager.reload();let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0});this.resourceMetadataByPath=new Map;let metadataByPath=this.resourceMetadataByPath;this.extensionSkillSourceInfos=new Map,this.extensionPromptSourceInfos=new Map,this.extensionThemeSourceInfos=new Map;let getEnabledResources=resources=>{for(let r of resources)metadataByPath.has(r.path)||metadataByPath.set(r.path,r.metadata);return resources.filter(r=>r.enabled)},getEnabledPaths=resources=>getEnabledResources(resources).map(r=>r.path),enabledExtensions=getEnabledPaths(resolvedPaths.extensions),enabledSkillResources=getEnabledResources(resolvedPaths.skills),enabledPrompts=getEnabledPaths(resolvedPaths.prompts),enabledThemes=getEnabledPaths(resolvedPaths.themes),enabledSkills=enabledSkillResources.map(resource=>this.mapSkillPath(resource,metadataByPath));for(let r of cliExtensionPaths.extensions)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});for(let r of cliExtensionPaths.skills)metadataByPath.has(r.path)||metadataByPath.set(r.path,{source:"cli",scope:"temporary",origin:"top-level"});let cliEnabledExtensions=getEnabledPaths(cliExtensionPaths.extensions),cliEnabledSkills=getEnabledPaths(cliExtensionPaths.skills),cliEnabledPrompts=getEnabledPaths(cliExtensionPaths.prompts),cliEnabledThemes=getEnabledPaths(cliExtensionPaths.themes),extensionPaths=(this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions)).filter(path14=>!path14.startsWith(BUILTIN_PATH_PREFIX)||!this.disabledBuiltinExtensions.has(path14.slice(BUILTIN_PATH_PREFIX.length))),packageWarnings=collectExtensionPackageWarnings(extensionPaths,metadataByPath),extensionsResult=await this.loadFinalExtensionSet(extensionPaths,preTrustExtensions);mergeExtensionWarnings(extensionsResult,packageWarnings);for(let p of this.additionalExtensionPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);existsSync16(resolved)||extensionsResult.errors.push({path:resolved,error:`Extension path does not exist: ${resolved}`})}this.extensionsResult=this.extensionsOverride?this.extensionsOverride(extensionsResult):extensionsResult,this.applyExtensionSourceInfo(this.extensionsResult.extensions,metadataByPath);let skillPaths=this.noSkills?this.mergePaths(cliEnabledSkills,this.additionalSkillPaths):this.mergePaths([...cliEnabledSkills,...enabledSkills],this.additionalSkillPaths);this.lastSkillPaths=skillPaths,this.updateSkillsFromPaths(skillPaths,metadataByPath);for(let p of this.additionalSkillPaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync16(resolved)&&!this.skillDiagnostics.some(d=>d.path===resolved)&&this.skillDiagnostics.push({type:"error",message:"Skill path does not exist",path:resolved})}let promptPaths=this.noPromptTemplates?this.mergePaths(cliEnabledPrompts,this.additionalPromptTemplatePaths):this.mergePaths([...cliEnabledPrompts,...enabledPrompts],this.additionalPromptTemplatePaths);this.lastPromptPaths=promptPaths,this.updatePromptsFromPaths(promptPaths,metadataByPath);for(let p of this.additionalPromptTemplatePaths)if(isLocalPath(p)){let resolved=this.resolveResourcePath(p);!existsSync16(resolved)&&!this.promptDiagnostics.some(d=>d.path===resolved)&&this.promptDiagnostics.push({type:"error",message:"Prompt template path does not exist",path:resolved})}let themePaths=this.noThemes?this.mergePaths(cliEnabledThemes,this.additionalThemePaths):this.mergePaths([...cliEnabledThemes,...enabledThemes],this.additionalThemePaths);this.lastThemePaths=themePaths,this.updateThemesFromPaths(themePaths,metadataByPath);for(let p of this.additionalThemePaths){let resolved=this.resolveResourcePath(p);!existsSync16(resolved)&&!this.themeDiagnostics.some(d=>d.path===resolved)&&this.themeDiagnostics.push({type:"error",message:"Theme path does not exist",path:resolved})}let agentsFiles={agentsFiles:this.noContextFiles?[]:loadProjectContextFiles({cwd:this.cwd,agentDir:this.agentDir})},resolvedAgentsFiles=this.agentsFilesOverride?this.agentsFilesOverride(agentsFiles):agentsFiles;this.agentsFiles=resolvedAgentsFiles.agentsFiles;let systemPromptSource=this.systemPromptSource??this.discoverSystemPromptFile(),baseSystemPrompt=resolvePromptInput(systemPromptSource,"system prompt");this.systemPrompt=this.systemPromptOverride?this.systemPromptOverride(baseSystemPrompt):baseSystemPrompt,this.systemPromptSourcePath=systemPromptSource&&existsSync16(systemPromptSource)?resolvePath(systemPromptSource):void 0;let appendSources=this.appendSystemPromptSource;if(!appendSources){let discoveredAppendSystemPromptFile=this.discoverAppendSystemPromptFile();appendSources=discoveredAppendSystemPromptFile?[discoveredAppendSystemPromptFile]:[]}let baseAppend=appendSources.map(s=>resolvePromptInput(s,"append system prompt")).filter(s=>s!==void 0);this.appendSystemPrompt=this.appendSystemPromptOverride?this.appendSystemPromptOverride(baseAppend):baseAppend,this.appendSystemPromptSourcePaths=appendSources.filter(source=>existsSync16(source)).map(source=>resolvePath(source)),this.loaded=!0}async loadCurrentExtensionSet(options){let resolvedPaths=await this.packageManager.resolve(),cliExtensionPaths=await this.packageManager.resolveExtensionSources(this.additionalExtensionPaths,{temporary:!0}),enabledExtensions=resolvedPaths.extensions.filter(r=>r.enabled).map(r=>r.path),cliEnabledExtensions=cliExtensionPaths.extensions.filter(r=>r.enabled).map(r=>r.path),extensionPaths=(this.noExtensions?cliEnabledExtensions:this.mergePaths(cliEnabledExtensions,enabledExtensions)).filter(path14=>!path14.startsWith(BUILTIN_PATH_PREFIX)),metadataByPath=new Map([...resolvedPaths.extensions,...cliExtensionPaths.extensions].map(resource=>[resource.path,resource.metadata])),packageWarnings=collectExtensionPackageWarnings(extensionPaths,metadataByPath),extensionsResult=await loadExtensionsCached(extensionPaths,this.cwd,this.eventBus);if(mergeExtensionWarnings(extensionsResult,packageWarnings),!options.includeInlineFactories)return extensionsResult;let inlineExtensions=await this.loadExtensionFactories(extensionsResult.runtime);extensionsResult.extensions.push(...inlineExtensions.extensions),extensionsResult.errors.push(...inlineExtensions.errors);let replacementWarnings=[];return extensionsResult.extensions=omitReplacedExtensions(extensionsResult.extensions,replacementWarnings),mergeExtensionWarnings(extensionsResult,replacementWarnings),extensionsResult}resolveExtensionLoadPath(path14){return isSyntheticPath(path14)?path14:resolvePath(path14,this.cwd,{normalizeUnicodeSpaces:!0})}async loadExtensionPaths(paths,runtime){let isBuiltinPath=path14=>path14.startsWith(BUILTIN_PATH_PREFIX),result2=await loadExtensionsCached(paths.filter(path14=>!isBuiltinPath(path14)),this.cwd,this.eventBus,runtime);for(let path14 of paths.filter(isBuiltinPath)){let builtin=this.builtinExtensions.get(path14.slice(BUILTIN_PATH_PREFIX.length));if(!builtin){result2.errors.push({path:path14,error:`Unknown built-in extension: ${path14}`});continue}try{let extension=await loadExtensionFromFactory(builtin.factory,this.cwd,this.eventBus,result2.runtime,path14);extension.hidden=!0,extension.replaceable=builtin.replaceable===!0,result2.extensions.push(extension)}catch(error){result2.errors.push({path:path14,error:error instanceof Error?error.message:"failed to load extension"})}}return result2}async loadFinalExtensionSet(extensionPaths,preTrustExtensions){let preloaded=preTrustExtensions?.extensions??[],preloadedByPath=new Map(preloaded.filter(extension=>!extension.path.startsWith("<inline:")).map(extension=>[extension.resolvedPath,extension])),failedPreloadPaths=new Set((preTrustExtensions?.errors??[]).map(error=>this.resolveExtensionLoadPath(error.path))),remainingPaths=extensionPaths.filter(path14=>{let resolvedPath=this.resolveExtensionLoadPath(path14);return!preloadedByPath.has(resolvedPath)&&!failedPreloadPaths.has(resolvedPath)}),remainingExtensions=await this.loadExtensionPaths(remainingPaths,preTrustExtensions?.runtime),loadedByPath=new Map(preloadedByPath);for(let extension of remainingExtensions.extensions)loadedByPath.set(extension.resolvedPath,extension);let inlineExtensions=preTrustExtensions?{extensions:preloaded.filter(extension=>extension.path.startsWith("<inline:")),errors:[]}:await this.loadExtensionFactories(remainingExtensions.runtime),orderedExtensions=extensionPaths.map(path14=>loadedByPath.get(this.resolveExtensionLoadPath(path14))).filter(extension=>extension!==void 0);orderedExtensions.push(...inlineExtensions.extensions);let replacementWarnings=[],extensionsResult={extensions:omitReplacedExtensions(orderedExtensions,replacementWarnings),errors:[...preTrustExtensions?.errors??[],...remainingExtensions.errors,...inlineExtensions.errors],warnings:[...preTrustExtensions?.warnings??[],...remainingExtensions.warnings??[]],runtime:remainingExtensions.runtime};return mergeExtensionWarnings(extensionsResult,replacementWarnings),this.addExtensionConflictDiagnostics(extensionsResult),extensionsResult}addExtensionConflictDiagnostics(extensionsResult){let conflicts=this.detectExtensionConflicts(extensionsResult.extensions);for(let conflict of conflicts)extensionsResult.errors.push({path:conflict.path,error:conflict.message})}mapSkillPath(resource,metadataByPath){if(resource.metadata.source!=="auto"&&resource.metadata.origin!=="package")return resource.path;try{if(!statSync11(resource.path).isDirectory())return resource.path}catch{return resource.path}let skillFile=join27(resource.path,"SKILL.md");return existsSync16(skillFile)?(metadataByPath.has(skillFile)||metadataByPath.set(skillFile,resource.metadata),skillFile):resource.path}normalizeExtensionPaths(entries){return entries.map(entry=>{let metadata=entry.metadata.baseDir?{...entry.metadata,baseDir:this.resolveResourcePath(entry.metadata.baseDir)}:entry.metadata;return{path:this.resolveResourcePath(entry.path),metadata}})}updateSkillsFromPaths(skillPaths,metadataByPath){let skillsResult;this.noSkills&&skillPaths.length===0?skillsResult={skills:[],diagnostics:[]}:skillsResult=loadSkills({cwd:this.cwd,agentDir:this.agentDir,skillPaths,includeDefaults:!1});let resolvedSkills=this.skillsOverride?this.skillsOverride(skillsResult):skillsResult;this.skills=resolvedSkills.skills.map(skill=>({...skill,sourceInfo:this.findSourceInfoForPath(skill.filePath,this.extensionSkillSourceInfos,metadataByPath)??skill.sourceInfo??this.getDefaultSourceInfoForPath(skill.filePath)})),this.skillDiagnostics=resolvedSkills.diagnostics}updatePromptsFromPaths(promptPaths,metadataByPath){let promptsResult;if(this.noPromptTemplates&&promptPaths.length===0)promptsResult={prompts:[],diagnostics:[]};else{let loaded=loadPromptTemplates({cwd:this.cwd,agentDir:this.agentDir,promptPaths,includeDefaults:!1}),deduped=this.dedupePrompts(loaded.templates);promptsResult={prompts:deduped.prompts,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedPrompts=this.promptsOverride?this.promptsOverride(promptsResult):promptsResult;this.prompts=resolvedPrompts.prompts.map(prompt=>({...prompt,sourceInfo:this.findSourceInfoForPath(prompt.filePath,this.extensionPromptSourceInfos,metadataByPath)??prompt.sourceInfo??this.getDefaultSourceInfoForPath(prompt.filePath)})),this.promptDiagnostics=resolvedPrompts.diagnostics}updateThemesFromPaths(themePaths,metadataByPath){let themesResult;if(this.noThemes&&themePaths.length===0)themesResult={themes:[],diagnostics:[]};else{let colorMode=getTerminalColorMode({...detectCapabilities(()=>!1),...this.settingsManager.getTerminalCapabilityOverrides()}),loaded=this.loadThemes(themePaths,!1,colorMode),deduped=this.dedupeThemes(loaded.themes);themesResult={themes:deduped.themes,diagnostics:[...loaded.diagnostics,...deduped.diagnostics]}}let resolvedThemes=this.themesOverride?this.themesOverride(themesResult):themesResult;this.themes=resolvedThemes.themes.map(theme2=>{let sourcePath=theme2.sourcePath;return theme2.sourceInfo=sourcePath?this.findSourceInfoForPath(sourcePath,this.extensionThemeSourceInfos,metadataByPath)??theme2.sourceInfo??this.getDefaultSourceInfoForPath(sourcePath):theme2.sourceInfo,theme2}),this.themeDiagnostics=resolvedThemes.diagnostics}applyExtensionSourceInfo(extensions,metadataByPath){for(let extension of extensions){extension.sourceInfo=this.findSourceInfoForPath(extension.path,void 0,metadataByPath)??this.getDefaultSourceInfoForPath(extension.path);for(let command of extension.commands.values())command.sourceInfo=extension.sourceInfo;for(let tool of extension.tools.values())tool.sourceInfo=extension.sourceInfo}}findSourceInfoForPath(resourcePath,extraSourceInfos,metadataByPath){if(!resourcePath)return;if(isSyntheticPath(resourcePath))return this.getDefaultSourceInfoForPath(resourcePath);let normalizedResourcePath=resolve9(resourcePath);if(extraSourceInfos)for(let[sourcePath,sourceInfo]of extraSourceInfos.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return{...sourceInfo,path:resourcePath}}if(metadataByPath){let exact=metadataByPath.get(normalizedResourcePath)??metadataByPath.get(resourcePath);if(exact)return createSourceInfo(resourcePath,exact);for(let[sourcePath,metadata]of metadataByPath.entries()){let normalizedSourcePath=resolve9(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep9}`))return createSourceInfo(resourcePath,metadata)}}}getDefaultSourceInfoForPath(filePath){let syntheticSource=getSyntheticPathSource(filePath);if(syntheticSource)return{path:filePath,source:syntheticSource,scope:"temporary",origin:"top-level"};let normalizedPath=resolve9(filePath),agentRoots=[join27(this.agentDir,"skills"),join27(this.agentDir,"prompts"),join27(this.agentDir,"themes"),join27(this.agentDir,"extensions")],projectRoots=[join27(this.cwd,CONFIG_DIR_NAME,"skills"),join27(this.cwd,CONFIG_DIR_NAME,"prompts"),join27(this.cwd,CONFIG_DIR_NAME,"themes"),join27(this.cwd,CONFIG_DIR_NAME,"extensions")];for(let root of agentRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"user",origin:"top-level",baseDir:root};for(let root of projectRoots)if(this.isUnderPath(normalizedPath,root))return{path:filePath,source:"local",scope:"project",origin:"top-level",baseDir:root};return{path:filePath,source:"local",scope:"temporary",origin:"top-level",baseDir:statSync11(normalizedPath).isDirectory()?normalizedPath:resolve9(normalizedPath,"..")}}mergePaths(primary,additional){let merged=[],seen=new Set;for(let p of[...primary,...additional]){let resolved=this.resolveResourcePath(p),canonicalPath=canonicalizePath(resolved);seen.has(canonicalPath)||(seen.add(canonicalPath),merged.push(resolved))}return merged}resolveResourcePath(p){return isSyntheticPath(p)?p:resolvePath(p,this.cwd,{trim:!0})}loadThemes(paths,includeDefaults,colorMode){let themes=[],diagnostics=[];if(includeDefaults){let defaultDirs=[join27(this.agentDir,"themes"),join27(this.cwd,CONFIG_DIR_NAME,"themes")];for(let dir of defaultDirs)this.loadThemesFromDir(dir,themes,diagnostics,colorMode)}for(let p of paths){let resolved=this.resolveResourcePath(p);if(!existsSync16(resolved)){diagnostics.push({type:"warning",message:"theme path does not exist",path:resolved});continue}try{let stats=statSync11(resolved);stats.isDirectory()?this.loadThemesFromDir(resolved,themes,diagnostics,colorMode):stats.isFile()&&resolved.endsWith(".json")?this.loadThemeFromFile(resolved,themes,diagnostics,colorMode):diagnostics.push({type:"warning",message:"theme path is not a json file",path:resolved})}catch(error){let message=error instanceof Error?error.message:"failed to read theme path";diagnostics.push({type:"warning",message,path:resolved})}}return{themes,diagnostics}}loadThemesFromDir(dir,themes,diagnostics,colorMode){if(existsSync16(dir))try{let entries=readdirSync9(dir,{withFileTypes:!0});for(let entry of entries){let isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync11(join27(dir,entry.name)).isFile()}catch{continue}isFile&&entry.name.endsWith(".json")&&this.loadThemeFromFile(join27(dir,entry.name),themes,diagnostics,colorMode)}}catch(error){let message=error instanceof Error?error.message:"failed to read theme directory";diagnostics.push({type:"warning",message,path:dir})}}loadThemeFromFile(filePath,themes,diagnostics,colorMode){try{themes.push(loadThemeFromPath(filePath,colorMode))}catch(error){let message=error instanceof Error?error.message:"failed to load theme";diagnostics.push({type:"warning",message,path:filePath})}}async loadExtensionFactories(runtime){let extensions=[],errors=[];for(let[index3,input2]of this.extensionFactories.entries()){let isNamed=typeof input2!="function",factory=isNamed?input2.factory:input2,extensionPath=`<inline:${isNamed?input2.name:index3+1}>`;try{let extension=await loadExtensionFromFactory(factory,this.cwd,this.eventBus,runtime,extensionPath);extension.hidden=isNamed&&input2.hidden,extension.replaceable=isNamed&&input2.replaceable===!0,extensions.push(extension)}catch(error){let message=error instanceof Error?error.message:"failed to load extension";errors.push({path:extensionPath,error:message})}}return{extensions,errors}}dedupePrompts(prompts){let seen=new Map,diagnostics=[];for(let prompt of prompts){let existing=seen.get(prompt.name);existing?diagnostics.push({type:"collision",message:`name "/${prompt.name}" collision`,path:prompt.filePath,collision:{resourceType:"prompt",name:prompt.name,winnerPath:existing.filePath,loserPath:prompt.filePath}}):seen.set(prompt.name,prompt)}return{prompts:Array.from(seen.values()),diagnostics}}dedupeThemes(themes){let seen=new Map,diagnostics=[];for(let t of themes){let name=t.name??"unnamed",existing=seen.get(name);existing?diagnostics.push({type:"collision",message:`name "${name}" collision`,path:t.sourcePath,collision:{resourceType:"theme",name,winnerPath:existing.sourcePath??"<builtin>",loserPath:t.sourcePath??"<builtin>"}}):seen.set(name,t)}return{themes:Array.from(seen.values()),diagnostics}}discoverSystemPromptFile(){let projectPath=join27(this.cwd,CONFIG_DIR_NAME,"SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync16(projectPath))return projectPath;let globalPath=join27(this.agentDir,"SYSTEM.md");if(existsSync16(globalPath))return globalPath}discoverAppendSystemPromptFile(){let projectPath=join27(this.cwd,CONFIG_DIR_NAME,"APPEND_SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync16(projectPath))return projectPath;let globalPath=join27(this.agentDir,"APPEND_SYSTEM.md");if(existsSync16(globalPath))return globalPath}isUnderPath(target,root){let normalizedRoot=resolve9(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep9)?normalizedRoot:`${normalizedRoot}${sep9}`;return target.startsWith(prefix)}detectExtensionConflicts(extensions){let conflicts=[],toolOwners=new Map,flagOwners=new Map;for(let ext2 of extensions){for(let toolName of ext2.tools.keys()){let existingOwner=toolOwners.get(toolName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Tool "${toolName}" conflicts with ${existingOwner}`}):toolOwners.set(toolName,ext2.path)}for(let flagName of ext2.flags.keys()){let existingOwner=flagOwners.get(flagName);existingOwner&&existingOwner!==ext2.path?conflicts.push({path:ext2.path,message:`Flag "--${flagName}" conflicts with ${existingOwner}`}):flagOwners.set(flagName,ext2.path)}}return conflicts}};import{constants as constants8,copyFileSync,existsSync as existsSync18,mkdirSync as mkdirSync9}from"node:fs";import{basename as basename11,join as join29,parse as parse2,resolve as resolve10}from"node:path";import{existsSync as existsSync17}from"node:fs";function getMissingSessionCwdIssue(sessionManager,fallbackCwd){let sessionFile=sessionManager.getSessionFile();if(!sessionFile)return;let sessionCwd=sessionManager.getCwd();if(!(!sessionCwd||existsSync17(sessionCwd)))return{sessionFile,sessionCwd,fallbackCwd}}function formatMissingSessionCwdError(issue){let sessionFile=issue.sessionFile?`
|
|
1096
1081
|
Session file: ${issue.sessionFile}`:"";return`Stored session working directory does not exist: ${issue.sessionCwd}${sessionFile}
|
|
1097
1082
|
Current working directory: ${issue.fallbackCwd}`}function formatMissingSessionCwdPrompt(issue){return`cwd from session file does not exist
|
|
@@ -1616,16 +1601,16 @@ Output:
|
|
|
1616
1601
|
`},{type:"text",text:`Script error:
|
|
1617
1602
|
${error}
|
|
1618
1603
|
|
|
1619
|
-
The script did not start.`}],details:snapshot(),isError:!0}}let
|
|
1604
|
+
The script did not start.`}],details:snapshot(),isError:!0}}let reserved2=!0,sandbox,result2;try{sandbox=new CodemodeSandbox({tools:sandboxTools,globals:[...createDiscoveryGlobals(callable,samples,options),...options.models&&ctx?createModelGlobals(ctx.modelRegistry,toolCallId,calls,publish,addModelUsage,addGeneratedImages):[]],timeoutMs:Math.max(1,Math.round(deadline-waitedMs)),memoryLimitBytes:CODEMODE_MEMORY_LIMIT_BYTES,wasm:loadQuickJSWasm(getQuickJSWasmPath()),workerUrl:getCodemodeWorkerSpecifier(),acquireWorker:()=>{if(!reserved2)throw new Error("The script already settled");return reserved2=!1,releaseCodemodeWorker}});let store=ctx?readCodemodeStore(ctx.sessionManager.getBranch()):{};result2=await sandbox.execute(code,{signal,store})}finally{await sandbox?.close(),reserved2&&(reserved2=!1,releaseCodemodeWorker())}for(let call of calls)call.status==="running"&&(call.status="cancelled");let scriptOutput=[...result2.output];if(result2.ok){let{set,delete:deleted}=result2.storeWrites;(Object.keys(set).length>0||deleted.length>0)&&options.appendEntry?.(CODEMODE_STORE_ENTRY_TYPE,{set,delete:deleted}),result2.value!==void 0&&scriptOutput.push({type:"text",text:valueText(result2.value)})}let items=formatOutput2(scriptOutput);result2.ok||items.push({type:"text",text:`Script error:
|
|
1620
1605
|
${formatError(result2,calls)}`}),generatedImages>0&&!items.some(item=>item.type==="image")&&items.push({type:"text",text:`Note: models.generateImages() returned ${generatedImages} image${generatedImages===1?"":"s"} that the script did not show. Show each image block of result.output with image(block).`});let truncated=await truncateOutput(joinAdjacentText(items),sourceOptions.maxOutputTokens??DEFAULT_MAX_OUTPUT_TOKENS),output=joinAdjacentText(await saveImages(truncated.items)),wallTime=((performance.now()-startedAt)/1e3).toFixed(1),header2=`${result2.ok?"Script completed":"Script failed"}
|
|
1621
1606
|
Wall time ${wallTime} seconds
|
|
1622
1607
|
Output:
|
|
1623
|
-
`,details=snapshot();return truncated.fullOutputPath&&(details.fullOutputPath=truncated.fullOutputPath),{content:[{type:"text",text:header2},...output],details,...modelUsage?{usage:modelUsage}:{},...result2.ok?{}:{isError:!0}}}function isNamespaceName(namespace,query){let queryId=toCodemodeIdentifier(query);return[namespace.name,...namespace.aliases??[]].some(name=>name===query||toCodemodeIdentifier(name)===queryId)}function createDiscoveryGlobals(tools,samples,options){let ranker=new Bm25Ranker,entry=name=>({name:toCodemodeIdentifier(name),description:samples.get(name)??""});return[{name:"searchTools",spread:!0,execute:args=>{let[query,searchOptions]=args;if(typeof query!="string")throw new Error("searchTools() expects a query string");let limit=searchOptions?.limit??8;if(typeof limit!="number"||!Number.isInteger(limit)||limit<=0)throw new Error("searchTools() limit must be a positive integer");let namespace=searchOptions?.namespace;if(namespace!=null&&typeof namespace!="string")throw new Error("searchTools() namespace must be a string");let documents=tools.flatMap(tool=>{let toolNamespace=options.getToolNamespace?.(tool.name);return namespace&&(!toolNamespace||!isNamespaceName(toolNamespace,namespace))?[]:[createToolSearchDocument(tool,toolNamespace)]});return ranker.rank(query,documents,limit).map(match2=>entry(match2.name))}},{name:"describeTool",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeTool() expects a tool name");let tool=tools.find(candidate=>candidate.name===name||toCodemodeIdentifier(candidate.name)===name);return tool?samples.get(tool.name):void 0}},{name:"describeNamespace",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeNamespace() expects a namespace name");let namespace,names2=[];for(let tool of tools){let toolNamespace=options.getToolNamespace?.(tool.name);!toolNamespace||!isNamespaceName(toolNamespace,name)||(namespace??=toolNamespace,names2.push(toCodemodeIdentifier(tool.name)))}if(namespace)return{name:namespace.name,...namespace.description?{description:namespace.description}:{},...namespace.instructions?{instructions:namespace.instructions}:{},tools:names2}}}]}function createModelGlobals(models,toolCallId,calls,publish,addUsage,addGeneratedImages){let limit=createLimiter(MAX_CONCURRENT_MODEL_CALLS),callCount=0,runModelCall=async(name,type,[model,context],checkContext,run)=>{let listHint=`List the ${type} models you can use with models.getAvailableOfType("${type}").`,given=model;if(typeof given?.provider!="string"||typeof given.id!="string"){let undefinedHint=model==null?" models.getModelOfType() returns undefined for an unknown provider or id.":"";throw new Error(`${name}() expects ${withArticle(type)} model as its first argument, got ${describeValue(model)}.${undefinedHint} ${listHint}`)}let provider=given.provider,id=given.id,ref=`${provider}/${id}`,resolved=models.getModelOfType(type,provider,id);if(!resolved){let actualType=[...MODEL_TYPES].find(other=>other!==type&&models.getModelOfType(other,provider,id)!==void 0);throw new Error(actualType?`"${ref}" is ${withArticle(actualType)} model, not ${withArticle(type)} model. ${listHint}`:`Unknown ${type} model "${ref}". ${listHint}`)}let checked=checkContext(context),record={id:`${toolCallId}/${name}/${++callCount}`,name,args:`${resolved.provider}/${resolved.id}`,status:"running"};calls.push(record),publish();let startedAt=performance.now(),result2=await limit(()=>run(resolved,checked));return record.durationMs=performance.now()-startedAt,record.status=result2.stopReason==="stop"?"ok":result2.stopReason==="aborted"?"cancelled":"error",result2.errorMessage&&(record.error=truncateText(result2.errorMessage,ERROR_PREVIEW_CHARS)),result2.usage&&(record.cost=result2.usage.cost.total,addUsage(result2.usage)),publish(),result2};return Object.entries({"models.getModelsOfType":args=>{let[type,provider]=args;return models.getModelsOfType(toModelType(type),toProvider(provider)).map(toModelInfo)},"models.getAvailableOfType":async(args,{signal})=>{let[type,provider]=args;return(await models.getAvailableOfType(toModelType(type),toProvider(provider),{signal})).map(toModelInfo)},"models.getModelOfType":args=>{let[type,provider,id]=args;if(typeof provider!="string"||typeof id!="string")throw new Error(`models.getModelOfType(type, provider, id) expects three strings, got (${args.map(describeValue).join(", ")}). The provider and the id are separate arguments, for example models.getModelOfType("classifier", "typesafe", "jev-latest").`);let model=models.getModelOfType(toModelType(type),provider,id);return model===void 0?void 0:toModelInfo(model)},"models.classify":(args,{signal})=>runModelCall("models.classify","classifier",args,checkClassifierContext,(resolved,context)=>models.classify(resolved,context,{signal})),"models.generateImages":(args,{signal})=>runModelCall("models.generateImages","image",args,checkImagesContext,async(resolved,context)=>{let result2=await models.generateImages(resolved,context,{signal});return addGeneratedImages(result2.output.filter(block=>block.type==="image").length),result2})}).map(([name,execute])=>({name,spread:!0,execute}))}var loadCodemodeExecutor=async()=>execute_exports;var CODE_PREVIEW_LINES=10,CALL_PREVIEW_COUNT=8,OUTPUT_PREVIEW_LINES=5,COLLAPSED_ARGS_CHARS2=80,SCRIPT_HEADER=/^Script (completed|failed)\nWall time [\d.]+ seconds\nOutput:\n$/;function expandHint(theme2,hidden,noun){return`${theme2.fg("muted",`... (${hidden} more ${noun},`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}function
|
|
1608
|
+
`,details=snapshot();return truncated.fullOutputPath&&(details.fullOutputPath=truncated.fullOutputPath),{content:[{type:"text",text:header2},...output],details,...modelUsage?{usage:modelUsage}:{},...result2.ok?{}:{isError:!0}}}function isNamespaceName(namespace,query){let queryId=toCodemodeIdentifier(query);return[namespace.name,...namespace.aliases??[]].some(name=>name===query||toCodemodeIdentifier(name)===queryId)}function createDiscoveryGlobals(tools,samples,options){let ranker=new Bm25Ranker,entry=name=>({name:toCodemodeIdentifier(name),description:samples.get(name)??""});return[{name:"searchTools",spread:!0,execute:args=>{let[query,searchOptions]=args;if(typeof query!="string")throw new Error("searchTools() expects a query string");let limit=searchOptions?.limit??8;if(typeof limit!="number"||!Number.isInteger(limit)||limit<=0)throw new Error("searchTools() limit must be a positive integer");let namespace=searchOptions?.namespace;if(namespace!=null&&typeof namespace!="string")throw new Error("searchTools() namespace must be a string");let documents=tools.flatMap(tool=>{let toolNamespace=options.getToolNamespace?.(tool.name);return namespace&&(!toolNamespace||!isNamespaceName(toolNamespace,namespace))?[]:[createToolSearchDocument(tool,toolNamespace)]});return ranker.rank(query,documents,limit).map(match2=>entry(match2.name))}},{name:"describeTool",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeTool() expects a tool name");let tool=tools.find(candidate=>candidate.name===name||toCodemodeIdentifier(candidate.name)===name);return tool?samples.get(tool.name):void 0}},{name:"describeNamespace",spread:!0,execute:args=>{let[name]=args;if(typeof name!="string")throw new Error("describeNamespace() expects a namespace name");let namespace,names2=[];for(let tool of tools){let toolNamespace=options.getToolNamespace?.(tool.name);!toolNamespace||!isNamespaceName(toolNamespace,name)||(namespace??=toolNamespace,names2.push(toCodemodeIdentifier(tool.name)))}if(namespace)return{name:namespace.name,...namespace.description?{description:namespace.description}:{},...namespace.instructions?{instructions:namespace.instructions}:{},tools:names2}}}]}function createModelGlobals(models,toolCallId,calls,publish,addUsage,addGeneratedImages){let limit=createLimiter(MAX_CONCURRENT_MODEL_CALLS),callCount=0,runModelCall=async(name,type,[model,context],checkContext,run)=>{let listHint=`List the ${type} models you can use with models.getAvailableOfType("${type}").`,given=model;if(typeof given?.provider!="string"||typeof given.id!="string"){let undefinedHint=model==null?" models.getModelOfType() returns undefined for an unknown provider or id.":"";throw new Error(`${name}() expects ${withArticle(type)} model as its first argument, got ${describeValue(model)}.${undefinedHint} ${listHint}`)}let provider=given.provider,id=given.id,ref=`${provider}/${id}`,resolved=models.getModelOfType(type,provider,id);if(!resolved){let actualType=[...MODEL_TYPES].find(other=>other!==type&&models.getModelOfType(other,provider,id)!==void 0);throw new Error(actualType?`"${ref}" is ${withArticle(actualType)} model, not ${withArticle(type)} model. ${listHint}`:`Unknown ${type} model "${ref}". ${listHint}`)}let checked=checkContext(context),record={id:`${toolCallId}/${name}/${++callCount}`,name,args:`${resolved.provider}/${resolved.id}`,status:"running"};calls.push(record),publish();let startedAt=performance.now(),result2=await limit(()=>run(resolved,checked));return record.durationMs=performance.now()-startedAt,record.status=result2.stopReason==="stop"?"ok":result2.stopReason==="aborted"?"cancelled":"error",result2.errorMessage&&(record.error=truncateText(result2.errorMessage,ERROR_PREVIEW_CHARS)),result2.usage&&(record.cost=result2.usage.cost.total,addUsage(result2.usage)),publish(),result2};return Object.entries({"models.getModelsOfType":args=>{let[type,provider]=args;return models.getModelsOfType(toModelType(type),toProvider(provider)).map(toModelInfo)},"models.getAvailableOfType":async(args,{signal})=>{let[type,provider]=args;return(await models.getAvailableOfType(toModelType(type),toProvider(provider),{signal})).map(toModelInfo)},"models.getModelOfType":args=>{let[type,provider,id]=args;if(typeof provider!="string"||typeof id!="string")throw new Error(`models.getModelOfType(type, provider, id) expects three strings, got (${args.map(describeValue).join(", ")}). The provider and the id are separate arguments, for example models.getModelOfType("classifier", "typesafe", "jev-latest").`);let model=models.getModelOfType(toModelType(type),provider,id);return model===void 0?void 0:toModelInfo(model)},"models.classify":(args,{signal})=>runModelCall("models.classify","classifier",args,checkClassifierContext,(resolved,context)=>models.classify(resolved,context,{signal})),"models.generateImages":(args,{signal})=>runModelCall("models.generateImages","image",args,checkImagesContext,async(resolved,context)=>{let result2=await models.generateImages(resolved,context,{signal});return addGeneratedImages(result2.output.filter(block=>block.type==="image").length),result2})}).map(([name,execute])=>({name,spread:!0,execute}))}var loadCodemodeExecutor=async()=>execute_exports;var CODE_PREVIEW_LINES=10,CALL_PREVIEW_COUNT=8,OUTPUT_PREVIEW_LINES=5,COLLAPSED_ARGS_CHARS2=80,SCRIPT_HEADER=/^Script (completed|failed)\nWall time [\d.]+ seconds\nOutput:\n$/;function expandHint(theme2,hidden,noun){return`${theme2.fg("muted",`... (${hidden} more ${noun},`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}function formatDuration(ms){return ms===void 0?"":ms<1e3?`${Math.round(ms)}ms`:`${(ms/1e3).toFixed(1)}s`}function formatCost(cost){return`$${cost>=.01?cost.toFixed(2):cost.toPrecision(2)}`}function statusIcon(call,theme2){switch(call.status){case"running":return theme2.fg("warning","\u2026");case"ok":return theme2.fg("success","\u2713");case"error":return theme2.fg("error","\u2717");case"cancelled":return theme2.fg("muted","\u2298")}}function formatCall(call,theme2,expanded){let args=!expanded&&call.args.length>COLLAPSED_ARGS_CHARS2?`${call.args.slice(0,COLLAPSED_ARGS_CHARS2-3)}...`:call.args,duration=formatDuration(call.durationMs),line=`${statusIcon(call,theme2)} ${theme2.fg("toolTitle",call.name)}`;return args&&(line+=` ${theme2.fg("muted",args)}`),duration&&(line+=` ${theme2.fg("dim",duration)}`),call.cost&&(line+=` ${theme2.fg("dim",formatCost(call.cost))}`),expanded&&call.error&&(line+=`
|
|
1624
1609
|
${theme2.fg("error",call.error.split(`
|
|
1625
1610
|
`).join(`
|
|
1626
|
-
`))}`),line}var codemodeRenderers={renderCall(args,theme2,context){startToolTimer(context);let code=str(args?.code),title=theme2.fg("toolTitle",theme2.bold("codemode")),component=context.lastComponent??new Container;if(component.clear(),code===null)return component.addChild(new Text(`${title} ${theme2.fg("error","[invalid arg]")}`,0,0)),component;if(component.addChild(new Text(title,0,0)),code){let highlighted=highlightCode(
|
|
1611
|
+
`))}`),line}var codemodeRenderers={renderCall(args,theme2,context){startToolTimer(context);let code=str(args?.code),title=theme2.fg("toolTitle",theme2.bold("codemode")),component=context.lastComponent??new Container;if(component.clear(),code===null)return component.addChild(new Text(`${title} ${theme2.fg("error","[invalid arg]")}`,0,0)),component;if(component.addChild(new Text(title,0,0)),code){let highlighted=highlightCode(replaceTabs2(code.replace(/\r/g,"").trimEnd()),"javascript").join(`
|
|
1627
1612
|
`);component.addChild(context.expanded?new Text(highlighted,0,0):new VisualLinePreview({text:highlighted,maxVisualLines:CODE_PREVIEW_LINES,keep:"start",formatHint:hidden=>expandHint(theme2,hidden,"lines")}))}return component},renderResult(result2,options,theme2,context){let timerText=toolTimerText(context,options.isPartial),component=context.lastComponent??new Container;component.clear();let calls=result2.details?.calls??[];if(calls.length>0){let shown=options.expanded?calls:calls.slice(-CALL_PREVIEW_COUNT),lines=shown.map(call=>formatCall(call,theme2,options.expanded));shown.length<calls.length&&lines.unshift(`${theme2.fg("muted",`... (${calls.length-shown.length} earlier calls,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`);let priced=calls.filter(call=>call.cost);if(priced.length>1){let total=priced.reduce((sum,call)=>sum+(call.cost??0),0);lines.push(theme2.fg("muted",`Model calls: ${formatCost(total)}`))}component.addChild(new Spacer(1)),component.addChild(new Text(lines.join(`
|
|
1628
|
-
`),0,0))}let[first,...rest]=result2.content,hasHeader2=first?.type==="text"&&SCRIPT_HEADER.test(first.text),output=options.isPartial?"":getTextOutput({...result2,content:hasHeader2?rest:result2.content},context.showImages).trim();if(output){let color2=context.isError?"error":"toolOutput",styled=
|
|
1613
|
+
`),0,0))}let[first,...rest]=result2.content,hasHeader2=first?.type==="text"&&SCRIPT_HEADER.test(first.text),output=options.isPartial?"":getTextOutput({...result2,content:hasHeader2?rest:result2.content},context.showImages).trim();if(output){let color2=context.isError?"error":"toolOutput",styled=replaceTabs2(output).split(`
|
|
1629
1614
|
`).map(line=>theme2.fg(color2,line)).join(`
|
|
1630
1615
|
`);if(component.addChild(new Spacer(1)),options.expanded)component.addChild(new Text(styled,0,0));else{component.addChild(new VisualLinePreview({text:styled,maxVisualLines:OUTPUT_PREVIEW_LINES,keep:"start",formatHint:hidden=>expandHint(theme2,hidden,"lines")}));let fullOutputPath=result2.details?.fullOutputPath;fullOutputPath&&component.addChild(new Text(theme2.fg("muted",`Full output: ${fullOutputPath}`),0,0))}}return timerText&&(component.addChild(new Spacer(1)),component.addChild(new Text(theme2.fg("muted",timerText),0,0))),component}};var CODEMODE_TOOL_NAME="codemode",CODEMODE_STORE_ENTRY_TYPE="codemode-store",TEXT_OUTPUT_SCHEMA={type:"string"},codemodeSchema=typebox_exports.Object({code:typebox_exports.String({description:"Raw JavaScript source."})}),codemodeToolSystemPromptContribution={snippet:"Run JavaScript that calls other tools",guidelines:["Use codemode to batch independent tool calls (Promise.allSettled), chain them, or filter large output, instead of many separate calls."]},CODEMODE_DOCS_PATH=join32(getDocsPath(),"codemode.md"),DESCRIPTION_INTRO='Run JavaScript that calls other tools. The input is raw JavaScript (not JSON, no code fence), run as an async function body in a QuickJS sandbox: top-level `await` and `return` work. No Node, file system, network, or timers.\n- `await tools.<name>({ ...args })` resolves to a string, or an object if the tool\'s declaration says so, and rejects with an Error on failure. A tool whose declaration returns an object resolves on failure too when it returned that object; check its fields. Calls still running when the script ends are cancelled.\n- Optional first line: `// @options: {"max_output_tokens": 10000, "timeout_ms": 60000}`';function describeGlobals(models){let lines=["Globals:","- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. With several text items, each starts with a `==> text N/M <==` line, and `console` lines follow the other output in one `<console_output>` block. `image()` also saves the image to a temp file and the result names its path.","- `store(key, value)` and `load(key)` keep JSON values across codemode calls.","- `ALL_TOOLS`, `await searchTools(query, { limit?, namespace? })`, `await describeTool(name)`, `await describeNamespace(name)`: find unlisted tools, such as MCP tools."];return models&&lines.push(`- \`models\`: classifiers and image generation. Read ${CODEMODE_DOCS_PATH} first.`),lines.join(`
|
|
1631
1616
|
`)}var DEFAULT_CODEMODE_INLINE_BUDGET=SETTINGS_DEFAULTS.codemode.inlineBudget,CHARS_PER_TOKEN2=4;function toCodemodeDeclaration(tool,guidelines=[]){let bullets=guidelines.flatMap(guideline=>guideline.trim()?[`- ${guideline.trim()}`]:[]);return{name:tool.name,description:bullets.length>0?`${tool.description.trim()}
|
|
@@ -1652,7 +1637,7 @@ Total output lines: ${truncation.totalLines}
|
|
|
1652
1637
|
|
|
1653
1638
|
${truncation.content}
|
|
1654
1639
|
|
|
1655
|
-
${where}`},...content.filter(block=>block.type==="image")],...fullOutputPath?{fullOutputPath}:{}}}function extensionOf(uri){let path14=URL.canParse(uri)?new URL(uri).pathname:uri;return/\.[A-Za-z0-9]{1,8}$/.exec(path14)?.[0]??".bin"}function isTextMimeType(mimeType){if(!mimeType)return!1;let type=mimeType.split(";",1)[0].trim().toLowerCase();return type.startsWith("text/")||type==="application/json"||type.endsWith("+json")||type.endsWith("+xml")}async function blockToContent(server,block,options){if(block.type==="resource_link"){let details=[block.mimeType,block.size===void 0?void 0:formatSize(block.size)].filter(Boolean),read=options.readableResources?`. Read it with ${READ_MCP_RESOURCE_TOOL} (server "${server}")`:"",description=block.description?`: ${block.description}`:"";return[{type:"text",text:`[Resource ${block.uri} "${block.title??block.name}"${details.length>0?` (${details.join(", ")})`:""}${description}${read}]`}]}if(block.type==="resource"&&"blob"in block.resource&&!block.resource.mimeType?.startsWith("image/")){let{uri,mimeType,blob}=block.resource,data=Buffer.from(blob,"base64");if(isTextMimeType(mimeType))return[{type:"text",text:data.toString("utf8")}];let kind=`${mimeType??"unknown type"}, ${formatSize(data.length)}`;try{let path14=await(options.saveOutput??saveToTempFile)(data,extensionOf(uri));return[{type:"text",text:`[Binary resource ${uri} (${kind}) saved to ${path14}]`}]}catch(error){let reason=error instanceof Error?error.message:String(error);return[{type:"text",text:`[Binary resource ${uri} (${kind}) could not be saved: ${reason}]`}]}}return toLlmContent({content:[block]})}async function toModelContent(server,blocks,options={}){return(await Promise.all(blocks.map(block=>blockToContent(server,block,options)))).flat()}async function convertMcpResult(server,tool,result2,options={}){let converted=result2.content.length>0?await toModelContent(server,result2.content,options):toLlmContent(result2);result2.isError&&textOf3(converted)===""&&converted.push({type:"text",text:`MCP tool ${server}/${tool} returned an error`});let{content,fullOutputPath}=await limitMcpContent(converted,options.saveOutput),{_meta:_ignored,...scriptResult}=result2;return{content,details:{server,tool,...fullOutputPath?{fullOutputPath}:{}},structuredContent:scriptResult,...result2.isError?{isError:!0}:{}}}function toParameters(schema){return{...schema,type:schema.type??"object",...schema.properties===void 0?{properties:{}}:{}}}var ANNOTATION_HINTS=["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"];function toToolAnnotations(tool){let annotations={};for(let hint of ANNOTATION_HINTS){let value=tool.annotations?.[hint];typeof value=="boolean"&&(annotations[hint]=value)}return Object.keys(annotations).length>0?annotations:void 0}function createMcpToolDefinition(options){let{server,tool}=options,title=tool.title??tool.annotations?.title,annotations=toToolAnnotations(tool),label=`${server}/${tool.name}`;return{name:options.name,label,description:tool.description?.trim()||title||`MCP tool ${tool.name} from server ${server}`,parameters:toParameters(tool.inputSchema),outputSchema:createMcpResultSchema(tool.outputSchema),exposure:toToolExposure(options.exposure),namespace:options.namespace,...annotations?{annotations}:{},...createMcpToolRenderers(label),async execute(_toolCallId,params,signal,onUpdate){let result2=await(await options.getClient()).callTool(tool.name,params??{},{signal,timeoutMs:options.timeoutMs,onProgress:progress=>{let total=progress.total===void 0?"":`/${progress.total}`,text2=progress.message??`Progress ${progress.progress}${total}`;onUpdate?.({content:[{type:"text",text:text2}],details:{server,tool:tool.name}})}});return convertMcpResult(server,tool.name,result2,{readableResources:options.readableResources?.()})}}}function createMcpToolRenderers(label){return{renderCall(args,theme2,context){let component=context.lastComponent??new Text("",0,0);return component.setText(formatToolCallWithArgs(label,args,theme2,context.expanded)),component},renderResult(result2,options,theme2,context){let component=context.lastComponent??new Container;component.clear();let output=getTextOutput(result2,context.showImages).trim();if(!output)return component;let color2=context.isError?"error":"toolOutput",styled=
|
|
1640
|
+
${where}`},...content.filter(block=>block.type==="image")],...fullOutputPath?{fullOutputPath}:{}}}function extensionOf(uri){let path14=URL.canParse(uri)?new URL(uri).pathname:uri;return/\.[A-Za-z0-9]{1,8}$/.exec(path14)?.[0]??".bin"}function isTextMimeType(mimeType){if(!mimeType)return!1;let type=mimeType.split(";",1)[0].trim().toLowerCase();return type.startsWith("text/")||type==="application/json"||type.endsWith("+json")||type.endsWith("+xml")}async function blockToContent(server,block,options){if(block.type==="resource_link"){let details=[block.mimeType,block.size===void 0?void 0:formatSize(block.size)].filter(Boolean),read=options.readableResources?`. Read it with ${READ_MCP_RESOURCE_TOOL} (server "${server}")`:"",description=block.description?`: ${block.description}`:"";return[{type:"text",text:`[Resource ${block.uri} "${block.title??block.name}"${details.length>0?` (${details.join(", ")})`:""}${description}${read}]`}]}if(block.type==="resource"&&"blob"in block.resource&&!block.resource.mimeType?.startsWith("image/")){let{uri,mimeType,blob}=block.resource,data=Buffer.from(blob,"base64");if(isTextMimeType(mimeType))return[{type:"text",text:data.toString("utf8")}];let kind=`${mimeType??"unknown type"}, ${formatSize(data.length)}`;try{let path14=await(options.saveOutput??saveToTempFile)(data,extensionOf(uri));return[{type:"text",text:`[Binary resource ${uri} (${kind}) saved to ${path14}]`}]}catch(error){let reason=error instanceof Error?error.message:String(error);return[{type:"text",text:`[Binary resource ${uri} (${kind}) could not be saved: ${reason}]`}]}}return toLlmContent({content:[block]})}async function toModelContent(server,blocks,options={}){return(await Promise.all(blocks.map(block=>blockToContent(server,block,options)))).flat()}async function convertMcpResult(server,tool,result2,options={}){let converted=result2.content.length>0?await toModelContent(server,result2.content,options):toLlmContent(result2);result2.isError&&textOf3(converted)===""&&converted.push({type:"text",text:`MCP tool ${server}/${tool} returned an error`});let{content,fullOutputPath}=await limitMcpContent(converted,options.saveOutput),{_meta:_ignored,...scriptResult}=result2;return{content,details:{server,tool,...fullOutputPath?{fullOutputPath}:{}},structuredContent:scriptResult,...result2.isError?{isError:!0}:{}}}function toParameters(schema){return{...schema,type:schema.type??"object",...schema.properties===void 0?{properties:{}}:{}}}var ANNOTATION_HINTS=["readOnlyHint","destructiveHint","idempotentHint","openWorldHint"];function toToolAnnotations(tool){let annotations={};for(let hint of ANNOTATION_HINTS){let value=tool.annotations?.[hint];typeof value=="boolean"&&(annotations[hint]=value)}return Object.keys(annotations).length>0?annotations:void 0}function createMcpToolDefinition(options){let{server,tool}=options,title=tool.title??tool.annotations?.title,annotations=toToolAnnotations(tool),label=`${server}/${tool.name}`;return{name:options.name,label,description:tool.description?.trim()||title||`MCP tool ${tool.name} from server ${server}`,parameters:toParameters(tool.inputSchema),outputSchema:createMcpResultSchema(tool.outputSchema),exposure:toToolExposure(options.exposure),namespace:options.namespace,...annotations?{annotations}:{},...createMcpToolRenderers(label),async execute(_toolCallId,params,signal,onUpdate){let result2=await(await options.getClient()).callTool(tool.name,params??{},{signal,timeoutMs:options.timeoutMs,onProgress:progress=>{let total=progress.total===void 0?"":`/${progress.total}`,text2=progress.message??`Progress ${progress.progress}${total}`;onUpdate?.({content:[{type:"text",text:text2}],details:{server,tool:tool.name}})}});return convertMcpResult(server,tool.name,result2,{readableResources:options.readableResources?.()})}}}function createMcpToolRenderers(label){return{renderCall(args,theme2,context){let component=context.lastComponent??new Text("",0,0);return component.setText(formatToolCallWithArgs(label,args,theme2,context.expanded)),component},renderResult(result2,options,theme2,context){let component=context.lastComponent??new Container;component.clear();let output=getTextOutput(result2,context.showImages).trim();if(!output)return component;let color2=context.isError?"error":"toolOutput",styled=replaceTabs2(output).split(`
|
|
1656
1641
|
`).map(line=>theme2.fg(color2,line)).join(`
|
|
1657
1642
|
`);if(component.addChild(new Spacer(1)),options.expanded)component.addChild(new Text(styled,0,0));else{component.addChild(new VisualLinePreview({text:styled,maxVisualLines:OUTPUT_PREVIEW_LINES2,keep:"start",formatHint:hidden=>`${theme2.fg("muted",`... (${hidden} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme2.fg("muted",")")}`}));let fullOutputPath=result2.details?.fullOutputPath;fullOutputPath&&component.addChild(new Text(theme2.fg("muted",`Full output: ${fullOutputPath}`),0,0))}return component}}}function isMcpAppResource(item){return(item.uri??item.uriTemplate??"").startsWith("ui://")||/;\s*profile\s*=\s*"?mcp-app"?/i.test(item.mimeType??"")}function listed(server,item){let{_meta,icons:_icons,...rest}=item;return{server,...rest}}var stringProperty=description=>({type:"string",description}),SERVER_FILTER=stringProperty("MCP server name. Omit to list every server with resources."),CURSOR=stringProperty("Opaque cursor from a previous call with the same server; omit for the first page."),LIST_PARAMETERS={type:"object",properties:{server:SERVER_FILTER,cursor:CURSOR},additionalProperties:!1},READ_PARAMETERS={type:"object",properties:{server:stringProperty("MCP server name exactly as configured. Must match the 'server' field returned by list_mcp_resources."),uri:stringProperty("Resource URI to read. Must be one of the URIs returned by list_mcp_resources.")},required:["server","uri"],additionalProperties:!1},optionalString2={type:"string"},LISTING_ERRORS={type:"array",description:"Servers that could not be listed",items:{type:"object",properties:{server:{type:"string"},error:{type:"string"}},required:["server","error"]}},LIST_OUTPUT_SCHEMA={type:"object",properties:{server:optionalString2,resources:{type:"array",items:{type:"object",properties:{server:{type:"string"},uri:{type:"string"},name:{type:"string"},title:optionalString2,description:optionalString2,mimeType:optionalString2,size:{type:"number"}},required:["server","uri","name"]}},nextCursor:optionalString2,errors:LISTING_ERRORS},required:["resources"]},LIST_TEMPLATES_OUTPUT_SCHEMA={type:"object",properties:{server:optionalString2,resourceTemplates:{type:"array",items:{type:"object",properties:{server:{type:"string"},uriTemplate:{type:"string",description:"RFC 6570 URI template"},name:{type:"string"},title:optionalString2,description:optionalString2,mimeType:optionalString2},required:["server","uriTemplate","name"]}},nextCursor:optionalString2,errors:LISTING_ERRORS},required:["resourceTemplates"]},READ_OUTPUT_SCHEMA={type:"object",properties:{server:{type:"string"},uri:{type:"string"},contents:{type:"array",items:{anyOf:[{type:"object",properties:{uri:{type:"string"},mimeType:optionalString2,text:{type:"string"}},required:["uri","text"]},{type:"object",properties:{uri:{type:"string"},mimeType:optionalString2,blob:{type:"string",description:"base64"}},required:["uri","blob"]}]}}},required:["server","uri","contents"]};function stringArgument(params,key){let value=params?.[key];if(value!=null){if(typeof value!="string")throw new Error(`${key} must be a string`);return value.trim()||void 0}}function errorMessage2(error){return error instanceof Error?error.message:String(error)}async function jsonResult(tool,server,payload){let{content,fullOutputPath}=await limitMcpContent([{type:"text",text:JSON.stringify(payload)}]);return{content,details:{server:server??"",tool,...fullOutputPath?{fullOutputPath}:{}},structuredContent:payload}}function createMcpResourceToolDefinitions(options){let readOnly={readOnlyHint:!0},findServer=name=>{let servers=options.servers(),server=servers.find(candidate=>candidate.name===name);if(server)return server;let available=servers.map(candidate=>candidate.name).join(", ");throw new Error(`MCP server "${name}" has no resources${available?`. Servers with resources: ${available}`:""}`)},list2=async(params,signal,key,page,all)=>{let serverName=stringArgument(params,"server"),cursor=stringArgument(params,"cursor"),visible=item=>!isMcpAppResource(item);if(serverName){let server=findServer(serverName),result2=await page(server,cursor,{signal,timeoutMs:server.timeoutMs});return{server:server.name,[key]:result2.items.filter(visible).map(item=>listed(server.name,item)),...result2.nextCursor===void 0?{}:{nextCursor:result2.nextCursor}}}if(cursor)throw new Error("cursor can only be used when a server is specified");let servers=[...options.servers()].sort((a,b2)=>a.name.localeCompare(b2.name)),results=await Promise.allSettled(servers.map(server=>all(server,{signal,timeoutMs:server.timeoutMs}))),items=[],errors=[];return results.forEach((result2,index3)=>{let server=servers[index3].name;result2.status==="fulfilled"?items.push(...result2.value.filter(visible).map(item=>listed(server,item))):errors.push({server,error:errorMessage2(result2.reason)})}),{[key]:items,...errors.length>0?{errors}:{}}},listResources={name:LIST_MCP_RESOURCES_TOOL,label:LIST_MCP_RESOURCES_TOOL,description:"Lists resources provided by MCP servers. Resources allow servers to share data that provides context to language models, such as files, database schemas, or application-specific information. Prefer resources over web search when possible.",parameters:LIST_PARAMETERS,outputSchema:LIST_OUTPUT_SCHEMA,exposure:toToolExposure(options.exposure),annotations:readOnly,async execute(_toolCallId,params,signal){let payload=await list2(params,signal,"resources",async(server,cursor,requestOptions)=>{let result2=await server.resourcesPage(cursor,requestOptions);return{items:result2.resources,nextCursor:result2.nextCursor}},(server,requestOptions)=>server.allResources(requestOptions));return jsonResult(LIST_MCP_RESOURCES_TOOL,stringArgument(params,"server"),payload)}},listTemplates2={name:LIST_MCP_RESOURCE_TEMPLATES_TOOL,label:LIST_MCP_RESOURCE_TEMPLATES_TOOL,description:"Lists resource templates provided by MCP servers. Parameterized resource templates allow servers to share data that takes parameters and provides context to language models, such as files, database schemas, or application-specific information. Prefer resource templates over web search when possible.",parameters:LIST_PARAMETERS,outputSchema:LIST_TEMPLATES_OUTPUT_SCHEMA,exposure:toToolExposure(options.exposure),annotations:readOnly,async execute(_toolCallId,params,signal){let payload=await list2(params,signal,"resourceTemplates",async(server,cursor,requestOptions)=>{let result2=await server.resourceTemplatesPage(cursor,requestOptions);return{items:result2.resourceTemplates,nextCursor:result2.nextCursor}},(server,requestOptions)=>server.allResourceTemplates(requestOptions));return jsonResult(LIST_MCP_RESOURCE_TEMPLATES_TOOL,stringArgument(params,"server"),payload)}},readResource={name:READ_MCP_RESOURCE_TOOL,label:READ_MCP_RESOURCE_TOOL,description:"Read a specific resource from an MCP server given the server name and resource URI.",parameters:READ_PARAMETERS,outputSchema:READ_OUTPUT_SCHEMA,exposure:toToolExposure(options.exposure),annotations:readOnly,async execute(_toolCallId,params,signal){let serverName=stringArgument(params,"server"),uri=stringArgument(params,"uri");if(!serverName)throw new Error("server must be provided");if(!uri)throw new Error("uri must be provided");let server=findServer(serverName),result2=await server.readResource(uri,{signal,timeoutMs:server.timeoutMs}),blocks=result2.contents.flatMap(contents2=>[...result2.contents.length>1?[{type:"text",text:`${contents2.uri}:`}]:[],{type:"resource",resource:contents2}]),converted=await toModelContent(server.name,blocks),{content,fullOutputPath}=await limitMcpContent(converted.length>0?converted:[{type:"text",text:`Resource ${uri} is empty.`}]),contents=result2.contents.map(({_meta:_ignored,...rest})=>rest);return{content,details:{server:server.name,tool:READ_MCP_RESOURCE_TOOL,...fullOutputPath?{fullOutputPath}:{}},structuredContent:{server:server.name,uri,contents}}}};return[listResources,listTemplates2,readResource]}var runtime_exports={};__export(runtime_exports,{McpOAuthCredentialStore:()=>McpOAuthCredentialStore,McpServerConnection:()=>McpServerConnection,McpServerLog:()=>McpServerLog,McpSignInCancelledError:()=>McpSignInCancelledError,createDefaultTransport:()=>createDefaultTransport,signInMcpServer:()=>signInMcpServer});import{homedir as homedir9}from"node:os";import{basename as basename12,join as join36,resolve as resolve11}from"node:path";import{setTimeout as sleep4}from"node:timers/promises";import{pathToFileURL as pathToFileURL3}from"node:url";import{createServer}from"node:http";function plainText(page){return page.ok?"Authorization complete. You may close this window.":page.details?`${page.message}
|
|
1658
1643
|
|
|
@@ -1758,9 +1743,9 @@ Some of the tools, such as tools of MCP servers, may not have been provided to y
|
|
|
1758
1743
|
${tools.map(tool=>`- ${tool.name}: ${tool.description.trim().split(/\r?\n/)[0]}`).join(`
|
|
1759
1744
|
`)}`}],details:{loaded:tools.map(tool=>tool.name)}}}}}function createToolSearchExtension(){return pi=>{pi.registerTool({...createToolSearchToolDefinition({tools:pi}),defaultActive:!1})}}var tool_search_default=createToolSearchExtension();var BorderedLoader=class extends Container{constructor(tui,theme2,message,options){super(),this.cancellable=options?.cancellable??!0;let borderColor=s=>theme2.fg("border",s);this.addChild(new DynamicBorder(borderColor)),this.cancellable?this.loader=new CancellableLoader(tui,s=>theme2.fg("accent",s),s=>theme2.fg("muted",s),message):(this.signalController=new AbortController,this.loader=new Loader(tui,s=>theme2.fg("accent",s),s=>theme2.fg("muted",s),message)),this.addChild(this.loader),this.cancellable&&(this.addChild(new Spacer(1)),this.addChild(new Text(keyHint("tui.select.cancel","cancel"),1,0))),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(borderColor))}get signal(){return this.cancellable?this.loader.signal:this.signalController?.signal??new AbortController().signal}set onAbort(fn){this.cancellable&&(this.loader.onAbort=fn)}handleInput(data){this.cancellable&&this.loader.handleInput(data)}dispose(){"dispose"in this.loader&&typeof this.loader.dispose=="function"?this.loader.dispose():"stop"in this.loader&&typeof this.loader.stop=="function"&&this.loader.stop()}};var import_cross_spawn3=__toESM(require_cross_spawn(),1);import{mkdtempSync,readFileSync as readFileSync17,rmSync as rmSync3,writeFileSync as writeFileSync11}from"node:fs";import{tmpdir as tmpdir4}from"node:os";import{join as join38}from"node:path";function parseEditorCommand(command){let args=[],current="",quote,started=!1;for(let char of command.trim()){if(quote){char===quote?quote=void 0:current+=char,started=!0;continue}if(char==='"'||char==="'"){quote=char,started=!0;continue}if(/\s/u.test(char)){started&&(args.push(current),current="",started=!1);continue}current+=char,started=!0}return started&&args.push(current),args}async function editInExternalEditor(options){let directory=mkdtempSync(join38(tmpdir4(),"pi-editor-")),filePath=join38(directory,"prompt.md");try{writeFileSync11(filePath,options.content,"utf-8");let[editor,...editorArgs]=parseEditorCommand(options.command);return editor?(process.stdout.write(`Launching external editor: ${options.command}
|
|
1760
1745
|
Pi will resume when the editor exits.
|
|
1761
|
-
`),await new Promise(resolve20=>{let child=(0,import_cross_spawn3.default)(editor,[...editorArgs,filePath],{stdio:"inherit"});child.on("error",()=>resolve20(null)),child.on("close",code=>resolve20(code))})!==0?{status:"failed"}:{status:"complete",content:stripBom(readFileSync17(filePath,"utf-8")).replace(/\n$/,"")}):{status:"failed"}}finally{try{rmSync3(directory,{recursive:!0,force:!0})}catch{}}}var ExtensionEditorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.editor.focused=value}constructor(tui,keybindings,title,prefill,onSubmit,onCancel,options,externalEditorCommand){super(),this._focused=!1,this.tui=tui,this.keybindings=keybindings,this.externalEditorCommand=externalEditorCommand||process.env.VISUAL||process.env.EDITOR||(process.platform==="win32"?"notepad":"nano"),this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel;let{description,...editorOptions}=options??{};this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",title),1,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",description),1,0))),this.addChild(new Spacer(1)),this.editor=new Editor(tui,getEditorTheme(),editorOptions),prefill&&this.editor.setText(prefill),this.editor.onSubmit=text2=>{this.onSubmitCallback(text2)},this.addChild(this.editor),this.addChild(new Spacer(1));let hint=keyHint("tui.select.confirm","submit")+" "+keyHint("tui.input.newLine","newline")+" "+keyHint("tui.select.cancel","cancel")+` ${keyHint("app.editor.external","external editor")}`;this.addChild(new Text(hint,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){if(getKeybindings().matches(keyData,"tui.select.cancel")){this.onCancelCallback();return}if(this.keybindings.matches(keyData,"app.editor.external")){this.handleOpenExternalEditor();return}this.editor.handleInput(keyData)}async handleOpenExternalEditor(){let content=this.editor.getText();this.tui.stop();try{let result2=await editInExternalEditor({command:this.externalEditorCommand,content});result2.status==="complete"&&this.editor.setText(result2.content)}finally{this.tui.start(),this.tui.requestRender(!0)}}};var ARMIN_WIDTH=31,ARMIN_HEIGHT=36,WIDTH=ARMIN_WIDTH,HEIGHT=ARMIN_HEIGHT,BITS=[255,255,255,127,255,240,255,127,255,237,255,127,255,219,255,127,255,183,255,127,255,119,254,127,63,248,254,127,223,255,254,127,223,63,252,127,159,195,251,127,111,252,244,127,247,15,247,127,247,255,247,127,247,255,227,127,247,7,232,127,239,248,103,112,15,255,187,111,241,0,208,91,253,63,236,83,193,255,239,87,159,253,238,95,159,252,174,95,31,120,172,95,63,0,80,108,127,0,220,119,255,192,63,120,255,1,248,127,255,3,156,120,255,7,140,124,255,15,206,120,255,255,207,127,255,255,207,120,255,255,223,120,255,255,223,125,255,255,63,126,255,255,255,127],BYTES_PER_ROW=Math.ceil(WIDTH/8),DISPLAY_HEIGHT=Math.ceil(HEIGHT/2),EFFECTS=["typewriter","scanline","rain","fade","crt","glitch","dissolve"];function isArminPixel(x2,y2){if(y2>=HEIGHT)return!1;let byteIndex=y2*BYTES_PER_ROW+Math.floor(x2/8),bitIndex=x2%8;return(BITS[byteIndex]>>bitIndex&1)===0}function getChar(x2,row){let upper=isArminPixel(x2,row*2),lower=isArminPixel(x2,row*2+1);return upper&&lower?"\u2588":upper?"\u2580":lower?"\u2584":" "}function buildFinalGrid(){let grid=[];for(let row=0;row<DISPLAY_HEIGHT;row++){let line=[];for(let x2=0;x2<WIDTH;x2++)line.push(getChar(x2,row));grid.push(line)}return grid}var ArminComponent=class{constructor(ui){this.interval=null,this.effectState={},this.cachedLines=[],this.cachedWidth=0,this.gridVersion=0,this.cachedVersion=-1,this.ui=ui,this.effect=EFFECTS[Math.floor(Math.random()*EFFECTS.length)],this.finalGrid=buildFinalGrid(),this.currentGrid=this.createEmptyGrid(),this.initEffect(),this.startAnimation()}invalidate(){this.cachedWidth=0}render(width){if(width===this.cachedWidth&&this.cachedVersion===this.gridVersion)return this.cachedLines;let padding=1,availableWidth=width-padding;this.cachedLines=this.currentGrid.map(row=>{let clipped=row.slice(0,availableWidth).join(""),padRight=Math.max(0,width-padding-clipped.length);return` ${theme.fg("accent",clipped)}${" ".repeat(padRight)}`});let message="ARMIN SAYS HI",msgPadRight=Math.max(0,width-padding-message.length);return this.cachedLines.push(` ${theme.fg("accent",message)}${" ".repeat(msgPadRight)}`),this.cachedWidth=width,this.cachedVersion=this.gridVersion,this.cachedLines}createEmptyGrid(){return Array.from({length:DISPLAY_HEIGHT},()=>Array(WIDTH).fill(" "))}initEffect(){switch(this.effect){case"typewriter":this.effectState={pos:0};break;case"scanline":this.effectState={row:0};break;case"rain":this.effectState={drops:Array.from({length:WIDTH},()=>({y:-Math.floor(Math.random()*DISPLAY_HEIGHT*2),settled:0}))};break;case"fade":{let positions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)positions.push([row,x2]);for(let i=positions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[positions[i],positions[j2]]=[positions[j2],positions[i]]}this.effectState={positions,idx:0};break}case"crt":this.effectState={expansion:0};break;case"glitch":this.effectState={phase:0,glitchFrames:8};break;case"dissolve":{this.currentGrid=Array.from({length:DISPLAY_HEIGHT},()=>Array.from({length:WIDTH},()=>{let chars=[" ","\u2591","\u2592","\u2593","\u2588","\u2580","\u2584"];return chars[Math.floor(Math.random()*chars.length)]}));let dissolvePositions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)dissolvePositions.push([row,x2]);for(let i=dissolvePositions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[dissolvePositions[i],dissolvePositions[j2]]=[dissolvePositions[j2],dissolvePositions[i]]}this.effectState={positions:dissolvePositions,idx:0};break}}}startAnimation(){let fps=this.effect==="glitch"?60:30;this.interval=setInterval(()=>{let done=this.tickEffect();this.updateDisplay(),this.ui.requestRender(),done&&this.stopAnimation()},1e3/fps)}stopAnimation(){this.interval&&(clearInterval(this.interval),this.interval=null)}tickEffect(){switch(this.effect){case"typewriter":return this.tickTypewriter();case"scanline":return this.tickScanline();case"rain":return this.tickRain();case"fade":return this.tickFade();case"crt":return this.tickCrt();case"glitch":return this.tickGlitch();case"dissolve":return this.tickDissolve();default:return!0}}tickTypewriter(){let state2=this.effectState,pixelsPerFrame=3;for(let i=0;i<pixelsPerFrame;i++){let row=Math.floor(state2.pos/WIDTH),x2=state2.pos%WIDTH;if(row>=DISPLAY_HEIGHT)return!0;this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.pos++}return!1}tickScanline(){let state2=this.effectState;if(state2.row>=DISPLAY_HEIGHT)return!0;for(let x2=0;x2<WIDTH;x2++)this.currentGrid[state2.row][x2]=this.finalGrid[state2.row][x2];return state2.row++,!1}tickRain(){let state2=this.effectState,allSettled=!0;this.currentGrid=this.createEmptyGrid();for(let x2=0;x2<WIDTH;x2++){let drop=state2.drops[x2];for(let row=DISPLAY_HEIGHT-1;row>=DISPLAY_HEIGHT-drop.settled;row--)row>=0&&(this.currentGrid[row][x2]=this.finalGrid[row][x2]);if(drop.settled>=DISPLAY_HEIGHT)continue;allSettled=!1;let targetRow=-1;for(let row=DISPLAY_HEIGHT-1-drop.settled;row>=0;row--)if(this.finalGrid[row][x2]!==" "){targetRow=row;break}drop.y++,drop.y>=0&&drop.y<DISPLAY_HEIGHT&&(targetRow>=0&&drop.y>=targetRow?(drop.settled=DISPLAY_HEIGHT-targetRow,drop.y=-Math.floor(Math.random()*5)-1):this.currentGrid[drop.y][x2]="\u2593")}return allSettled}tickFade(){let state2=this.effectState,pixelsPerFrame=15;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}tickCrt(){let state2=this.effectState,midRow=Math.floor(DISPLAY_HEIGHT/2);this.currentGrid=this.createEmptyGrid();let top=midRow-state2.expansion,bottom=midRow+state2.expansion;for(let row=Math.max(0,top);row<=Math.min(DISPLAY_HEIGHT-1,bottom);row++)for(let x2=0;x2<WIDTH;x2++)this.currentGrid[row][x2]=this.finalGrid[row][x2];return state2.expansion++,state2.expansion>DISPLAY_HEIGHT}tickGlitch(){let state2=this.effectState;return state2.phase<state2.glitchFrames?(this.currentGrid=this.finalGrid.map(row=>{let offset=Math.floor(Math.random()*7)-3,glitchRow=[...row];if(Math.random()<.3)return glitchRow.slice(offset).concat(glitchRow.slice(0,offset)).slice(0,WIDTH);if(Math.random()<.2){let swapRow=Math.floor(Math.random()*DISPLAY_HEIGHT);return[...this.finalGrid[swapRow]]}return glitchRow}),state2.phase++,!1):(this.currentGrid=this.finalGrid.map(row=>[...row]),!0)}tickDissolve(){let state2=this.effectState,pixelsPerFrame=20;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}updateDisplay(){this.gridVersion++}dispose(){this.stopAnimation()}};function createMarkdownTransform(messageType,isStreaming,transformers){return(markdown,availableWidth)=>applyMarkdownTransformers(markdown,{messageType,isStreaming,availableWidth},transformers)}function applyMarkdownTransformers(markdown,context,transformers){let transformedMarkdown=markdown;for(let transformer of transformers)try{let transformed=transformer(transformedMarkdown,context);typeof transformed=="string"&&(transformedMarkdown=transformed)}catch{}return transformedMarkdown}var OSC133_ZONE_START="\x1B]133;A\x07",OSC133_ZONE_END="\x1B]133;B\x07",OSC133_ZONE_FINAL="\x1B]133;C\x07",AssistantMessageComponent=class extends Container{constructor(message,hideThinkingBlock=!1,markdownTheme=getMarkdownTheme(),hiddenThinkingLabel="Thinking...",outputPad=1,markdownTransformers=[]){super(),this.hasToolCalls=!1,this.isStreaming=!1,this.thinkingVisibilityOverrides=new Map,this.hideThinkingBlock=hideThinkingBlock,this.markdownTheme=markdownTheme,this.hiddenThinkingLabel=hiddenThinkingLabel,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.contentContainer=new Container,this.addChild(this.contentContainer),message&&this.updateContent(message)}invalidate(){super.invalidate(),this.lastMessage&&this.updateContent(this.lastMessage)}setHideThinkingBlock(hide){this.hideThinkingBlock=hide,this.thinkingVisibilityOverrides.clear(),this.lastMessage&&this.updateContent(this.lastMessage)}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label,this.lastMessage&&this.updateContent(this.lastMessage)}setOutputPad(padding){this.outputPad=padding,this.lastMessage&&this.updateContent(this.lastMessage)}render(width){let lines=super.render(width);return this.hasToolCalls||lines.length===0||(lines[0]=OSC133_ZONE_START+lines[0],lines[lines.length-1]=OSC133_ZONE_END+OSC133_ZONE_FINAL+lines[lines.length-1]),lines}updateContent(message,isStreaming=this.isStreaming){this.lastMessage=message,this.isStreaming=isStreaming,this.contentContainer.clear(),message.content.some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim())&&this.contentContainer.addChild(new Spacer(1));let thinkingRunIndex=0;for(let i=0;i<message.content.length;i++){let content=message.content[i];if(content.type==="text"&&content.text.trim())this.contentContainer.addChild(new Markdown(content.text.trim(),this.outputPad,0,this.markdownTheme,void 0,{transform:createMarkdownTransform("assistant",this.isStreaming,this.markdownTransformers)}));else if(content.type==="thinking"){let thinkingBlocks=[];for(;i<message.content.length;i++){let thinkingContent=message.content[i];if(thinkingContent.type!=="thinking")break;let thinking=thinkingContent.thinking.trim();thinking&&thinkingBlocks.push(thinking)}if(i--,thinkingBlocks.length===0)continue;let hasVisibleContentAfter=message.content.slice(i+1).some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim()),runIndex=thinkingRunIndex++,hidden=this.thinkingVisibilityOverrides.get(runIndex)??this.hideThinkingBlock,thinkingComponent=hidden?new Text(theme.italic(theme.fg("thinkingText",this.hiddenThinkingLabel)),this.outputPad,0):new Markdown(thinkingBlocks.join(`
|
|
1746
|
+
`),await new Promise(resolve20=>{let child=(0,import_cross_spawn3.default)(editor,[...editorArgs,filePath],{stdio:"inherit"});child.on("error",()=>resolve20(null)),child.on("close",code=>resolve20(code))})!==0?{status:"failed"}:{status:"complete",content:stripBom(readFileSync17(filePath,"utf-8")).replace(/\n$/,"")}):{status:"failed"}}finally{try{rmSync3(directory,{recursive:!0,force:!0})}catch{}}}var ExtensionEditorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.editor.focused=value}constructor(tui,keybindings,title,prefill,onSubmit,onCancel,options,externalEditorCommand){super(),this._focused=!1,this.tui=tui,this.keybindings=keybindings,this.externalEditorCommand=externalEditorCommand||process.env.VISUAL||process.env.EDITOR||(process.platform==="win32"?"notepad":"nano"),this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel;let{description,...editorOptions}=options??{};this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",title),1,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("text",description),1,0))),this.addChild(new Spacer(1)),this.editor=new Editor(tui,getEditorTheme(),editorOptions),prefill&&this.editor.setText(prefill),this.editor.onSubmit=text2=>{this.onSubmitCallback(text2)},this.addChild(this.editor),this.addChild(new Spacer(1));let hint=keyHint("tui.select.confirm","submit")+" "+keyHint("tui.input.newLine","newline")+" "+keyHint("tui.select.cancel","cancel")+` ${keyHint("app.editor.external","external editor")}`;this.addChild(new Text(hint,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){if(getKeybindings().matches(keyData,"tui.select.cancel")){this.onCancelCallback();return}if(this.keybindings.matches(keyData,"app.editor.external")){this.handleOpenExternalEditor();return}this.editor.handleInput(keyData)}async handleOpenExternalEditor(){let content=this.editor.getText();this.tui.stop();try{let result2=await editInExternalEditor({command:this.externalEditorCommand,content});result2.status==="complete"&&this.editor.setText(result2.content)}finally{this.tui.start(),this.tui.requestRender(!0)}}};var ARMIN_WIDTH=31,ARMIN_HEIGHT=36,WIDTH=ARMIN_WIDTH,HEIGHT=ARMIN_HEIGHT,BITS=[255,255,255,127,255,240,255,127,255,237,255,127,255,219,255,127,255,183,255,127,255,119,254,127,63,248,254,127,223,255,254,127,223,63,252,127,159,195,251,127,111,252,244,127,247,15,247,127,247,255,247,127,247,255,227,127,247,7,232,127,239,248,103,112,15,255,187,111,241,0,208,91,253,63,236,83,193,255,239,87,159,253,238,95,159,252,174,95,31,120,172,95,63,0,80,108,127,0,220,119,255,192,63,120,255,1,248,127,255,3,156,120,255,7,140,124,255,15,206,120,255,255,207,127,255,255,207,120,255,255,223,120,255,255,223,125,255,255,63,126,255,255,255,127],BYTES_PER_ROW=Math.ceil(WIDTH/8),DISPLAY_HEIGHT=Math.ceil(HEIGHT/2),EFFECTS=["typewriter","scanline","rain","fade","crt","glitch","dissolve"];function isArminPixel(x2,y2){if(y2>=HEIGHT)return!1;let byteIndex=y2*BYTES_PER_ROW+Math.floor(x2/8),bitIndex=x2%8;return(BITS[byteIndex]>>bitIndex&1)===0}function getChar(x2,row){let upper=isArminPixel(x2,row*2),lower=isArminPixel(x2,row*2+1);return upper&&lower?"\u2588":upper?"\u2580":lower?"\u2584":" "}function buildFinalGrid(){let grid=[];for(let row=0;row<DISPLAY_HEIGHT;row++){let line=[];for(let x2=0;x2<WIDTH;x2++)line.push(getChar(x2,row));grid.push(line)}return grid}var ArminComponent=class{constructor(ui){this.interval=null,this.effectState={},this.cachedLines=[],this.cachedWidth=0,this.gridVersion=0,this.cachedVersion=-1,this.ui=ui,this.effect=EFFECTS[Math.floor(Math.random()*EFFECTS.length)],this.finalGrid=buildFinalGrid(),this.currentGrid=this.createEmptyGrid(),this.initEffect(),this.startAnimation()}invalidate(){this.cachedWidth=0}render(width){if(width===this.cachedWidth&&this.cachedVersion===this.gridVersion)return this.cachedLines;let padding=1,availableWidth=width-padding;this.cachedLines=this.currentGrid.map(row=>{let clipped=row.slice(0,availableWidth).join(""),padRight=Math.max(0,width-padding-clipped.length);return` ${theme.fg("accent",clipped)}${" ".repeat(padRight)}`});let message="ARMIN SAYS HI",msgPadRight=Math.max(0,width-padding-message.length);return this.cachedLines.push(` ${theme.fg("accent",message)}${" ".repeat(msgPadRight)}`),this.cachedWidth=width,this.cachedVersion=this.gridVersion,this.cachedLines}createEmptyGrid(){return Array.from({length:DISPLAY_HEIGHT},()=>Array(WIDTH).fill(" "))}initEffect(){switch(this.effect){case"typewriter":this.effectState={pos:0};break;case"scanline":this.effectState={row:0};break;case"rain":this.effectState={drops:Array.from({length:WIDTH},()=>({y:-Math.floor(Math.random()*DISPLAY_HEIGHT*2),settled:0}))};break;case"fade":{let positions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)positions.push([row,x2]);for(let i=positions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[positions[i],positions[j2]]=[positions[j2],positions[i]]}this.effectState={positions,idx:0};break}case"crt":this.effectState={expansion:0};break;case"glitch":this.effectState={phase:0,glitchFrames:8};break;case"dissolve":{this.currentGrid=Array.from({length:DISPLAY_HEIGHT},()=>Array.from({length:WIDTH},()=>{let chars=[" ","\u2591","\u2592","\u2593","\u2588","\u2580","\u2584"];return chars[Math.floor(Math.random()*chars.length)]}));let dissolvePositions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x2=0;x2<WIDTH;x2++)dissolvePositions.push([row,x2]);for(let i=dissolvePositions.length-1;i>0;i--){let j2=Math.floor(Math.random()*(i+1));[dissolvePositions[i],dissolvePositions[j2]]=[dissolvePositions[j2],dissolvePositions[i]]}this.effectState={positions:dissolvePositions,idx:0};break}}}startAnimation(){let fps=this.effect==="glitch"?60:30;this.interval=setInterval(()=>{let done=this.tickEffect();this.updateDisplay(),this.ui.requestRender(),done&&this.stopAnimation()},1e3/fps)}stopAnimation(){this.interval&&(clearInterval(this.interval),this.interval=null)}tickEffect(){switch(this.effect){case"typewriter":return this.tickTypewriter();case"scanline":return this.tickScanline();case"rain":return this.tickRain();case"fade":return this.tickFade();case"crt":return this.tickCrt();case"glitch":return this.tickGlitch();case"dissolve":return this.tickDissolve();default:return!0}}tickTypewriter(){let state2=this.effectState,pixelsPerFrame=3;for(let i=0;i<pixelsPerFrame;i++){let row=Math.floor(state2.pos/WIDTH),x2=state2.pos%WIDTH;if(row>=DISPLAY_HEIGHT)return!0;this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.pos++}return!1}tickScanline(){let state2=this.effectState;if(state2.row>=DISPLAY_HEIGHT)return!0;for(let x2=0;x2<WIDTH;x2++)this.currentGrid[state2.row][x2]=this.finalGrid[state2.row][x2];return state2.row++,!1}tickRain(){let state2=this.effectState,allSettled=!0;this.currentGrid=this.createEmptyGrid();for(let x2=0;x2<WIDTH;x2++){let drop=state2.drops[x2];for(let row=DISPLAY_HEIGHT-1;row>=DISPLAY_HEIGHT-drop.settled;row--)row>=0&&(this.currentGrid[row][x2]=this.finalGrid[row][x2]);if(drop.settled>=DISPLAY_HEIGHT)continue;allSettled=!1;let targetRow=-1;for(let row=DISPLAY_HEIGHT-1-drop.settled;row>=0;row--)if(this.finalGrid[row][x2]!==" "){targetRow=row;break}drop.y++,drop.y>=0&&drop.y<DISPLAY_HEIGHT&&(targetRow>=0&&drop.y>=targetRow?(drop.settled=DISPLAY_HEIGHT-targetRow,drop.y=-Math.floor(Math.random()*5)-1):this.currentGrid[drop.y][x2]="\u2593")}return allSettled}tickFade(){let state2=this.effectState,pixelsPerFrame=15;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}tickCrt(){let state2=this.effectState,midRow=Math.floor(DISPLAY_HEIGHT/2);this.currentGrid=this.createEmptyGrid();let top=midRow-state2.expansion,bottom=midRow+state2.expansion;for(let row=Math.max(0,top);row<=Math.min(DISPLAY_HEIGHT-1,bottom);row++)for(let x2=0;x2<WIDTH;x2++)this.currentGrid[row][x2]=this.finalGrid[row][x2];return state2.expansion++,state2.expansion>DISPLAY_HEIGHT}tickGlitch(){let state2=this.effectState;return state2.phase<state2.glitchFrames?(this.currentGrid=this.finalGrid.map(row=>{let offset=Math.floor(Math.random()*7)-3,glitchRow=[...row];if(Math.random()<.3)return glitchRow.slice(offset).concat(glitchRow.slice(0,offset)).slice(0,WIDTH);if(Math.random()<.2){let swapRow=Math.floor(Math.random()*DISPLAY_HEIGHT);return[...this.finalGrid[swapRow]]}return glitchRow}),state2.phase++,!1):(this.currentGrid=this.finalGrid.map(row=>[...row]),!0)}tickDissolve(){let state2=this.effectState,pixelsPerFrame=20;for(let i=0;i<pixelsPerFrame;i++){if(state2.idx>=state2.positions.length)return!0;let[row,x2]=state2.positions[state2.idx];this.currentGrid[row][x2]=this.finalGrid[row][x2],state2.idx++}return!1}updateDisplay(){this.gridVersion++}dispose(){this.stopAnimation()}};function createMarkdownTransform(messageType,isStreaming,transformers){return(markdown,availableWidth)=>applyMarkdownTransformers(markdown,{messageType,isStreaming,availableWidth},transformers)}function applyMarkdownTransformers(markdown,context,transformers){let transformedMarkdown=markdown;for(let transformer of transformers)try{let transformed=transformer(transformedMarkdown,context);typeof transformed=="string"&&(transformedMarkdown=transformed)}catch{}return transformedMarkdown}var OSC133_ZONE_START="\x1B]133;A\x07",OSC133_ZONE_END="\x1B]133;B\x07",OSC133_ZONE_FINAL="\x1B]133;C\x07",SETTLED_THINKING_LABEL="Thoughts",THINKING_PREVIEW_LINES=3,THINKING_PREVIEW_INDENT=2,DEFAULT_ACTIVE_THINKING_LABEL="Thinking...";function isVisibleAssistantBlock(block){return block.type==="text"&&block.text.trim().length>0||block.type==="thinking"&&block.thinking.trim().length>0}function styleThinkingText(text2){return theme.italic(theme.fg("thinkingText",text2))}function createThinkingLabel(label,outputPad){return new Text(styleThinkingText(label),outputPad,0)}var ThinkingRollingPreview=class{constructor(text2,paddingX){this.body=new Text(styleThinkingText(text2),paddingX,0)}invalidate(){this.body.invalidate()}render(width){return width<=0?[]:this.body.render(width).slice(-THINKING_PREVIEW_LINES)}};function createThinkingComponent(options){if(options.view==="active"){let container=new Container;return container.addChild(createThinkingLabel(options.activeLabel,options.outputPad)),container.addChild(new ThinkingRollingPreview(options.text,options.outputPad+THINKING_PREVIEW_INDENT)),container}return options.view==="settled"?createThinkingLabel(SETTLED_THINKING_LABEL,options.outputPad):new Markdown(options.text,options.outputPad,0,options.markdownTheme,{color:text2=>theme.fg("thinkingText",text2),italic:!0},{transform:createMarkdownTransform("assistant-thinking",options.isStreaming,options.markdownTransformers)})}var AssistantMessageComponent=class extends Container{constructor(message,hideThinkingBlock=!1,markdownTheme=getMarkdownTheme(),activeThinkingLabel=DEFAULT_ACTIVE_THINKING_LABEL,outputPad=1,markdownTransformers=[]){super(),this.hasToolCalls=!1,this.isStreaming=!1,this.thinkingVisibilityOverrides=new Map,this.hideThinkingBlock=hideThinkingBlock,this.markdownTheme=markdownTheme,this.activeThinkingLabel=activeThinkingLabel,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.contentContainer=new Container,this.addChild(this.contentContainer),message&&this.updateContent(message)}invalidate(){super.invalidate(),this.lastMessage&&this.updateContent(this.lastMessage)}setHideThinkingBlock(hide){this.hideThinkingBlock=hide,this.thinkingVisibilityOverrides.clear(),this.lastMessage&&this.updateContent(this.lastMessage)}setHiddenThinkingLabel(label){this.activeThinkingLabel=label,this.lastMessage&&this.updateContent(this.lastMessage)}setOutputPad(padding){this.outputPad=padding,this.lastMessage&&this.updateContent(this.lastMessage)}render(width){let lines=super.render(width);return this.hasToolCalls||lines.length===0||(lines[0]=OSC133_ZONE_START+lines[0],lines[lines.length-1]=OSC133_ZONE_END+OSC133_ZONE_FINAL+lines[lines.length-1]),lines}updateContent(message,isStreaming=this.isStreaming){this.lastMessage=message,this.isStreaming=isStreaming,this.contentContainer.clear(),message.content.some(isVisibleAssistantBlock)&&this.contentContainer.addChild(new Spacer(1));let thinkingRunIndex=0;for(let i=0;i<message.content.length;i++){let content=message.content[i];if(content.type==="text"&&content.text.trim())this.contentContainer.addChild(new Markdown(content.text.trim(),this.outputPad,0,this.markdownTheme,void 0,{transform:createMarkdownTransform("assistant",this.isStreaming,this.markdownTransformers)}));else if(content.type==="thinking"){let thinkingBlocks=[];for(;i<message.content.length;i++){let thinkingContent=message.content[i];if(thinkingContent.type!=="thinking")break;let thinking=thinkingContent.thinking.trim();thinking&&thinkingBlocks.push(thinking)}if(i--,thinkingBlocks.length===0)continue;let remaining=message.content.slice(i+1),hasVisibleContentAfter=remaining.some(isVisibleAssistantBlock),hasToolCallAfter=remaining.some(block=>block.type==="toolCall"),isActiveThinking=this.isStreaming&&!hasVisibleContentAfter&&!hasToolCallAfter,runIndex=thinkingRunIndex++,hidden=this.thinkingVisibilityOverrides.get(runIndex)??this.hideThinkingBlock,thinkingComponent=createThinkingComponent({view:hidden?isActiveThinking?"active":"settled":"expanded",text:thinkingBlocks.join(`
|
|
1762
1747
|
|
|
1763
|
-
`),this.outputPad
|
|
1748
|
+
`),activeLabel:this.activeThinkingLabel,outputPad:this.outputPad,markdownTheme:this.markdownTheme,isStreaming:this.isStreaming,markdownTransformers:this.markdownTransformers});this.contentContainer.addChild(new MouseRegion(thinkingComponent,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.thinkingVisibilityOverrides.set(runIndex,!hidden),this.lastMessage&&this.updateContent(this.lastMessage),{handled:!0}})),hasVisibleContentAfter&&this.contentContainer.addChild(new Spacer(1))}}let hasToolCalls=message.content.some(c=>c.type==="toolCall");if(this.hasToolCalls=hasToolCalls,message.stopReason==="length")this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("error","Response was truncated before completion."),this.outputPad,0));else if(!hasToolCalls){if(message.stopReason==="aborted"){let abortMessage=message.errorMessage&&message.errorMessage!=="Request was aborted"?message.errorMessage:"Operation aborted";this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("error",abortMessage),this.outputPad,0))}else if(message.stopReason==="error"){let errorMsg=message.errorMessage||"Unknown error";this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("error",`Error: ${errorMsg}`),this.outputPad,0))}}}};var PREVIEW_LINES=20,BashExecutionComponent=class extends Container{constructor(command,ui,excludeFromContext=!1,outputPad=1){super(),this.outputLines=[],this.status="running",this.exitCode=void 0,this.expanded=!1,this.command=command,this.colorKey=excludeFromContext?"dim":"bashMode",this.outputPad=outputPad;let borderColor=str2=>theme.fg(this.colorKey,str2);this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(borderColor)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.loader=new Loader(ui,spinner=>theme.fg(this.colorKey,spinner),text2=>theme.fg("muted",text2),`Running... (${keyText("tui.select.cancel")} to cancel)`),this.addChild(new DynamicBorder(borderColor)),this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.outputPad=outputPad,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}appendOutput(chunk){let newLines=stripAnsi(chunk).replace(/\r\n/g,`
|
|
1764
1749
|
`).replace(/\r/g,`
|
|
1765
1750
|
`).split(`
|
|
1766
1751
|
`);this.outputLines.length>0&&newLines.length>0?(this.outputLines[this.outputLines.length-1]+=newLines[0],this.outputLines.push(...newLines.slice(1))):this.outputLines.push(...newLines),this.updateDisplay()}setComplete(exitCode,cancelled,truncationResult,fullOutputPath){this.exitCode=exitCode,this.status=cancelled?"cancelled":exitCode!==0&&exitCode!==void 0&&exitCode!==null?"error":"complete",this.truncationResult=truncationResult,this.fullOutputPath=fullOutputPath,this.loader.stop(),this.updateDisplay()}updateDisplay(){let fullOutput=this.outputLines.join(`
|
|
@@ -1776,31 +1761,20 @@ ${statusParts.join(`
|
|
|
1776
1761
|
|
|
1777
1762
|
`;content.addChild(new Markdown(header2+this.message.summary,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else content.addChild(new Text(theme.fg("customMessageText","Branch summary (")+theme.fg("dim",keyText("app.tools.expand"))+theme.fg("customMessageText"," to expand)"),0,0));this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var CompactionSummaryMessageComponent=class extends Box{constructor(message,markdownTheme=getMarkdownTheme(),outputPad=1){super(outputPad,1,t=>theme.bg("customMessageBg",t)),this.expanded=!1,this.message=message,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.setPaddingX(outputPad)}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let content=new Container,tokenStr=this.message.tokensBefore.toLocaleString(),label=theme.fg("customMessageLabel","\x1B[1m[compaction]\x1B[22m");if(content.addChild(new Text(label,0,0)),content.addChild(new Spacer(1)),this.expanded){let header2=`**Compacted from ${tokenStr} tokens**
|
|
1778
1763
|
|
|
1779
|
-
`;content.addChild(new Markdown(header2+this.message.summary,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else content.addChild(new Text(theme.fg("customMessageText",`Compacted from ${tokenStr} tokens (`)+theme.fg("dim",keyText("app.tools.expand"))+theme.fg("customMessageText"," to expand)"),0,0));this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var CustomEditor=class extends Editor{constructor(tui,theme2,keybindings,options){super(tui,theme2,options),this.actionHandlers=new Map,this.keybindings=keybindings,this.embedWorkingStatus=options?.embedWorkingStatus??!1}setWorkingStatusIndicator(indicator){this.workingStatusIndicator=indicator}renderTopBorder(width,hiddenLineCount){if(!this.embedWorkingStatus||!this.workingStatusIndicator||width<=0)return super.renderTopBorder(width,hiddenLineCount);let status=this.workingStatusIndicator.renderInBorder(Math.max(1,width-5)),statusWidth=visibleWidth(status);if(statusWidth===0)return super.renderTopBorder(width,hiddenLineCount);let overflowLabel=hiddenLineCount>0?` \u2191 ${hiddenLineCount} more `:void 0,overflowLabelWidth=overflowLabel?visibleWidth(overflowLabel):0,overflowStart=Math.floor((width-overflowLabelWidth)/2),canFitOverflow=()=>overflowLabel!==void 0&&overflowLabelWidth+2<=width&&overflowStart-(3+statusWidth+1)>=1;if(overflowLabel&&!canFitOverflow()&&(status=this.workingStatusIndicator.renderSpinnerInBorder(width),statusWidth=visibleWidth(status)),canFitOverflow()){let leftBlockWidth=3+statusWidth+1;return this.borderColor("\u2500\u2500 ")+status+this.borderColor(` ${"\u2500".repeat(overflowStart-leftBlockWidth)}${overflowLabel}${"\u2500".repeat(width-overflowStart-overflowLabelWidth)}`)}if(width>=statusWidth+5)return this.borderColor("\u2500\u2500 ")+status+this.borderColor(` ${"\u2500".repeat(width-statusWidth-4)}`);status=this.workingStatusIndicator.renderSpinnerInBorder(width),statusWidth=visibleWidth(status);let prefixWidth=Math.min(3,Math.max(0,width-statusWidth));return this.borderColor("\u2500".repeat(prefixWidth))+status+this.borderColor("\u2500".repeat(Math.max(0,width-prefixWidth-statusWidth)))}onAction(action,handler){this.actionHandlers.set(action,handler)}handleInput(data){if(!this.onExtensionShortcut?.(data)){if(this.keybindings.matches(data,"app.clipboard.pasteImage")){this.onPasteImage?.();return}if(this.keybindings.matches(data,"app.interrupt")){if(!this.isShowingAutocomplete()){let handler=this.onEscape??this.actionHandlers.get("app.interrupt");if(handler){handler();return}}super.handleInput(data);return}if(this.keybindings.matches(data,"app.exit")&&this.getText().length===0){let handler=this.onCtrlD??this.actionHandlers.get("app.exit");handler&&handler();return}if(this.keybindings.matches(data,"tui.editor.historyPrevious")||this.keybindings.matches(data,"tui.editor.historyNext")){super.handleInput(data);return}for(let[action,handler]of this.actionHandlers)if(action!=="app.interrupt"&&action!=="app.exit"&&this.keybindings.matches(data,action)){handler();return}super.handleInput(data)}}};
|
|
1780
|
-
`)}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?`
|
|
1781
|
-
`:""}${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=readTaskCompletion(message.details);if(!snapshot){let{text:text2,clipped}=savedText(message);return{body:text2,truncated:clipped}}return{title:clean(snapshot.title),duration:runtimeLabel(snapshot),kind:snapshot.kind,status:snapshot.status,id:clean(snapshot.taskId),exitCode:snapshot.exitCode,command:snapshot.command===void 0?void 0:clean(snapshot.command.text),cwd:snapshot.cwd===void 0?void 0:clean(snapshot.cwd),path:snapshot.outputPath===void 0?void 0:clean(snapshot.outputPath),diagnostic:snapshot.error===void 0?void 0:clean(snapshot.error),output:clean(snapshot.output.text),body:"",truncated:snapshot.output.truncated||snapshot.command?.truncated===!0}}function color(status){return status===void 0?"muted":statusMarker(status).color}function shortId(id){return id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,"$1-$2")}var CompletionCard=class{constructor(view,options,theme2){this.view=view,this.options=options,this.theme=theme2}invalidate(){}render(width){return width<1?[]:new FramedComponent({render:contentWidth=>this.renderContent(contentWidth),invalidate(){}},"header",()=>color(this.view.status)).render(width).map(line=>truncateToWidth(line,width,""))}renderContent(width){if(!Number.isFinite(width)||width<1)return[];let view=this.view,theme2=this.theme,options=this.options,padding=Math.min(Math.max(0,Math.floor(options.outputPad||0)-1),Math.floor((width-1)/2)),inner=width-padding*2,indent=inner>=3?" ":"",bodyWidth=Math.max(1,inner-indent.length),lines=[],status=view.status?statusName(view.status):"Result received",kind=view.kind===void 0?"Notification":SHELL_NAMES[view.kind]??view.kind;lines.push(`${theme2.fg("toolTitle",theme2.bold(kind))}${theme2.fg("muted",` \xB7 Background ${status.toLowerCase()}${view.duration?` \xB7 ${view.duration}`:""}`)}${view.id?theme2.fg("dim",` \xB7 ${shortId(view.id)}`):""}`);let summary=view.command?`$ ${view.command.split(`
|
|
1782
|
-
`)[0]}`:view.title;if(!options.expanded)summary&&lines.push(theme2.fg("toolOutput",summary)),view.diagnostic&&lines.push(theme2.fg(color(view.status),view.diagnostic));else{view.truncated&&lines.push(theme2.fg("warning","The saved result is truncated; this is not the complete original output."));let section=(title,text2,limit,tail2=!1,error=!1)=>{lines.push("",theme2.fg("muted",theme2.bold(title)));let rendered=wrapTextWithAnsi(text2,bodyWidth).map(line=>theme2.fg(error?"error":"toolOutput",line)),omitted=Math.max(0,rendered.length-limit),selected=tail2?rendered.slice(-limit):rendered.slice(0,limit);tail2&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} earlier display lines omitted`));for(let line of selected)lines.push(indent+line);!tail2&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} more display lines omitted`))};view.output===void 0?section("Details",view.body||"No text result.",36):(view.command?section("Command",view.command,8):view.title&§ion("Task",view.title,4),view.cwd&§ion("Directory",view.cwd,2),section(view.status==="failed"||view.status==="timeout"?"Error":"Result",`${view.diagnostic??status}${view.exitCode!==void 0?` \xB7 ${view.exitCode===null?"terminated by signal":`exit ${view.exitCode}`}`:""}`,4,!1,view.status==="failed"),section("Output",view.output.trim()?view.output:"No output.",OUTPUT_ROWS,!0),view.path&§ion("Log",view.path,4)),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."))}return(lines.length>CARD_ROWS?[...lines.slice(0,CARD_ROWS-1),theme2.fg("dim","\u2026 card shortened; use tasks read for retained output")]:lines).map(line=>" ".repeat(padding)+truncateToWidth(line,inner,"\u2026")+" ".repeat(padding))}};function renderTaskCompletion(message,options,theme2){let view;try{view=completionView(message)}catch{view={body:"The saved notification could not be interpreted. Its original message remains in session history.",truncated:!1}}return new CompletionCard(view,options,theme2)}function isPlainPrimaryClick(event){return event.type==="click"&&event.button==="left"&&!event.shift&&!event.alt&&!event.ctrl&&(event.clickCount??1)===1}var CustomMessageComponent=class extends Container{constructor(message,customRenderer,markdownTheme=getMarkdownTheme(),outputPad=1){super(),this._expanded=!1,this.message=message,this.customRenderer=customRenderer??(message.customType==="task-completion"?renderTaskCompletion:void 0),this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.addChild(new Spacer(1)),this.box=new Box(1,1,t=>theme.bg("customMessageBg",t)),this.rebuild()}setExpanded(expanded){this._expanded!==expanded&&(this._expanded=expanded,this.rebuild())}setOutputPad(outputPad){this.outputPad!==outputPad&&(this.outputPad=outputPad,this.rebuild())}invalidate(){super.invalidate(),this.rebuild()}rebuild(){if(this.customComponent&&(this.removeChild(this.customComponent),this.customComponent=void 0),this.removeChild(this.box),this.customRenderer)try{let component=this.customRenderer(this.message,{expanded:this._expanded,outputPad:this.outputPad},theme);if(component){this.customComponent=new MouseRegion(component,event=>{if(isPlainPrimaryClick(event))return this.setExpanded(!this._expanded),{handled:!0}}),this.addChild(this.customComponent);return}}catch{}this.addChild(this.box),this.box.clear(),this.box.setPaddingX(this.outputPad);let label=theme.fg("customMessageLabel",`\x1B[1m[${this.message.customType}]\x1B[22m`);this.box.addChild(new Text(label,0,0)),this.box.addChild(new Spacer(1));let text2;typeof this.message.content=="string"?text2=this.message.content:text2=this.message.content.filter(c=>c.type==="text").map(c=>c.text).join(`
|
|
1764
|
+
`;content.addChild(new Markdown(header2+this.message.summary,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else content.addChild(new Text(theme.fg("customMessageText",`Compacted from ${tokenStr} tokens (`)+theme.fg("dim",keyText("app.tools.expand"))+theme.fg("customMessageText"," to expand)"),0,0));this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var CustomEditor=class extends Editor{constructor(tui,theme2,keybindings,options){super(tui,theme2,options),this.actionHandlers=new Map,this.keybindings=keybindings,this.embedWorkingStatus=options?.embedWorkingStatus??!1}setWorkingStatusIndicator(indicator){this.workingStatusIndicator=indicator}renderTopBorder(width,hiddenLineCount){if(!this.embedWorkingStatus||!this.workingStatusIndicator||width<=0)return super.renderTopBorder(width,hiddenLineCount);let status=this.workingStatusIndicator.renderInBorder(Math.max(1,width-5)),statusWidth=visibleWidth(status);if(statusWidth===0)return super.renderTopBorder(width,hiddenLineCount);let overflowLabel=hiddenLineCount>0?` \u2191 ${hiddenLineCount} more `:void 0,overflowLabelWidth=overflowLabel?visibleWidth(overflowLabel):0,overflowStart=Math.floor((width-overflowLabelWidth)/2),canFitOverflow=()=>overflowLabel!==void 0&&overflowLabelWidth+2<=width&&overflowStart-(3+statusWidth+1)>=1;if(overflowLabel&&!canFitOverflow()&&(status=this.workingStatusIndicator.renderSpinnerInBorder(width),statusWidth=visibleWidth(status)),canFitOverflow()){let leftBlockWidth=3+statusWidth+1;return this.borderColor("\u2500\u2500 ")+status+this.borderColor(` ${"\u2500".repeat(overflowStart-leftBlockWidth)}${overflowLabel}${"\u2500".repeat(width-overflowStart-overflowLabelWidth)}`)}if(width>=statusWidth+5)return this.borderColor("\u2500\u2500 ")+status+this.borderColor(` ${"\u2500".repeat(width-statusWidth-4)}`);status=this.workingStatusIndicator.renderSpinnerInBorder(width),statusWidth=visibleWidth(status);let prefixWidth=Math.min(3,Math.max(0,width-statusWidth));return this.borderColor("\u2500".repeat(prefixWidth))+status+this.borderColor("\u2500".repeat(Math.max(0,width-prefixWidth-statusWidth)))}onAction(action,handler){this.actionHandlers.set(action,handler)}handleInput(data){if(!this.onExtensionShortcut?.(data)){if(this.keybindings.matches(data,"app.clipboard.pasteImage")){this.onPasteImage?.();return}if(this.keybindings.matches(data,"app.interrupt")){if(!this.isShowingAutocomplete()){let handler=this.onEscape??this.actionHandlers.get("app.interrupt");if(handler){handler();return}}super.handleInput(data);return}if(this.keybindings.matches(data,"app.exit")&&this.getText().length===0){let handler=this.onCtrlD??this.actionHandlers.get("app.exit");handler&&handler();return}if(this.keybindings.matches(data,"tui.editor.historyPrevious")||this.keybindings.matches(data,"tui.editor.historyNext")){super.handleInput(data);return}for(let[action,handler]of this.actionHandlers)if(action!=="app.interrupt"&&action!=="app.exit"&&this.keybindings.matches(data,action)){handler();return}super.handleInput(data)}}};function isPlainPrimaryClick(event){return event.type==="click"&&event.button==="left"&&!event.shift&&!event.alt&&!event.ctrl&&(event.clickCount??1)===1}var CustomMessageComponent=class extends Container{constructor(message,customRenderer,markdownTheme=getMarkdownTheme(),outputPad=1){super(),this._expanded=!1,this.message=message,this.customRenderer=customRenderer,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.addChild(new Spacer(1)),this.box=new Box(1,1,t=>theme.bg("customMessageBg",t)),this.rebuild()}setExpanded(expanded){this._expanded!==expanded&&(this._expanded=expanded,this.rebuild())}setOutputPad(outputPad){this.outputPad!==outputPad&&(this.outputPad=outputPad,this.rebuild())}invalidate(){super.invalidate(),this.rebuild()}rebuild(){if(this.customComponent&&(this.removeChild(this.customComponent),this.customComponent=void 0),this.removeChild(this.box),this.customRenderer)try{let component=this.customRenderer(this.message,{expanded:this._expanded,outputPad:this.outputPad},theme);if(component){this.customComponent=new MouseRegion(component,event=>{if(isPlainPrimaryClick(event))return this.setExpanded(!this._expanded),{handled:!0}}),this.addChild(this.customComponent);return}}catch{}this.addChild(this.box),this.box.clear(),this.box.setPaddingX(this.outputPad);let label=theme.fg("customMessageLabel",`\x1B[1m[${this.message.customType}]\x1B[22m`);this.box.addChild(new Text(label,0,0)),this.box.addChild(new Spacer(1));let text2;typeof this.message.content=="string"?text2=this.message.content:text2=this.message.content.filter(c=>c.type==="text").map(c=>c.text).join(`
|
|
1783
1765
|
`),this.box.addChild(new Markdown(text2,0,0,this.markdownTheme,{color:text3=>theme.fg("customMessageText",text3)}))}};import{isAbsolute as isAbsolute5,relative as relative7,resolve as resolve13,sep as sep10}from"node:path";function areExperimentalFeaturesEnabled(){return process.env.PI_EXPERIMENTAL==="1"}function sanitizeStatusText(text2){return text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()}function formatTokens(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function formatCwdForFooter(cwd,home){if(!home)return cwd;let resolvedCwd=resolve13(cwd),resolvedHome=resolve13(home),relativeToHome=relative7(resolvedHome,resolvedCwd);return relativeToHome===""||relativeToHome!==".."&&!relativeToHome.startsWith(`..${sep10}`)&&!isAbsolute5(relativeToHome)?relativeToHome===""?"~":`~${sep10}${relativeToHome}`:cwd}var FooterComponent=class{constructor(session,footerData){this.autoCompactEnabled=!0,this.session=session,this.footerData=footerData}setSession(session){this.session=session}setAutoCompactEnabled(enabled){this.autoCompactEnabled=enabled}invalidate(){}dispose(){}getSessionStats(){let sessionManager=this.session.sessionManager,entryCount=sessionManager.getEntryCount(),sessionId=sessionManager.getSessionId(),leafId=sessionManager.getLeafId(),limitsModel=this.session.routedModel?.model??this.session.model,cached=this.sessionStats;if(cached&&cached.session===this.session&&cached.sessionId===sessionId&&cached.leafId===leafId&&cached.entryCount===entryCount&&cached.limitsModel===limitsModel)return cached;let usageTotals=createUsageTotals(),latestCacheHitRate,entries=this.session.sessionManager.getEntries();for(let usage of getAccountedUsages(entries))addUsageToTotals(usageTotals,usage);for(let entry of entries)if(entry.type==="message"&&entry.message.role==="assistant"){let latestPromptTokens=entry.message.usage.input+entry.message.usage.cacheRead+entry.message.usage.cacheWrite;latestCacheHitRate=latestPromptTokens>0?entry.message.usage.cacheRead/latestPromptTokens*100:void 0}let contextUsage=this.session.getContextUsage();return this.sessionStats={session:this.session,sessionId,leafId,entryCount,limitsModel,usageTotals,latestCacheHitRate,contextUsage},this.sessionStats}render(width){let state2=this.session.state,{usageTotals,latestCacheHitRate,contextUsage}=this.getSessionStats(),contextWindow=contextUsage?.contextWindow??state2.model?.contextWindow??0,contextPercentValue=contextUsage?.percent??0,contextPercent=contextUsage?.percent!==null?contextPercentValue.toFixed(1):"?",pwd=formatCwdForFooter(this.session.sessionManager.getCwd(),process.env.HOME||process.env.USERPROFILE),branch=this.footerData.getGitBranch();branch&&(pwd=`${pwd} (${branch})`);let sessionName=this.session.sessionManager.getSessionName();sessionName&&(pwd=`${pwd} \u2022 ${sessionName}`);let statsParts=[];usageTotals.input&&statsParts.push(`\u2191${formatTokens(usageTotals.input)}`),usageTotals.output&&statsParts.push(`\u2193${formatTokens(usageTotals.output)}`),usageTotals.cacheRead&&statsParts.push(`R${formatTokens(usageTotals.cacheRead)}`),usageTotals.cacheWrite&&statsParts.push(`W${formatTokens(usageTotals.cacheWrite)}`),(usageTotals.cacheRead>0||usageTotals.cacheWrite>0)&&latestCacheHitRate!==void 0&&statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);let usingSubscription=state2.model?state2.model.provider==="kimi-coding"||this.session.modelRuntime.isUsingSubscription(state2.model.provider):!1;if(usageTotals.cost||usingSubscription){let costStr=`$${usageTotals.cost.toFixed(3)}${usingSubscription?" (sub)":""}`;statsParts.push(costStr)}let contextPercentStr,autoIndicator=this.autoCompactEnabled?" (auto)":"",contextPercentDisplay=contextPercent==="?"?`?/${formatTokens(contextWindow)}${autoIndicator}`:`${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;contextPercentValue>90?contextPercentStr=theme.fg("error",contextPercentDisplay):contextPercentValue>70?contextPercentStr=theme.fg("warning",contextPercentDisplay):contextPercentStr=contextPercentDisplay,statsParts.push(contextPercentStr),areExperimentalFeaturesEnabled()&&statsParts.push(`${theme.fg("dim","\u2022")} ${theme.bold(theme.fg("warning","xp"))}`);let statsLeft=statsParts.join(" "),modelName=state2.model?.id||"no-model",statsLeftWidth=visibleWidth(statsLeft);statsLeftWidth>width&&(statsLeft=truncateToWidth(statsLeft,width,"..."),statsLeftWidth=visibleWidth(statsLeft));let minPadding=2,rightSideWithoutProvider=modelName;if(state2.model?.reasoning){let thinkingLevel=state2.thinkingLevel||"off";rightSideWithoutProvider=thinkingLevel==="off"?`${modelName} \u2022 thinking off`:`${modelName} \u2022 ${thinkingLevel}`}let routed=this.session.routedModel;if(routed){let level=routed.thinkingLevel?` \u2022 ${routed.thinkingLevel}`:"";rightSideWithoutProvider+=` \u2192 ${routed.model.id}${level}`}let rightSide=rightSideWithoutProvider;this.footerData.getAvailableProviderCount()>1&&state2.model&&(rightSide=`(${state2.model.provider}) ${rightSideWithoutProvider}`,statsLeftWidth+minPadding+visibleWidth(rightSide)>width&&(rightSide=rightSideWithoutProvider));let rightSideWidth=visibleWidth(rightSide),totalNeeded=statsLeftWidth+minPadding+rightSideWidth,statsLine;if(totalNeeded<=width){let padding=" ".repeat(width-statsLeftWidth-rightSideWidth);statsLine=statsLeft+padding+rightSide}else{let availableForRight=width-statsLeftWidth-minPadding;if(availableForRight>0){let truncatedRight=truncateToWidth(rightSide,availableForRight,""),truncatedRightWidth=visibleWidth(truncatedRight),padding=" ".repeat(Math.max(0,width-statsLeftWidth-truncatedRightWidth));statsLine=statsLeft+padding+truncatedRight}else statsLine=statsLeft}let dimStatsLeft=theme.fg("dim",statsLeft),remainder=statsLine.slice(statsLeft.length),dimRemainder=theme.fg("dim",remainder),lines=[truncateToWidth(theme.fg("dim",pwd),width,theme.fg("dim","...")),dimStatsLeft+dimRemainder],extensionStatuses=this.footerData.getExtensionStatuses();if(extensionStatuses.size>0){let statusLine=Array.from(extensionStatuses.entries()).sort(([a],[b2])=>a.localeCompare(b2)).map(([,text2])=>sanitizeStatusText(text2)).join(" ");lines.push(truncateToWidth(statusLine,width,theme.fg("dim","...")))}return lines}};var LoginDialogComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(tui,providerId,onComplete,providerNameOverride,titleOverride){super(),this.abortController=new AbortController,this._focused=!1,this.tui=tui,this.onComplete=onComplete;let title=titleOverride??`Login to ${providerNameOverride||providerId}`;this.addChild(new DynamicBorder),this.addChild(new Text(theme.fg("accent",theme.bold(title)),1,0)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.input=new Input,this.input.onSubmit=()=>{if(this.inputResolver){let value=this.input.getValue();this.replaceInputWithSubmittedText(value),this.inputResolver(value),this.inputResolver=void 0,this.inputRejecter=void 0}},this.input.onEscape=()=>{this.cancel()},this.addChild(new DynamicBorder)}get signal(){return this.abortController.signal}replaceInputWithSubmittedText(value){this.contentContainer.children=this.contentContainer.children.map(child=>child===this.input?new Text(`> ${value}`,0,0):child)}cancel(){this.abortController.abort(),this.inputRejecter&&(this.inputRejecter(new Error("Login cancelled")),this.inputResolver=void 0,this.inputRejecter=void 0),this.onComplete(!1,"Login cancelled")}showAuth(url,instructions){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1)),this.authUrl=new AuthUrlComponent(this.tui,url),this.contentContainer.addChild(this.authUrl),instructions&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",instructions),1,0))),openBrowser(url),this.tui.requestRender()}showDeviceCode(info){this.authUrl=void 0,this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${info.verificationUri}\x07${info.verificationUri}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?"Cmd+click to open":"Ctrl+click to open",hyperlink2=`\x1B]8;;${info.verificationUri}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",`Enter code: ${info.userCode}`),1,0)),this.tui.requestRender()}showManualInput(prompt){return this.input.setValue(""),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",prompt),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender(),new Promise((resolve20,reject)=>{this.inputResolver=resolve20,this.inputRejecter=reject})}showPrompt(message,placeholder){return this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0)),placeholder&&this.contentContainer.addChild(new Text(theme.fg("dim",`e.g., ${placeholder}`),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel,")} ${keyHint("tui.select.confirm","to submit")})`,1,0)),this.input.setValue(""),this.tui.requestRender(),new Promise((resolve20,reject)=>{this.inputResolver=resolve20,this.inputRejecter=reject})}showDetails(lines){this.authUrl=void 0,this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));for(let line of lines)this.contentContainer.addChild(new Text(line,1,0));this.tui.requestRender()}showInfo(message,links=[],showCloseHint=!1){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0));for(let link of links){let text2=link.label?`${link.label}: ${link.url}`:link.url,hyperlink2=`\x1B]8;;${link.url}\x07${text2}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",hyperlink2),1,0))}showCloseHint&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to close")})`,1,0))),this.tui.requestRender()}showWaiting(message){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel","to cancel")})`,1,0)),this.tui.requestRender()}showProgress(message){this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.tui.requestRender()}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.authUrl&&kb.matches(data,"app.message.copy")){this.authUrl.copy();return}this.input.handleInput(data)}};var ModelCatalogRefreshCoordinator=class{constructor(){this.activeByRuntime=new WeakMap}refresh(modelRuntime,signal){signal.throwIfAborted();let active=this.activeByRuntime.get(modelRuntime);if(!active){let controller=new AbortController,created,operation=modelRuntime.refresh({signal:controller.signal}),promise=raceWithAbortSignal(operation,controller.signal).finally(()=>{this.activeByRuntime.get(modelRuntime)===created&&this.activeByRuntime.delete(modelRuntime)});created={controller,promise,waiters:0},active=created,this.activeByRuntime.set(modelRuntime,active)}return active.waiters++,raceWithAbortSignal(active.promise,signal).finally(()=>{active.waiters--,active.waiters===0&&this.activeByRuntime.get(modelRuntime)===active&&active.controller.abort()})}},modelCatalogRefreshCoordinator=new ModelCatalogRefreshCoordinator;function refreshModelCatalogs(modelRuntime,signal){return modelCatalogRefreshCoordinator.refresh(modelRuntime,signal)}function getModelSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${id} ${provider} ${provider}/${id} ${provider} ${id}${name}`}function getModelSelectorSearchText(item){let{id,provider}=item,name=item.name?` ${item.name}`:"";return`${provider} ${provider}/${id} ${provider} ${id}${name}`}var ModelSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(tui,currentModel,modelRuntime,scopedModels,onSelect,onCancel,initialSearchInput,onSelectAsDefault,defaultModel){if(super(),this._focused=!1,this.allModels=[],this.scopedModelItems=[],this.activeModels=[],this.filteredModels=[],this.selectedIndex=0,this.refreshStatusMessage="Refreshing model catalogs\u2026",this.refreshStatusSuccess=!1,this.scope="all",this.refreshAbortController=new AbortController,this.closed=!1,this.tui=tui,this.currentModel=currentModel,this.modelRuntime=modelRuntime,this.scopedModels=scopedModels,this.defaultModel=defaultModel,this.scope=scopedModels.length>0?"scoped":"all",this.onSelectCallback=onSelect,this.onSelectAsDefaultCallback=onSelectAsDefault,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),scopedModels.length>0)this.scopeText=new Text(this.getScopeText(),0,0),this.addChild(this.scopeText),this.scopeHintText=new Text(this.getScopeHintText(),0,0),this.addChild(this.scopeHintText);else{let hintText="Only showing models from configured providers. Use /login to add providers.";this.addChild(new Text(theme.fg("warning",hintText),0,0))}this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{this.filteredModels[this.selectedIndex]&&this.handleSelect(this.filteredModels[this.selectedIndex].model)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.onSelectAsDefaultCallback&&this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.models.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder),this.loadModelsFromSnapshot(),initialSearchInput?this.filterModels(initialSearchInput):this.updateList(),this.tui.requestRender(),this.refreshModels()}loadModelsFromSnapshot(){let models=this.modelRuntime.getAvailableSnapshot().map(model=>({provider:model.provider,id:model.id,model}));this.allModels=this.sortModels(models),this.scopedModels=this.scopedModels.map(scoped=>{let refreshed=this.modelRuntime.getModel(scoped.model.provider,scoped.model.id);return refreshed?{...scoped,model:refreshed}:scoped}),this.scopedModelItems=this.scopedModels.map(scoped=>({provider:scoped.model.provider,id:scoped.model.id,model:scoped.model})),this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels,this.filteredModels=this.activeModels;let currentIndex=this.filteredModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1))}async refreshModels(){let timedOut=!1;this.refreshTimeout=setTimeout(()=>{timedOut=!0,this.refreshAbortController.abort()},15e3);try{let result2=await refreshModelCatalogs(this.modelRuntime,this.refreshAbortController.signal);if(this.closed)return;this.refreshStatusMessage="",result2.aborted&&timedOut?this.errorMessage="Model refresh timed out; showing cached models.":result2.errors.size===1?this.errorMessage=`Could not refresh ${result2.errors.keys().next().value}; showing cached models.`:result2.errors.size>1?this.errorMessage=`Could not refresh ${result2.errors.size} model catalogs (${[...result2.errors.keys()].join(", ")}); showing cached models.`:(this.errorMessage=this.modelRuntime.getError(),this.errorMessage||(this.refreshStatusMessage="Model catalogs refreshed.",this.refreshStatusSuccess=!0)),this.loadModelsFromSnapshot(),this.filterModels(this.searchInput.getValue()),this.tui.requestRender()}catch(error){if(this.closed)return;this.refreshStatusMessage="",this.errorMessage=timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,this.updateList(),this.tui.requestRender()}finally{this.refreshTimeout&&clearTimeout(this.refreshTimeout)}}dispose(){this.closed||(this.closed=!0,this.refreshTimeout&&clearTimeout(this.refreshTimeout),this.refreshAbortController.abort())}sortModels(models){let sorted=[...models];return sorted.sort((a,b2)=>{let aIsCurrent=modelsAreEqual(this.currentModel,a.model),bIsCurrent=modelsAreEqual(this.currentModel,b2.model);if(aIsCurrent&&!bIsCurrent)return-1;if(!aIsCurrent&&bIsCurrent)return 1;let aIsDefault=this.isDefaultModel(a.model),bIsDefault=this.isDefaultModel(b2.model);return aIsDefault&&!bIsDefault?-1:!aIsDefault&&bIsDefault?1:a.provider.localeCompare(b2.provider)}),sorted}getScopeText(){let allText=this.scope==="all"?theme.fg("accent","all"):theme.fg("muted","all"),scopedText=this.scope==="scoped"?theme.fg("accent","scoped"):theme.fg("muted","scoped");return`${theme.fg("muted","Scope: ")}${allText}${theme.fg("muted"," | ")}${scopedText}`}getScopeHintText(){return keyHint("tui.input.tab","scope")+theme.fg("muted"," (all/scoped)")}isDefaultModel(model){return this.defaultModel?.provider===model.provider&&this.defaultModel.id===model.id}isDefaultSearch(query){let normalized=query.trim().toLowerCase();return normalized.length>0&&"default".startsWith(normalized)}setScope(scope){if(this.scope===scope)return;this.scope=scope,this.activeModels=this.scope==="scoped"?this.scopedModelItems:this.allModels;let currentIndex=this.activeModels.findIndex(item=>modelsAreEqual(this.currentModel,item.model));this.selectedIndex=currentIndex>=0?currentIndex:0,this.filterModels(this.searchInput.getValue()),this.scopeText&&this.scopeText.setText(this.getScopeText())}filterModels(query){if(query){let filtered=fuzzyFilter(this.activeModels,query,item=>{let defaultText=this.isDefaultModel(item.model)?" default":"";return`${getModelSelectorSearchText({id:item.id,provider:item.provider,name:item.model.name})}${defaultText}`});if(this.isDefaultSearch(query)){let defaultItems=this.activeModels.filter(item=>this.isDefaultModel(item.model)),defaultKeys=new Set(defaultItems.map(item=>`${item.provider}\0${item.id}`));this.filteredModels=[...defaultItems,...filtered.filter(item=>!defaultKeys.has(`${item.provider}\0${item.id}`))]}else this.filteredModels=filtered}else this.filteredModels=this.activeModels;this.selectedIndex=query?0:Math.min(this.selectedIndex,Math.max(0,this.filteredModels.length-1)),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=10,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredModels.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredModels.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredModels[i];if(!item)continue;let isSelected2=i===this.selectedIndex,isCurrent=modelsAreEqual(this.currentModel,item.model),defaultBadge=this.isDefaultModel(item.model)?theme.fg("muted"," \xB7 default"):"",cursor=isSelected2?theme.fg("accent","\u2192 "):" ",currentMarker=isCurrent?theme.fg("accent","\u2713 "):" ",modelText2=isSelected2?theme.fg("accent",item.id):item.id,providerBadge=theme.fg("muted",`[${item.provider}]`),line=`${cursor}${currentMarker}${modelText2} ${providerBadge}${defaultBadge}`;this.listContainer.addChild(new Text(line,0,0))}if(startIndex>0||endIndex<this.filteredModels.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredModels.length})`);this.listContainer.addChild(new Text(scrollInfo,0,0))}if(this.errorMessage){let errorLines=this.errorMessage.split(`
|
|
1784
1766
|
`);for(let line of errorLines)this.listContainer.addChild(new Text(theme.fg("error",line),0,0))}else if(this.filteredModels.length===0)this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));else{let selected=this.filteredModels[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` Model Name: ${selected.model.name}`),0,0))}this.refreshStatusMessage&&(this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg(this.refreshStatusSuccess?"success":"muted",` ${this.refreshStatusMessage}`),0,0)))}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.input.tab")){if(this.scopedModelItems.length>0){let nextScope=this.scope==="all"?"scoped":"all";this.setScope(nextScope),this.scopeHintText&&this.scopeHintText.setText(this.getScopeHintText())}return}if(kb.matches(keyData,"tui.select.up")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredModels.length-1:this.selectedIndex-1,this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredModels.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredModels.length-1?0:this.selectedIndex+1,this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&this.handleSelect(selectedModel.model)}else if(kb.matches(keyData,"tui.select.cancel"))this.dispose(),this.onCancelCallback();else if(kb.matches(keyData,"app.models.save")&&this.onSelectAsDefaultCallback){let selectedModel=this.filteredModels[this.selectedIndex];selectedModel&&(this.dispose(),this.onSelectAsDefaultCallback(selectedModel.model))}else this.searchInput.handleInput(keyData),this.filterModels(this.searchInput.getValue())}handleSelect(model){this.dispose(),this.onSelectCallback(model)}getSearchInput(){return this.searchInput}};function formatAuthSelectorProviderType(authType,subscription){return authType==="api_key"?"API key":subscription===!1?"account":"subscription"}function formatAuthSelectorProviderStatus(provider){if(!provider.status)return theme.fg("muted"," \u2022 not configured");if(provider.status.type!==provider.authType){let label=`${formatAuthSelectorProviderType(provider.status.type,provider.subscription)} configured`;return theme.fg("muted"," \u2022 ")+theme.fg("warning",label)}if(!provider.status.source||provider.status.source==="OAuth"||provider.status.source==="stored credential")return theme.fg("success"," \u2713 configured");let source=/^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)?`env: ${provider.status.source}`:provider.status.source;return theme.fg("success",` \u2713 ${source}`)}var OAuthSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(mode,providers,onSelect,onCancel,initialSearchInput){super(),this._focused=!1,this.selectedIndex=0,this.mode=mode,this.allProviders=providers,this.filteredProviders=providers,this.showAuthTypeLabels=new Set(providers.map(provider=>provider.authType)).size>1,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1));let title=mode==="login"?"Select provider to configure:":"Select provider to logout:";this.addChild(new TruncatedText(theme.fg("accent",theme.bold(title)),1,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.filterProviders(initialSearchInput??"")}filterProviders(query){this.filteredProviders=query?fuzzyFilter(this.allProviders,query,provider=>`${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name??""}`):this.allProviders,this.selectedIndex=Math.max(0,Math.min(this.selectedIndex,Math.max(0,this.filteredProviders.length-1))),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=8,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredProviders.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredProviders.length);for(let i=startIndex;i<endIndex;i++){let provider=this.filteredProviders[i];if(!provider)continue;let isSelected2=i===this.selectedIndex,statusIndicator=formatAuthSelectorProviderStatus(provider),authTypeLabel=this.showAuthTypeLabels?theme.fg("muted",` [${formatAuthSelectorProviderType(provider.authType,provider.subscription)}]`):"",line="";if(isSelected2){let prefix=theme.fg("accent","\u2192 "),text2=theme.fg("accent",provider.name);line=prefix+text2+authTypeLabel+statusIndicator}else line=` ${theme.fg("text",provider.name)}`+authTypeLabel+statusIndicator;this.listContainer.addChild(new TruncatedText(line,1,0))}if(startIndex>0||endIndex<this.filteredProviders.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredProviders.length})`);this.listContainer.addChild(new TruncatedText(scrollInfo,1,0))}if(this.filteredProviders.length===0){let message=this.allProviders.length===0?this.mode==="login"?"No providers available":"No providers logged in. Use /login first.":"No matching providers";this.listContainer.addChild(new TruncatedText(theme.fg("muted",` ${message}`),1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.min(this.filteredProviders.length-1,this.selectedIndex+1),this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)}else kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():(this.searchInput.handleInput(keyData),this.filterProviders(this.searchInput.getValue()))}};var SUBMENU_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},SelectSubmenu=class extends Container{constructor(title,description,options,currentValue,onSelect,onCancel,onSelectionChange,submenuOptions){super(),this.allOptions=options,this.listLayout=submenuOptions?.layout??SUBMENU_SELECT_LIST_LAYOUT,this.onSelectCb=onSelect,this.onCancelCb=onCancel,this.onSelectionChangeCb=onSelectionChange,this.addChild(new Text(theme.bold(theme.fg("accent",title)),0,0)),description&&(this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",description),0,0))),submenuOptions?.searchable&&(this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>{this.selectList.handleInput("\r")},this.addChild(this.searchInput)),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(options,currentValue),this.listChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1));let hint=submenuOptions?.searchable?" Type to filter \xB7 Enter to select \xB7 Esc to go back":" Enter to select \xB7 Esc to go back";this.addChild(new Text(theme.fg("dim",hint),0,0))}buildSelectList(options,preselect){let list2=new SelectList(options,Math.min(options.length,10),getSelectListTheme(),this.listLayout),idx=options.findIndex(o=>o.value===preselect);if(idx!==-1&&list2.setSelectedIndex(idx),list2.onSelect=item=>this.onSelectCb(item.value),list2.onCancel=this.onCancelCb,this.onSelectionChangeCb){let cb=this.onSelectionChangeCb;list2.onSelectionChange=item=>cb(item.value)}return list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allOptions,query,item=>`${item.label} ${item.description??""}`):this.allOptions,newList=this.buildSelectList(filtered,"");this.children[this.listChildIndex]=newList,this.selectList=newList}handleInput(data){if(this.searchInput){let kb=getKeybindings();kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")?this.selectList.handleInput(data):(this.searchInput.handleInput(data),this.applyFilter(this.searchInput.getValue()))}else this.selectList.handleInput(data)}},SteppedSubmenu=class extends Container{constructor(steps,onComplete,onCancel,opts={}){super(),this.steps=steps,this.onComplete=onComplete,this.onCancel=onCancel,this.opts=opts,this.context={...opts.initialContext??{}},this.activeComponent=this.buildStep(opts.startAtStep??0)}buildStep(stepIndex){let step=this.steps[stepIndex],total=this.steps.length,stepLabel=total>1?`Step ${stepIndex+1}/${total} \xB7 `:"",title=typeof step.title=="function"?step.title(this.context):step.title,desc=typeof step.description=="function"?step.description(this.context):step.description,items=step.options(this.context),preselect=step.preselect?.(this.context)??"";return new SelectSubmenu(title,`${stepLabel}${desc}`,items,preselect,value=>{this.context[step.key]=value,stepIndex<total-1?this.activeComponent=this.buildStep(stepIndex+1):(this.onComplete({...this.context}),this.opts.loop?(this.context={},this.activeComponent=this.buildStep(0)):this.onCancel())},()=>{stepIndex>0?(delete this.context[step.key],this.activeComponent=this.buildStep(stepIndex-1)):this.onCancel()},void 0,step.searchable||step.layout?{searchable:step.searchable,layout:step.layout}:void 0)}render(width){return this.activeComponent.render(width)}handleInput(data){this.activeComponent.handleInput?.(data)}invalidate(){this.activeComponent.invalidate?.()}};var MODEL_PICKER_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:46},THINKING_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},DEFAULT_PROJECT_TRUST_LABELS={ask:"Ask",always:"Always trust",never:"Never trust"},DEFAULT_PROJECT_TRUST_BY_LABEL=new Map(Object.entries(DEFAULT_PROJECT_TRUST_LABELS).map(([value,label])=>[label,value])),WarningSettingsSubmenu=class extends Container{constructor(warnings,onChange,onCancel){super(),this.state={...warnings};let items=[{id:"anthropic-extra-usage",label:"Anthropic extra usage",description:"Warn when Anthropic subscription auth may use paid extra usage",currentValue:this.state.anthropicExtraUsage??SETTINGS_DEFAULTS.warnings.anthropicExtraUsage?"true":"false",values:["true","false"]}];this.settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),(id,newValue)=>{id==="anthropic-extra-usage"&&(this.state={...this.state,anthropicExtraUsage:newValue==="true"},onChange({...this.state}))},onCancel),this.addChild(this.settingsList)}handleInput(data){this.settingsList.handleInput(data)}},CLEAR_OVERRIDE_VALUE="__clear__";function modelSettingKey(model){return`${model.provider}/${model.id}`}function modelDisplayLabel(model){return`${model.id} [${model.provider}]`}function modelThinkingOverridesSummary(overrides){let count=Object.keys(overrides).length;return count===0?"none":`${count} configured`}function modelItemLabel(model){return`${model.id} ${theme.fg("muted",`[${model.provider}]`)}`}function themeItems(availableThemes,currentTheme){return availableThemes.map(name=>({value:name,label:`${name===currentTheme?"\u2713 ":" "}${name}`,...name===SYSTEM_THEME_NAME?{description:"Theme created from your terminal's colors"}:{}}))}var AUTOMATIC_THEME_VALUE="/";function singleModeThemeItems(availableThemes,currentTheme){let items=themeItems(availableThemes,currentTheme),systemIndex=items.findIndex(item=>item.value===SYSTEM_THEME_NAME);return[...systemIndex===-1?[]:items.splice(systemIndex,1),{value:AUTOMATIC_THEME_VALUE,label:" automatic",description:"Use separate themes for light and dark terminal appearance"},...items]}function preferredTheme(availableThemes,preferred,fallback){return preferred&&availableThemes.includes(preferred)?preferred:availableThemes.includes(fallback)?fallback:availableThemes[0]??fallback}function defaultAutomaticThemes(currentThemeSetting,availableThemes){let autoTheme=parseAutoThemeSetting(currentThemeSetting);if(autoTheme)return autoTheme;let currentFixedTheme=currentThemeSetting.includes("/")?void 0:currentThemeSetting,themeName=preferredTheme(availableThemes,currentFixedTheme,SYSTEM_THEME_NAME);return{lightTheme:themeName,darkTheme:themeName}}var ThemeSubmenu=class extends Container{constructor(currentThemeSetting,terminalTheme,availableThemes,callbacks,onDone){super(),this.callbacks=callbacks,this.availableThemes=availableThemes,this.terminalTheme=terminalTheme,this.onDone=onDone,this.originalThemeSetting=currentThemeSetting;let autoTheme=parseAutoThemeSetting(currentThemeSetting),automaticThemes=defaultAutomaticThemes(currentThemeSetting,availableThemes),fixedTheme=autoTheme||currentThemeSetting.includes("/")?void 0:currentThemeSetting;this.mode=autoTheme?"automatic":"single",this.lightTheme=automaticThemes.lightTheme,this.darkTheme=automaticThemes.darkTheme,this.singleTheme=preferredTheme(availableThemes,fixedTheme??(autoTheme?this.getActiveAutomaticTheme():void 0),SYSTEM_THEME_NAME),this.mode==="automatic"?this.showAutomaticMenu():this.showSingleMenu()}handleInput(data){this.inputComponent?.handleInput?.(data)}setContent(renderComponent,inputComponent=renderComponent){this.clear(),this.addChild(renderComponent),this.inputComponent=inputComponent}showSingleMenu(){this.mode="single";let menu=new SelectSubmenu("Theme","Select a theme, or choose automatic to follow terminal appearance.",singleModeThemeItems(this.availableThemes,this.singleTheme),this.singleTheme,value=>{if(value===AUTOMATIC_THEME_VALUE){this.mode="automatic",this.callbacks.onThemePreview?.(this.getThemeSetting()),this.showAutomaticMenu();return}this.singleTheme=value,this.apply(value)},()=>this.cancel(),value=>{this.callbacks.onThemePreview?.(value===AUTOMATIC_THEME_VALUE?this.getAutomaticThemeSetting():value)});this.setContent(menu)}showAutomaticMenu(){this.mode="automatic";let content=new Container;content.addChild(new Text(theme.bold(theme.fg("accent","Automatic Theme")),0,0)),content.addChild(new Spacer(1)),content.addChild(new Text(theme.fg("muted","Choose themes for terminal light and dark appearance."),0,0)),content.addChild(new Text(theme.fg("muted","Light/dark detection requires terminal support."),0,0)),content.addChild(new Spacer(1));let items=[{id:"light-theme",label:"Light theme",description:"Theme to use in automatic mode when the terminal is light",currentValue:this.lightTheme,submenu:(currentValue,done)=>this.createThemeSelect("Light Theme","Select the theme to use for light terminal appearance",currentValue,done,value=>{this.lightTheme=value,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value)})},{id:"dark-theme",label:"Dark theme",description:"Theme to use in automatic mode when the terminal is dark",currentValue:this.darkTheme,submenu:(currentValue,done)=>this.createThemeSelect("Dark Theme","Select the theme to use for dark terminal appearance",currentValue,done,value=>{this.darkTheme=value,this.callbacks.onThemePreview?.(this.getThemeSetting()),done(value)})},{id:"apply",label:"Apply",description:"Save and go back",currentValue:"save and go back",values:["save and go back"]},{id:"single-mode",label:"Change mode",description:"Switch to one theme for light and dark",currentValue:"switch to single theme",values:["switch to single theme"]}],settingsList=new SettingsList(items,Math.min(items.length,10),getSettingsListTheme(),id=>{switch(id){case"single-mode":this.mode="single",this.singleTheme=this.getActiveAutomaticTheme(),this.callbacks.onThemePreview?.(this.singleTheme),this.showSingleMenu();break;case"apply":this.apply(this.getAutomaticThemeSetting());break}},()=>this.cancel());content.addChild(settingsList),this.setContent(content,settingsList)}createThemeSelect(title,description,currentValue,done,onSelect){return new SelectSubmenu(title,description,themeItems(this.availableThemes,currentValue),currentValue,onSelect,()=>{this.callbacks.onThemePreview?.(this.getThemeSetting()),done()},value=>this.callbacks.onThemePreview?.(value))}getThemeSetting(){return this.mode==="automatic"?this.getAutomaticThemeSetting():this.singleTheme}getActiveAutomaticTheme(){return this.terminalTheme==="light"?this.lightTheme:this.darkTheme}getAutomaticThemeSetting(){return`${this.lightTheme}/${this.darkTheme}`}apply(themeSetting){this.onDone(themeSetting)}cancel(){this.callbacks.onThemePreview?.(this.originalThemeSetting),this.onDone()}},SettingsSelectorComponent=class extends Container{constructor(config,callbacks){super();let supportsImages=getCapabilities().images,followUpKey=keyDisplayText("app.message.followUp"),cycleThinkingKey=keyDisplayText("app.thinking.cycle"),currentWarnings={...config.warnings},currentModelThinkingLevels={...config.modelThinkingLevels},defaultModelByValue=new Map(config.availableDefaultModels.map(model=>[modelSettingKey(model),model])),currentDefaultModelKey=defaultModelByValue.has(config.defaultModel)?config.defaultModel:void 0,currentModelKey=config.currentModel?modelSettingKey(config.currentModel):void 0,items=[{id:"autocompact",label:"Auto-compact",description:"Automatically compact context when it gets too large",currentValue:config.autoCompact?"true":"false",values:["true","false"]},{id:"steering-mode",label:"Steering mode",description:"Enter while streaming queues steering messages. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.",currentValue:config.steeringMode,values:["one-at-a-time","all"]},{id:"follow-up-mode",label:"Follow-up mode",description:`${followUpKey} queues follow-up messages until agent stops. 'one-at-a-time': deliver one, wait for response. 'all': deliver all at once.`,currentValue:config.followUpMode,values:["one-at-a-time","all"]},{id:"transport",label:"Transport",description:"Preferred transport for providers that support multiple transports",currentValue:config.transport,values:["sse","websocket","websocket-cached","auto"]},{id:"share-destination",label:"Session share destination",description:"Where to upload sessions with /share (auto prefers Radius when authenticated, otherwise GitHub Gist)",currentValue:config.sessionShareDestination,values:["auto","gist","radius"]},{id:"http-idle-timeout",label:"HTTP idle timeout",description:"Maximum idle gap while waiting for HTTP headers or body chunks. Disable for local models that pause longer than five minutes.",currentValue:formatHttpIdleTimeoutMs(config.httpIdleTimeoutMs),values:HTTP_IDLE_TIMEOUT_CHOICES.map(choice=>choice.label)},{id:"cache-warming-mode",label:"Cache warming",description:"off; streaming while the agent runs; idle also between runs while continuation stays profitable",currentValue:config.cacheWarmingMode,values:[...CACHE_WARMING_MODES]},{id:"hide-thinking",label:"Hide thinking",description:"Hide thinking blocks in assistant responses",currentValue:config.hideThinkingBlock?"true":"false",values:["true","false"]},{id:"mermaid-rendering",label:"Mermaid diagrams",description:"Render Mermaid code blocks as Unicode diagrams",currentValue:config.mermaidRenderingMode,values:["off","final","streaming"]},{id:"cache-miss-notices",label:"Cache miss notices",description:"Show transcript notices for cache costs and provider recovery diagnostics",currentValue:config.showCacheMissNotices?"true":"false",values:["true","false"]},{id:"collapse-changelog",label:"Collapse changelog",description:"Show condensed changelog after updates",currentValue:config.collapseChangelog?"true":"false",values:["true","false"]},{id:"quiet-startup",label:"Quiet startup",description:"Disable verbose printing at startup (header: keep only the startup header)",currentValue:String(config.quietStartup),values:["true","header","false"]},{id:"install-telemetry",label:"Provider attribution",description:"Send optional provider attribution headers for supported services",currentValue:config.enableInstallTelemetry?"true":"false",values:["true","false"]},{id:"default-project-trust",label:"Default project trust",description:"Fallback behavior when no extension or saved trust decision decides project trust",currentValue:DEFAULT_PROJECT_TRUST_LABELS[config.defaultProjectTrust],values:Object.values(DEFAULT_PROJECT_TRUST_LABELS)},{id:"double-escape-action",label:"Double-escape action",description:"Action when pressing Escape twice with empty editor",currentValue:config.doubleEscapeAction,values:["tree","fork","none"]},{id:"tree-filter-mode",label:"Tree filter mode",description:"Default filter when opening /tree",currentValue:config.treeFilterMode,values:["default","no-tools","user-only","labeled-only","all"]},{id:"warnings",label:"Warnings",description:"Enable or disable individual warnings",currentValue:"configure",submenu:(_currentValue,done)=>new WarningSettingsSubmenu(currentWarnings,warnings=>{currentWarnings=warnings,callbacks.onWarningsChange(warnings)},()=>done())},{id:"model-thinking",label:"Default thinking level per model",description:`Override the default thinking level for specific models. ${cycleThinkingKey} cycles in-session.`,currentValue:modelThinkingOverridesSummary(currentModelThinkingLevels),submenu:(_currentValue,done)=>{let steps=[{key:"model",title:"Per-Model Thinking Level",description:"Select a model to configure",options:()=>{let items2=[...config.availableDefaultModels].sort((a,b2)=>{let aKey=modelSettingKey(a),bKey=modelSettingKey(b2);return aKey===currentModelKey?-1:bKey===currentModelKey?1:aKey===currentDefaultModelKey?-1:bKey===currentDefaultModelKey?1:a.provider.localeCompare(b2.provider)}).map(model=>{let key=modelSettingKey(model),override=currentModelThinkingLevels[key];return{value:key,label:modelItemLabel(model),description:override??void 0}});return items2.length===0&&items2.push({value:"__none__",label:"No models available",description:"Log in to a provider or configure an API key first"}),items2},preselect:()=>currentModelKey??currentDefaultModelKey,searchable:!0,layout:MODEL_PICKER_LAYOUT},{key:"level",title:ctx=>{let m2=defaultModelByValue.get(ctx.model);return`Thinking Level for ${m2?modelDisplayLabel(m2):ctx.model}`},description:"Select default thinking level for this model",options:ctx=>{let model=defaultModelByValue.get(ctx.model);if(!model)return[];let levels=model.reasoning?getSupportedThinkingLevels(model):["off"],activeLevel=currentModelThinkingLevels[ctx.model],items2=levels.map(level=>({value:level,label:`${level===activeLevel?"\u2713 ":" "}${level}`,description:THINKING_DESCRIPTIONS[level]}));return currentModelThinkingLevels[ctx.model]!==void 0&&items2.push({value:CLEAR_OVERRIDE_VALUE,label:" (clear override)",description:`Revert to global default (${config.thinkingLevel})`}),items2},preselect:ctx=>currentModelThinkingLevels[ctx.model]}],summary=()=>modelThinkingOverridesSummary(currentModelThinkingLevels);return new SteppedSubmenu(steps,selections=>{let model=defaultModelByValue.get(selections.model);model&&(selections.level===CLEAR_OVERRIDE_VALUE?(callbacks.onModelThinkingLevelRemove(model.provider,model.id),delete currentModelThinkingLevels[selections.model]):(callbacks.onModelThinkingLevelChange(model.provider,model.id,selections.level),currentModelThinkingLevels[selections.model]=selections.level))},()=>{done(summary())},{loop:!0})}},{id:"tui-mode",label:"TUI mode",description:"Interface layout; regular mode uses the terminal's normal scrollback",currentValue:config.tuiMode,values:["regular","fullscreen"]},{id:"fullscreen-exit-output",label:"Fullscreen exit output",description:"Print the transcript or only a session resume hint when exiting fullscreen mode",currentValue:config.fullscreenExitOutput,values:["transcript","resume-hint"]},{id:"fullscreen-scrollbar",label:"Fullscreen scrollbar",description:"Scrollbar behavior in fullscreen mode; has no effect in regular mode",currentValue:config.fullscreenScrollbar,values:["auto","always","hidden"]},{id:"fullscreen-copy-on-select",label:"Fullscreen copy on select",description:"Automatically copy selected text in fullscreen mode; disable to copy selections with Ctrl+X",currentValue:config.fullscreenCopyOnSelect?"true":"false",values:["true","false"]},{id:"fullscreen-wheel-scroll-lines",label:"Fullscreen wheel scrolling",description:"Lines per mouse-wheel event in fullscreen mode; 'auto' speeds up fast wheel spins where the terminal does not",currentValue:String(config.fullscreenWheelScrollLines),values:["auto",...[...new Set([1,2,3,5,10,config.fullscreenWheelScrollLines])].filter(lines=>lines!=="auto").sort((a,b2)=>a-b2).map(String)]},{id:"theme",label:"Theme",description:"Color theme for the interface",currentValue:config.currentTheme,submenu:(currentValue,done)=>new ThemeSubmenu(currentValue,config.terminalTheme,config.availableThemes,callbacks,done)}];supportsImages&&(items.splice(1,0,{id:"show-images",label:"Show images",description:"Render images inline in terminal",currentValue:config.showImages?"true":"false",values:["true","false"]}),items.splice(2,0,{id:"image-width-cells",label:"Image width",description:"Preferred inline image width in terminal cells",currentValue:String(config.imageWidthCells),values:["60","80","120"]})),items.splice(supportsImages?3:1,0,{id:"auto-resize-images",label:"Auto-resize images",description:"Resize large images to 2000x2000 max for better model compatibility",currentValue:config.autoResizeImages?"true":"false",values:["true","false"]});let autoResizeIndex=items.findIndex(item=>item.id==="auto-resize-images");items.splice(autoResizeIndex+1,0,{id:"block-images",label:"Block images",description:"Prevent images from being sent to LLM providers",currentValue:config.blockImages?"true":"false",values:["true","false"]});let blockImagesIndex=items.findIndex(item=>item.id==="block-images");items.splice(blockImagesIndex+1,0,{id:"skill-commands",label:"Skill commands",description:"Register skills as /skill:name commands",currentValue:config.enableSkillCommands?"true":"false",values:["true","false"]});let skillCommandsIndex=items.findIndex(item=>item.id==="skill-commands");items.splice(skillCommandsIndex+1,0,{id:"show-hardware-cursor",label:"Show hardware cursor",description:"Use the terminal cursor instead of Pi's drawn cursor",currentValue:config.showHardwareCursor?"true":"false",values:["true","false"]});let hardwareCursorIndex=items.findIndex(item=>item.id==="show-hardware-cursor");items.splice(hardwareCursorIndex+1,0,{id:"editor-padding",label:"Editor padding",description:"Horizontal padding for input editor (0-3)",currentValue:String(config.editorPaddingX),values:["0","1","2","3"]});let editorPaddingIndex=items.findIndex(item=>item.id==="editor-padding");items.splice(editorPaddingIndex+1,0,{id:"output-padding",label:"Output padding",description:"Horizontal padding for messages, tool output, and command output",currentValue:String(config.outputPad),values:["0","1"]});let outputPaddingIndex=items.findIndex(item=>item.id==="output-padding");items.splice(outputPaddingIndex+1,0,{id:"autocomplete-max-visible",label:"Autocomplete max items",description:"Max visible items in autocomplete dropdown (3-20)",currentValue:String(config.autocompleteMaxVisible),values:["3","5","7","10","15","20"]});let autocompleteIndex=items.findIndex(item=>item.id==="autocomplete-max-visible");items.splice(autocompleteIndex+1,0,{id:"clear-on-shrink",label:"Clear on shrink",description:"Clear empty rows when content shrinks (may cause flicker)",currentValue:config.clearOnShrink?"true":"false",values:["true","false"]});let clearOnShrinkIndex=items.findIndex(item=>item.id==="clear-on-shrink");items.splice(clearOnShrinkIndex+1,0,{id:"terminal-progress",label:"Terminal progress",description:"Show OSC 9;4 progress indicators in the terminal tab bar",currentValue:config.showTerminalProgress?"true":"false",values:["true","false"]}),this.addChild(new DynamicBorder),this.settingsList=new SettingsList(items,10,getSettingsListTheme(),(id,newValue)=>{switch(id){case"autocompact":callbacks.onAutoCompactChange(newValue==="true");break;case"show-images":callbacks.onShowImagesChange(newValue==="true");break;case"image-width-cells":callbacks.onImageWidthCellsChange(parseInt(newValue,10));break;case"auto-resize-images":callbacks.onAutoResizeImagesChange(newValue==="true");break;case"block-images":callbacks.onBlockImagesChange(newValue==="true");break;case"skill-commands":callbacks.onEnableSkillCommandsChange(newValue==="true");break;case"steering-mode":callbacks.onSteeringModeChange(newValue);break;case"follow-up-mode":callbacks.onFollowUpModeChange(newValue);break;case"transport":callbacks.onTransportChange(newValue);break;case"share-destination":callbacks.onSessionShareDestinationChange(newValue);break;case"http-idle-timeout":{let choice=HTTP_IDLE_TIMEOUT_CHOICES.find(item=>item.label===newValue);choice&&callbacks.onHttpIdleTimeoutMsChange(choice.timeoutMs);break}case"cache-warming-mode":callbacks.onCacheWarmingModeChange(newValue);break;case"hide-thinking":callbacks.onHideThinkingBlockChange(newValue==="true");break;case"mermaid-rendering":callbacks.onMermaidRenderingModeChange(newValue);break;case"cache-miss-notices":callbacks.onShowCacheMissNoticesChange(newValue==="true");break;case"collapse-changelog":callbacks.onCollapseChangelogChange(newValue==="true");break;case"quiet-startup":callbacks.onQuietStartupChange(newValue==="header"?"header":newValue==="true");break;case"install-telemetry":callbacks.onEnableInstallTelemetryChange(newValue==="true");break;case"default-project-trust":{let defaultProjectTrust=DEFAULT_PROJECT_TRUST_BY_LABEL.get(newValue);defaultProjectTrust&&callbacks.onDefaultProjectTrustChange(defaultProjectTrust);break}case"double-escape-action":callbacks.onDoubleEscapeActionChange(newValue);break;case"tree-filter-mode":callbacks.onTreeFilterModeChange(newValue);break;case"show-hardware-cursor":callbacks.onShowHardwareCursorChange(newValue==="true");break;case"editor-padding":callbacks.onEditorPaddingXChange(parseInt(newValue,10));break;case"output-padding":callbacks.onOutputPadChange(newValue==="0"?0:1);break;case"autocomplete-max-visible":callbacks.onAutocompleteMaxVisibleChange(parseInt(newValue,10));break;case"clear-on-shrink":callbacks.onClearOnShrinkChange(newValue==="true");break;case"terminal-progress":callbacks.onShowTerminalProgressChange(newValue==="true");break;case"tui-mode":callbacks.onTuiModeChange(newValue);break;case"fullscreen-exit-output":callbacks.onFullscreenExitOutputChange(newValue);break;case"fullscreen-scrollbar":callbacks.onFullscreenScrollbarChange(newValue);break;case"fullscreen-copy-on-select":callbacks.onFullscreenCopyOnSelectChange(newValue==="true");break;case"fullscreen-wheel-scroll-lines":callbacks.onFullscreenWheelScrollLinesChange(newValue==="auto"?"auto":parseInt(newValue,10));break;case"theme":callbacks.onThemeChange(newValue);break}},callbacks.onCancel,{enableSearch:!0}),this.addChild(this.settingsList),this.addChild(new DynamicBorder)}getSettingsList(){return this.settingsList}};var SkillInvocationMessageComponent=class extends Box{constructor(skillBlock,markdownTheme=getMarkdownTheme(),outputPad=1){super(outputPad,1,t=>theme.bg("customMessageBg",t)),this.expanded=!1,this.skillBlock=skillBlock,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.setPaddingX(outputPad)}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let content=new Container;if(this.expanded){let label=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m");content.addChild(new Text(label,0,0));let header2=`**${this.skillBlock.name}**
|
|
1785
1767
|
|
|
1786
|
-
`;content.addChild(new Markdown(header2+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected2=i===this.selectedIndex,cursor=isSelected2?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected2),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body2=prefixPart+label+labelTimestamp+content;isSelected2&&(gutter=theme.bg("selectedBg",gutter),body2=theme.bg("selectedBg",body2)),renderedRows.push({gutter,body:body2,anchorCol,bodyWidth:visibleWidth(body2),isSelected:isSelected2})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected2){let entry=node.entry,result2,normalize2=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize2(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize2(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize2(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize2(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize2(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize2(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected2?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":return`[read: ${shortenPath3(String(args.path||args.file_path||""))}${formatReadLineRange(args.offset,args.limit)}]`;case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value=this.input.getValue().trim();this.onSubmit?.(this.entryId,value||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.labelInput&&(this.labelInput.focused=value)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear(),this.addChild(new Markdown(this.text,this.outputPad,1,this.markdownTheme,{color:content=>theme.fg("userMessageText",content),bgColor:content=>theme.bg("userMessageBg",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)}))}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected2=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected2?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected2?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};function createAllToolRenderers(){return{tasks:{renderCall:(args,theme2,context)=>renderTasksCall(args,theme2,context),renderResult:renderTasksResult},read:readRenderers,bash:createShellRenderers({name:"bash",prompt:"$"}),powershell:createShellRenderers({name:"powershell",prompt:"PS>"}),edit:editRenderers,write:writeRenderers,grep:grepRenderers,find:findRenderers,ls:lsRenderers}}function withBuiltInRenderers(toolName,definition){let builtIn=createAllToolRenderers()[toolName];return definition?builtIn?{...definition,renderCall:definition.renderCall??builtIn.renderCall,renderResult:definition.renderResult??builtIn.renderResult}:definition:builtIn}function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value])=>{try{return`${key}=${JSON.stringify(value)??String(value)}`}catch{return`${key}=${String(value)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,toolStyle.fallbackArgsWidth,"...")}function createCallFallback(toolName,args,expanded=!1){if(expanded)return new Text(formatToolCallWithArgs(toolName,args,theme,!0),0,0);let summary=formatFallbackArgs(args),suffix=summary?theme.fg("dim",`(${summary})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(toolName))}${suffix}`,0,0)}var FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,toolStyle.collapsed.fallbackLines,width);if(preview.skippedCount<=0)return preview.visualLines;let noun=preview.skippedCount===1?"line":"lines",hint=theme.fg("muted",`... (${preview.skippedCount} earlier ${noun},`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return[truncateToWidth(hint,width,"..."),...preview.visualLines]}invalidate(){}};var builtInRenderers,ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSources=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.outputPad=options.outputPad??1,this.ui=ui,this.cwd=cwd,this.gap=new Spacer(toolStyle.gap.afterOther),this.addChild(this.gap),this.contentContainer=new Container,this.selfRenderContainer=new Container,this.addChild(this.isSelfRendered()?this.selfRenderContainer:this.contentContainer),this.updateDisplay()}getCallRenderer(){return this.toolDefinition?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult}isSelfRendered(){return this.toolDefinition?.renderShell==="self"}status(){return toolStatus({isPartial:this.isPartial,isError:this.result?.isError??!1})}setLeadingGap(lines){this.gap.setLines(lines)}getRenderContext(lastComponent){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,durationMs:this.isPartial?void 0:this.result?.durationMs,outputPad:this.outputPad,result:this.result?{content:this.result.content,details:this.result.details}:void 0}}frame(component,kind){return new FramedComponent(component,kind,()=>toolMarkerColor(this.status()))}createResultFallback(){let output=this.getTextOutput();if(output)return new FallbackResultComponent(output,this.expanded)}hidesCollapsedResult(){if(this.expanded||this.result?.isError||!toolStyle.collapsed.headerOnly.has(this.toolName))return!1;builtInRenderers??=createAllToolRenderers();let builtIn=builtInRenderers[this.toolName];return builtIn?.renderResult!==void 0&&builtIn.renderResult===this.getResultRenderer()}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,this.updateDisplay(),this.ui.requestRender())}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.outputPad=outputPad,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}render(width){if(this.hideComponent)return[];if(this.isSelfRendered()){let contentLines=this.selfRenderContainer.render(width);if(this.selfRenderHeight=contentLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[];contentLines.length>0&&(lines.push(""),lines.push(...contentLines));for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.isSelfRendered())return super.handleMouse(event);if(!(event.y<=0||event.y>this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-1,height:this.selfRenderHeight})}updateDisplay(){let hasContent=!1;this.hideComponent=!1;let selfRendered=this.isSelfRendered(),renderContainer=selfRendered?this.selfRenderContainer:this.contentContainer;renderContainer.clear();let addCall=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"header"))),hasContent=!0},addResult=component=>{renderContainer.addChild(selfRendered?component:this.createResultRegion(this.frame(component,"body"))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(createCallFallback(this.toolName,this.args,this.expanded));else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(createCallFallback(this.toolName,this.args,this.expanded))}if(this.result&&(selfRendered||!this.hidesCollapsedResult())){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}let previousImages=this.imageComponents,previousSources=this.imageSources;for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[],this.imageSources=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let img of imageBlocks)if(caps.images&&this.showImages&&img.data&&img.mimeType){let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let source={data:img.data,mimeType:img.mimeType,widthCells:this.imageWidthCells},index3=this.imageComponents.length,previous=previousSources[index3],imageComponent=previous?.data===source.data&&previous.mimeType===source.mimeType&&previous.widthCells===source.widthCells?previousImages[index3]:new Image(source.data,source.mimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:source.widthCells});source.mimeType!=="image/png"&&ensurePngTranscoder(()=>{this.disposed||(this.invalidate(),this.ui.requestRender())}),this.imageComponents.push(imageComponent),this.imageSources.push(source),this.addChild(imageComponent)}}!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}dispose(){this.disposed||(this.disposed=!0,this.rendererState.dispose?.())}};function hotkeysTaskSection(display){let detach=KEYBINDINGS["app.tasks.detach"],detachSelected=KEYBINDINGS["app.tasks.detachSelected"];return`
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
`}async function confirmStopBranchTasks(stopped,confirm){if(stopped.length===0)return!0;let shown=stopped.slice(0,5).map(task=>` ${cleanTaskText(firstCommandLine(task.command??task.title))}`);return stopped.length>shown.length&&shown.push(` \u2026and ${stopped.length-shown.length} more`),confirm(`Stop ${stopped.length} running task${stopped.length===1?"":"s"}?`,`They were started on the branch you are leaving and will be cancelled:
|
|
1793
|
-
${shown.join(`
|
|
1794
|
-
`)}`)}var TaskViewport=class{constructor(follow=!1){this.scroll=0,this.entries=[],this.height=1,this.start=0,this.follow=follow}layout(lines,width,height){this.height=Math.max(1,height),(lines!==this.wrapped?.lines||width!==this.wrapped.width)&&(this.wrapped={lines,width},this.entries=lines.flatMap((line,index3)=>{let column=0;return wrapTextWithAnsi(line,Math.max(1,width)).map(text2=>{let entry={text:text2,line:index3,column};return column+=visibleWidth(text2),entry})}));let offset=this.scroll;if(this.anchor){let anchor=this.anchor,first=this.entries.findIndex(entry=>entry.line===anchor.line);if(first>=0)for(offset=first;offset+1<this.entries.length&&this.entries[offset+1].line===anchor.line&&this.entries[offset+1].column<=anchor.column;)offset++}return this.start=this.follow?this.max:Math.min(offset,this.max),this.entries.slice(this.start,this.start+this.height).map(entry=>entry.text)}get max(){return Math.max(0,this.entries.length-this.height)}move(direction,page,tail2){this.scroll=Math.max(0,Math.min(this.max,this.start+direction*(page?this.height:1)));let entry=this.entries[this.scroll];this.anchor=entry?{line:entry.line,column:entry.column}:void 0,this.follow=tail2&&direction>0&&this.scroll===this.max}jump(bottom,tail2){this.scroll=bottom?this.max:0;let entry=this.entries[this.scroll];this.anchor=entry?{line:entry.line,column:entry.column}:void 0,this.follow=bottom&&tail2}get range(){return`${this.entries.length?this.start+1:0}\u2013${Math.min(this.start+this.height,this.entries.length)}/${this.entries.length}`}};var SHELLS={bash:{name:"Bash",language:"bash"},powershell:{name:"PowerShell",language:"powershell"}};function taskLines(task,read,theme2){let shell=SHELLS[task.kind],command=cleanTaskText(task.command??task.title),[first="",...rest]=shell?highlightCode(command,shell.language):command.split(`
|
|
1795
|
-
`),info=[theme2.fg("accent",shell?.name??task.kind),`${task.command===void 0?"Title ":"Command "}${first}`,...rest,...task.commandTruncated?["[Saved command truncated.]"]:[],...task.cwd?[`Directory ${cleanTaskText(task.cwd)}`]:[],...task.outputPath?[`Log ${cleanTaskText(task.outputPath)}`]:[],...task.exitCode!==void 0?[`Exit ${task.exitCode??"signal"}`]:[]],saved=task.result?.content.filter(block=>block.type==="text").map(block=>block.text).join(`
|
|
1796
|
-
`),empty=task.status==="completed"?"Completed with no output.":isTaskTerminal(task.status)?"No saved output.":"No output yet.",output=cleanTaskText((read?read.text:saved)||empty).split(`
|
|
1797
|
-
`).map(line=>theme2.fg("toolOutput",line));return read?.readError&&output.unshift(theme2.fg("warning","Log unavailable; showing saved result.")),(!read||read.readError)&&task.resultTruncated&&output.push(theme2.fg("warning","Saved result truncated.")),{info,output}}var TaskInspector=class{constructor(options){this.positions=new Map,this.reading=!1,this.disposed=!1,this.options=options}get position(){let id=this.task?.id,position=id?this.positions.get(id):void 0;return position||(position={info:new TaskViewport,output:new TaskViewport(!0)},id&&this.positions.set(id,position)),position}select(task){if(!this.disposed){if(this.task?.id!==task?.id){let release2=task?this.options.host.retain(task.id):void 0,previous=this.release;this.release=release2,previous?.()}this.task=task}}prune(ids){for(let id of this.positions.keys())ids.has(id)||this.positions.delete(id)}invalidate(){this.cache=void 0}async refresh(){let task=this.task;if(this.disposed||!task||this.reading)return;let position=this.position;if(!(position.read&&(!position.output.follow||isTaskTerminal(position.read.task.status)))){this.reading=!0;try{let read=await this.options.host.read(task.id,{mode:"tail",bytes:49152});if(this.disposed||this.task?.id!==task.id||!position.output.follow&&position.read)return;position.read=read}catch(error){!this.disposed&&this.task?.id===task.id&&(position.output.follow||!position.read)&&(position.read={task,text:"",readError:`Cannot read output: ${cleanTaskText(String(error))}`,totalBytes:0,truncated:!1})}finally{this.reading=!1,this.disposed||this.options.requestRender(),!this.disposed&&this.task?.id!==task.id&&await this.refresh()}}}lines(tab){let task=this.task;if(!task)return[];let read=this.position.read;return(this.cache?.task!==task||this.cache.read!==read)&&(this.cache={task,read,lines:taskLines(task,read,this.options.theme)}),this.cache.lines[tab]}dispose(){this.disposed||(this.disposed=!0,this.release?.(),this.release=void 0,this.positions.clear())}};var pad=(text2,width)=>truncateToWidth(text2,Math.max(1,width),"\u2026",!0);function renderTasksLayout(options){let{width,height,theme:theme2,selection,inspector,list:list2,focus,keybindings}=options,hint=key=>keyLabel(key,{keybindings}),result2={hits:[],listWidth:0,listPageSize:1,lines:[]};if(width<1||height<1)return result2;let wide=width>=100,listWidth=wide?Math.min(42,Math.max(32,Math.floor(width*.32))):width,rightWidth=wide?width-listWidth-1:width,rightX=wide?listWidth+1:0,bodyHeight=height-5,hits=result2.hits;result2.listWidth=listWidth,result2.listPageSize=Math.max(1,Math.floor((bodyHeight-1)/2));let pane=(lines,size,active)=>{let border=text2=>theme2.fg(wide&&active?"borderAccent":"borderMuted",text2);return[border(`\u250C${"\u2500".repeat(size-2)}\u2510`),...lines.map(line=>border("\u2502")+pad(line,size-2)+border("\u2502")),border(`\u2514${"\u2500".repeat(size-2)}\u2518`)]};if(width<60||height<14){result2.tooSmall=!0;let message="Terminal too small for /tasks. Enlarge the window to continue.",close=`${hint("tui.select.cancel")} close`,boxWidth=Math.min(width,46),inner=boxWidth-2,wrapped=wrapTextWithAnsi(message,inner).map(line=>theme2.fg("warning",line)),spacious=[theme2.fg("text","Tasks"),"",...wrapped,"",theme2.fg("dim",close)],tight=[theme2.fg("text","Tasks"),...wrapped,theme2.fg("dim",close)],body2=height>=spacious.length+2?spacious:tight;if(inner>=16&&height>=body2.length+2){let box2=pane(body2,boxWidth,!1),left2=Math.floor((width-boxWidth)/2),top=Math.max(0,Math.floor((height-box2.length)/2)),blank=" ".repeat(width);result2.lines=[...Array.from({length:top},()=>blank),...box2.map(line=>" ".repeat(left2)+line+" ".repeat(width-left2-boxWidth)),...Array.from({length:height-top-box2.length},()=>blank)],hits.push({x:left2+1,y:top+body2.length,width:visibleWidth(close),cancel:!0})}else for(result2.lines=["Tasks",message,close].slice(0,height).map(line=>pad(line,width));result2.lines.length<height;)result2.lines.push(" ".repeat(width));return result2}let visible=list2.render(selection,theme2,listWidth-2,bodyHeight),listHeader=theme2.fg("text","Tasks"),searchLabel=`${hint("app.tasks.search")} find`;if(options.searchLine)listHeader=options.searchLine(listWidth-2);else{let x2=Math.max(6,listWidth-2-visibleWidth(searchLabel));listHeader+=" ".repeat(x2-5)+theme2.fg("dim",searchLabel),(wide||focus==="list")&&hits.push({x:x2+1,y:1,width:visibleWidth(searchLabel),key:"app.tasks.search"})}(wide||focus==="list")&&visible.forEach((row,index3)=>{row.taskId&&hits.push({x:1,y:2+index3,width:listWidth-2,taskId:row.taskId})});let left=[listHeader,...Array.from({length:bodyHeight},(_2,i)=>visible[i]?.text??""),theme2.fg("dim",list2.range)],task=inspector.task,tab=selection.state.tab,tabLabel=(id,label)=>theme2.style(label,{fg:"text",underline:tab===id}),right=[`${tabLabel("output","Output")} ${tabLabel("info","Details")}`];(wide||focus==="inspector")&&hits.push({x:rightX+1,y:1,width:6,tab:"output"},{x:rightX+9,y:1,width:7,tab:"info"});let content=[],reading="";if(task){wide||content.push(theme2.fg("text",cleanTaskText(firstCommandLine(task.command??task.title))),theme2.fg("muted",`${statusName(task.status)} \xB7 ${runtimeLabel(task)}`));let lines=inspector.lines(tab),position=inspector.position,read=position.read,diagnostics=[task.error,read?.readError].filter(text2=>!!text2).map(cleanTaskText);tab==="output"&&diagnostics.length&&content.push(theme2.fg("warning",diagnostics.join(" \xB7 ").replace(/\n/g," ")));let source=tab==="info"?[`Task ID ${task.id}`,`Status ${statusName(task.status)} \xB7 ${statusName(task.mode)} \xB7 ${runtimeLabel(task)}`,...diagnostics,...lines]:lines;content.push(...position[tab].layout(source,rightWidth-2,bodyHeight-content.length)),tab==="output"?(reading=position.output.follow?isTaskTerminal(task.status)?"Finished":"Live":isTaskTerminal(task.status)?`Finished \xB7 ${hint("app.tasks.follow")} load final output`:`Browsing \xB7 ${hint("app.tasks.follow")} follow output`,!position.output.follow&&(wide||focus==="inspector")&&hits.push({x:rightX+1,y:height-3,width:Math.min(rightWidth-2,visibleWidth(reading)),key:"app.tasks.follow"}),read?.truncated&&(reading+=` \xB7 Tail preview: ${formatSize(Buffer.byteLength(read.text))} of ${formatSize(read.totalBytes)}`)):tab==="info"&&(reading=`Details ${position.info.range}`)}else content.push(theme2.fg("muted","Select a task to inspect its result."));right.push(...Array.from({length:bodyHeight},(_2,i)=>content[i]??""),theme2.fg("dim",reading));let rightPane=pane(right,rightWidth,focus==="inspector"),panels=wide?pane(left,listWidth,focus==="list").map((line,i)=>`${line} ${rightPane[i]}`):pane(focus==="list"?left:right,width,!1),footer="",addHint=(key,label,target)=>{let text2=`${hint(key)} ${label}`,x2=visibleWidth(footer)+(footer?3:0);x2+visibleWidth(text2)>width||(footer+=(footer?" \xB7 ":"")+text2,target&&hits.push({x:x2,y:height-1,width:visibleWidth(text2),...target}))};if(options.help||options.pendingKill){hits.length=0;let body2;if(options.help){let controls=[["app.tasks.nextFocus","Switch task list / inspector"],["app.tasks.previousFocus","Switch inspector / task list"],["app.tasks.previousTab","Output (inspector only)"],["app.tasks.nextTab","Details (inspector only)"],["tui.select.up","Previous task / scroll up"],["tui.select.down","Next task / scroll down"],["tui.select.pageUp","Page up in task list"],["tui.select.pageDown","Page down in task list"],["tui.editor.pageUp","Page up in inspector"],["tui.editor.pageDown","Page down in inspector"],["app.tasks.top","Top of list / content"],["app.tasks.bottom","Bottom of list / content"],["app.tasks.search","Locate a retained task; Enter chooses, Escape restores selection"],["app.tasks.follow","Follow latest / final output (Output only)"],["app.tasks.detach","Move every eligible foreground execution to the background"],["app.tasks.detachSelected","Move selected foreground task to background"],["app.tasks.kill","Request stop of selected whole task"],["app.tasks.confirmStop","Confirm stop"],["tui.select.cancel","Close current search, help or confirmation; otherwise close panel"]];body2=[theme2.fg("text","Task controls"),...options.help.layout(controls.map(([key,label])=>hint(key).padEnd(14)+label),width-2,height-5),""],addHint("tui.select.up",`/ ${hint("tui.select.down")} scroll`),addHint("tui.select.cancel","back",{cancel:!0})}else{let target=selection.all.find(task2=>task2.id===options.pendingKill),command=wrapTextWithAnsi(cleanTaskText(target?.command??target?.title??options.pendingKill),width-2),preview=command.slice(0,height-8);preview.length<command.length&&(preview[preview.length-1]="\u2026 Full command in Details."),body2=[theme2.fg("text","Stop task?"),"Stops the whole task, including its active work.",`Task ID: ${options.pendingKill}`,"",...preview],addHint("app.tasks.confirmStop","confirm",{key:"app.tasks.confirmStop"}),addHint("tui.select.cancel","cancel",{cancel:!0})}for(;body2.length<height-3;)body2.push("");panels=pane(body2,width,!1)}else if(options.searchLine){for(let i=hits.length-1;i>=0;i--)hits[i].taskId||hits.splice(i,1);addHint("tui.select.up",`/ ${hint("tui.select.down")} choose`),addHint("tui.select.confirm","locate"),addHint("tui.select.cancel","cancel",{cancel:!0})}else addHint("tui.select.up",`/ ${hint("tui.select.down")}${focus==="list"?" tasks":" scroll"}`),addHint("app.tasks.nextFocus",focus==="list"?tab==="output"?"output":"details":"tasks",{key:"app.tasks.nextFocus"}),addHint("tui.select.cancel","close",{cancel:!0}),focus==="list"?addHint("app.tasks.search","find",{key:"app.tasks.search"}):(addHint("app.tasks.previousTab","output",{tab:"output"}),addHint("app.tasks.nextTab","details",{tab:"info"})),task&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&(addHint("app.tasks.kill","stop",{key:"app.tasks.kill"}),task.mode==="foreground"&&options.canDetach&&addHint("app.tasks.detachSelected","background",{key:"app.tasks.detachSelected"})),addHint("app.tasks.help","keys",{key:"app.tasks.help"}),options.feedback&&(footer=options.feedback);return result2.lines=[...panels,theme2.fg(options.pendingKill?"warning":"dim",pad(footer,width))],result2}var TaskList=class{constructor(){this.start=0,this.height=1,this.rows=[],this.selectedLine=-1,this.reveal=!1}showSelection(){this.reveal=!0}scroll(delta){this.start=Math.max(0,Math.min(Math.max(0,this.rows.length-this.height),this.start+delta))}render(selection,theme2,width,height){let rows=[],labels=selection.rows.map(task=>cleanTaskText(firstCommandLine(task.command??task.title))),fitted=labels.map(label=>truncateToWidth(label,Math.max(1,width-3),"\u2026")),group="",selectedLine=-1;for(let[index3,task]of selection.rows.entries()){let nextGroup=isTaskTerminal(task.status)?"Finished":"Active";nextGroup!==group&&(rows.push({text:theme2.fg("dim",nextGroup)}),group=nextGroup);let selected=task.id===selection.state.selectedId;selected&&(selectedLine=rows.length);let marker=statusMarker(task.status,{now:Date.now()}),duplicate=fitted.some((label,other)=>other!==index3&&label===fitted[index3]),meta=`${runtimeLabel(task)}${duplicate?` \xB7 ${task.id.slice(-8)}`:""}`,texts=[`${theme2.fg(marker.color,marker.glyph)} ${theme2.fg("text",labels[index3])}`,` ${theme2.fg(marker.color,statusName(task.status))}${theme2.fg("muted",` \xB7 ${meta}`)}`];for(let text2 of texts){let padded=truncateToWidth(text2,width,"\u2026",!0);rows.push({text:selected?theme2.getBgAnsi("selectedBg")==="\x1B[49m"?theme2.style(stripTerminalSequences(padded),{inverse:!0}):theme2.bg("selectedBg",padded):padded,taskId:task.id})}}rows.length||rows.push({text:theme2.fg("muted",selection.query?"No matching tasks.":"No retained tasks.")});let sameSelection=this.selectedId===selection.state.selectedId,selectedWasVisible=sameSelection&&this.selectedLine>=this.start&&this.selectedLine<this.start+this.height&&selectedLine>=0;if(selectedWasVisible)this.start+=selectedLine-this.selectedLine;else{let anchor=this.rows[this.start]?.taskId,offset=anchor&&this.rows[this.start-1]?.taskId===anchor?1:0,next=anchor?rows.findIndex(row=>row.taskId===anchor):-1;next>=0&&(this.start=next+offset)}return selectedLine>=0&&(!sameSelection||this.reveal||selectedWasVisible)&&(selectedLine<this.start?this.start=selectedLine:selectedLine+1>=this.start+height&&(this.start=selectedLine+2-height)),this.start=Math.max(0,Math.min(Math.max(0,rows.length-height),this.start)),this.rows=rows,this.height=height,this.selectedId=selection.state.selectedId,this.selectedLine=selectedLine,this.reveal=!1,rows.slice(this.start,this.start+height)}get range(){if(this.rows.length<=this.height)return"";let ids=[...new Set(this.rows.flatMap(row=>row.taskId?[row.taskId]:[]))],visible=this.rows.slice(this.start,this.start+this.height).flatMap(row=>row.taskId?[row.taskId]:[]);return`Tasks ${ids.indexOf(visible[0])+1}-${ids.indexOf(visible.at(-1))+1} of ${ids.length}`}};var TaskSelection=class{constructor(state2){this.all=[],this.rows=[],this.query="",this.state=state2}get selected(){return this.rows.find(task=>task.id===this.state.selectedId)}get activeCount(){return this.all.filter(task=>!isTaskTerminal(task.status)).length}sync(all){this.all=all,this.refresh()}select(id){this.state.selectedId=id,this.refresh()}refresh(){let{selectedId}=this.state,active=this.all.filter(task=>!isTaskTerminal(task.status)).sort((a,b2)=>b2.startedAt-a.startedAt||a.id.localeCompare(b2.id)),history=this.all.filter(task=>isTaskTerminal(task.status)).sort((a,b2)=>(b2.endedAt??0)-(a.endedAt??0)||a.id.localeCompare(b2.id)),rows=[...active,...history],search2=this.query.toLocaleLowerCase().trim();this.rows=search2?rows.filter(task=>`${task.title}
|
|
1798
|
-
${task.command??""}
|
|
1799
|
-
${task.kind}
|
|
1800
|
-
${task.id}`.toLocaleLowerCase().includes(search2)):rows,this.rows.some(task=>task.id===selectedId)||(this.state.selectedId=this.rows[0]?.id)}};var actions=["app.tasks.search","app.tasks.kill","app.tasks.detachSelected","app.tasks.previousTab","app.tasks.nextTab","app.tasks.follow","app.tasks.top","app.tasks.bottom","app.tasks.nextFocus","app.tasks.previousFocus","app.tasks.help"],TasksMenu=class{constructor(options){this.focused=!1,this.list=new TaskList,this.focus="list",this.searching=!1,this.dirty=!0,this.tickQueued=!1,this.refreshQueued=!1,this.disposed=!1,this.options=options,this.width=options.tui.terminal.columns,this.selection=new TaskSelection(options.state??{tab:"output"}),this.inspector=new TaskInspector({host:options.host,theme:options.theme,requestRender:()=>options.tui.requestRender()}),this.search=new Input({prompt:"Find task: ",placeholder:"title, command, kind or ID"}),this.sync(),this.unsubscribe=options.host.subscribe(()=>{this.dirty=!0,this.queueTick(),options.tui.requestRender()}),this.pollTimer=setInterval(()=>{this.queueTick(!0),this.selection.activeCount&&options.tui.requestRender()},options.pollIntervalMs??1e3),this.pollTimer.unref?.(),this.queueTick(!0)}sync(){if(this.disposed||!this.dirty)return;this.dirty=!1;let previous=this.selection.selected;this.selection.sync(this.options.host.list()),this.inspector.select(this.selection.selected),this.inspector.prune(new Set(this.selection.all.map(task=>task.id)));let selected=this.selection.selected;selected&&isTaskTerminal(selected.status)&&previous&&!isTaskTerminal(previous.status)&&(this.feedback=void 0),this.pendingKill&&(this.pendingKill!==selected?.id||selected&&isTaskTerminal(selected.status))&&this.clearKill();let animates=this.selection.all.some(task=>task.status==="running");animates&&!this.animationTimer?(this.animationTimer=setInterval(()=>this.options.tui.requestRender(),STATUS_SPINNER_INTERVAL_MS),this.animationTimer.unref?.()):animates||(clearInterval(this.animationTimer),this.animationTimer=void 0)}queueTick(refresh=!1){this.disposed||(this.refreshQueued||=refresh,!this.tickQueued&&(this.tickQueued=!0,Promise.resolve().then(async()=>{if(this.tickQueued=!1,this.disposed)return;let refresh2=this.refreshQueued;this.refreshQueued=!1,this.sync(),(refresh2||this.inspector.task&&isTaskTerminal(this.inspector.task.status))&&await this.inspector.refresh()}).catch(()=>{})))}invalidate(){this.inspector.invalidate()}clearKill(){this.pendingKill=void 0}selectedChanged(){this.clearKill(),this.list.showSelection(),this.inspector.select(this.selection.selected),this.queueTick(!0)}stop(confirm=!1){let task=this.selection.selected;if(confirm){let id=this.pendingKill;if(this.clearKill(),!id||id!==task?.id||isTaskTerminal(task.status))return;this.feedback=this.options.host.kill(id)?"Cancellation requested; waiting for cleanup.":"No new cancellation requested."}else task&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&(this.pendingKill=task.id)}finishSearch(cancel){let id=cancel?this.beforeSearch?.id:this.selection.state.selectedId;!cancel&&!id||(this.focus=cancel?this.beforeSearch?.focus??"list":"list",this.searching=!1,this.search.focused=!1,this.selection.query="",this.selection.select(id),this.beforeSearch=void 0,this.selectedChanged())}action(key){switch(key){case"app.tasks.search":this.beforeSearch={id:this.selection.state.selectedId,focus:this.focus},this.focus="list",this.searching=!0,this.search.focused=!0,this.search.setValue("");break;case"app.tasks.previousTab":case"app.tasks.nextTab":this.focus==="inspector"&&(this.selection.state.tab=key==="app.tasks.previousTab"?"output":"info");break;case"app.tasks.nextFocus":case"app.tasks.previousFocus":this.focus=this.focus==="list"?"inspector":"list";break;case"app.tasks.follow":this.focus==="inspector"&&this.selection.state.tab==="output"&&(this.inspector.position.output.jump(!0,!0),this.queueTick(!0));break;case"app.tasks.top":case"app.tasks.bottom":this.focus==="list"?(this.selection.select(key==="app.tasks.top"?this.selection.rows[0]?.id:this.selection.rows.at(-1)?.id),this.selectedChanged()):this.inspector.position[this.selection.state.tab].jump(key==="app.tasks.bottom",this.selection.state.tab==="output");break;case"app.tasks.kill":this.stop();break;case"app.tasks.confirmStop":this.stop(!0);break;case"app.tasks.detachSelected":{let task=this.selection.selected;task?.mode==="foreground"&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&this.options.host.enabled!==!1&&(this.feedback=this.options.host.detach?.(task.id)?"Selected task moved to background; execution continues.":"This task cannot move to background.");break}case"app.tasks.help":this.help=this.help?void 0:new TaskViewport;break}}move(direction,page=!1){if(this.help){this.help.move(direction,page,!1);return}if(this.focus==="list"){let rows=this.selection.rows;if(!rows.length)return;let index3=rows.findIndex(task=>task.id===this.selection.state.selectedId),next=page?Math.max(0,Math.min(rows.length-1,index3+direction*(this.layout?.listPageSize??1))):(index3+direction+rows.length)%rows.length;this.selection.select(rows[next]?.id),this.selectedChanged()}else this.inspector.position[this.selection.state.tab].move(direction,page,this.selection.state.tab==="output")}handleInput(data){if(this.disposed)return;this.sync(),this.render(this.width);let kb=this.options.keybindings;this.feedback=void 0;try{if(this.layout?.tooSmall){if(kb.matches(data,"tui.select.cancel"))if(this.help)this.help=void 0;else if(this.searching)this.finishSearch(!0);else if(this.pendingKill)this.clearKill();else{this.dispose(),this.options.onClose();return}}else if(this.help)kb.matches(data,"tui.select.cancel")||kb.matches(data,"app.tasks.help")?this.help=void 0:kb.matches(data,"app.tasks.top")||kb.matches(data,"app.tasks.bottom")?this.help.jump(kb.matches(data,"app.tasks.bottom"),!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.editor.pageUp")?this.help.move(-1,kb.matches(data,"tui.editor.pageUp"),!1):(kb.matches(data,"tui.select.down")||kb.matches(data,"tui.editor.pageDown"))&&this.help.move(1,kb.matches(data,"tui.editor.pageDown"),!1);else if(this.searching)kb.matches(data,"tui.select.cancel")?this.finishSearch(!0):kb.matches(data,"tui.select.confirm")?this.finishSearch(!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.pageUp")?this.move(-1,kb.matches(data,"tui.select.pageUp")):kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.pageDown")?this.move(1,kb.matches(data,"tui.select.pageDown")):(this.search.handleInput(data),this.selection.query=this.search.getValue().slice(0,512),this.selection.refresh(),this.selectedChanged());else if(this.pendingKill)kb.matches(data,"app.tasks.confirmStop")?this.stop(!0):kb.matches(data,"tui.select.cancel")&&this.clearKill();else if(kb.matches(data,"tui.select.cancel")){this.dispose(),this.options.onClose();return}else{let pageUp=kb.matches(data,this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp"),pageDown=kb.matches(data,this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown");if(pageUp||kb.matches(data,"tui.select.up"))this.move(-1,pageUp);else if(pageDown||kb.matches(data,"tui.select.down"))this.move(1,pageDown);else{if(kb.matches(data,"tui.select.confirm"))return;{let key=actions.find(key2=>kb.matches(data,key2));key&&this.action(key)}}}}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}this.queueTick(!0),this.options.tui.requestRender()}handleMouse(event){if(this.disposed||event.ctrl||event.alt||event.shift)return;this.feedback=void 0,this.render(event.width);let layout=this.layout;if(event.type==="wheel"&&event.wheelDelta){if(!this.pendingKill&&!layout.tooSmall&&event.y>=2&&event.y<this.options.tui.terminal.rows-3){let delta=Math.sign(event.wheelDelta)*Math.min(20,Math.abs(event.wheelDelta)),region=this.width>=100?event.x<layout.listWidth?"list":"inspector":this.focus;this.help?this.help.move(delta,!1,!1):region==="list"?this.list.scroll(delta):this.searching||this.inspector.position[this.selection.state.tab].move(delta,!1,this.selection.state.tab==="output")}}else if(event.type==="click"&&event.button==="left"){let hit=layout.hits.find(hit2=>hit2.y===event.y&&event.x>=hit2.x&&event.x<hit2.x+hit2.width);try{hit?.cancel?this.searching?this.finishSearch(!0):this.help?this.help=void 0:this.pendingKill?this.clearKill():(this.dispose(),this.options.onClose()):hit?.taskId?(this.selection.select(hit.taskId),this.selectedChanged(),this.focus="list",this.searching&&this.finishSearch(!1)):hit?.tab?(this.focus="inspector",this.selection.state.tab=hit.tab):hit?.key?(hit.key==="app.tasks.follow"&&(this.focus="inspector"),this.action(hit.key)):!this.pendingKill&&!this.searching&&!this.help&&!layout.tooSmall&&event.y>=1&&event.y<this.options.tui.terminal.rows-2&&this.width>=100&&(this.focus=event.x<layout.listWidth?"list":"inspector")}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}}else return;return this.queueTick(!0),this.options.tui.requestRender(),{handled:!0,focus:event.type==="click"}}render(width){return this.width=width,this.sync(),this.layout=renderTasksLayout({width,height:this.options.tui.terminal.rows,theme:this.options.theme,keybindings:this.options.keybindings,selection:this.selection,inspector:this.inspector,list:this.list,focus:this.focus,searchLine:this.searching?width2=>this.search.render(width2).join(""):void 0,pendingKill:this.pendingKill,feedback:this.feedback,help:this.help,canDetach:this.options.host.enabled!==!1&&!!this.options.host.detach}),this.layout.lines}dispose(){this.disposed||(this.disposed=!0,clearInterval(this.pollTimer),clearInterval(this.animationTimer),this.clearKill(),this.unsubscribe(),this.inspector.dispose())}};function bindTasksUI(ctx){let state2={tab:"output"},unsubscribe,unsubscribeDetachKey,closeMenu,hintTimer,start=()=>{unsubscribe?.(),unsubscribeDetachKey?.();let update=()=>{clearTimeout(hintTimer),hintTimer=void 0;let all=ctx.tasks.list(),background=all.filter(task=>task.mode==="background"&&!isTaskTerminal(task.status)).length,parts=[];background&&(parts.push(theme.fg("text",`${background} background task${background===1?"":"s"}`)),parts.push(theme.fg("accent","/tasks")+theme.fg("muted"," to view")));let detachKey=keyLabel("app.tasks.detach"),now=Date.now(),movable=all.filter(task=>ctx.tasks.canDetach(task.id)),waits=movable.map(task=>task.startedAt+1e4-now).filter(wait=>wait>0);detachKey&&movable.length>waits.length&&parts.push(theme.fg("accent",detachKey)+theme.fg("muted"," to run in background")),detachKey&&waits.length>0&&(hintTimer=setTimeout(update,Math.min(...waits)),hintTimer.unref?.()),ctx.ui.setStatus("background",parts.length?parts.join(theme.fg("dim"," \xB7 ")):void 0)};unsubscribe=ctx.tasks.subscribe(update),unsubscribeDetachKey=ctx.ui.onTerminalInput(data=>{if(!getKeybindings().matches(data,"app.tasks.detach"))return;let count;try{count=ctx.tasks.detachForeground()}catch(error){return ctx.ui.notify(error instanceof Error?error.message:String(error),"warning"),{consume:!0}}if(count!==0)return ctx.ui.notify(`Moved ${count} execution${count===1?"":"s"} to the background. Use /tasks to manage tasks.`),{consume:!0}}),update()},dispose=()=>{unsubscribe?.(),unsubscribe=void 0,unsubscribeDetachKey?.(),unsubscribeDetachKey=void 0,clearTimeout(hintTimer),hintTimer=void 0,closeMenu?.(),closeMenu=void 0,ctx.ui.setStatus("background",void 0)};return start(),{dispose,open:async()=>{closeMenu?.(),await ctx.ui.custom((tui,theme2,keybindings,done)=>{let close=()=>{closeMenu===close&&(closeMenu=void 0),done()};return closeMenu=close,new TasksMenu({state:state2,tui,theme:theme2,keybindings,host:ctx.tasks,onClose:close})},{overlay:!0,overlayOptions:{anchor:"center",width:"100%",maxHeight:"100%"}})}}}import*as crypto3 from"node:crypto";import*as fs8 from"node:fs";import*as os7 from"node:os";import*as path13 from"node:path";import{spawn as spawn12}from"child_process";function detectMiss(prev,message,models){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!prev||promptTokens<=0||usage.cacheRead+usage.cacheWrite===0&&!prev.reportedCache)return;let missedTokens=Math.min(prev.promptTokens,promptTokens)-usage.cacheRead;if(missedTokens<=1024)return;let paidTokens=usage.input+usage.cacheWrite,paidPerToken=paidTokens>0?(usage.cost.input+usage.cost.cacheWrite)/paidTokens:0,readPerToken=usage.cacheRead>0?usage.cost.cacheRead/usage.cacheRead:(models.getModel(message.provider,message.model)?.cost.cacheRead??0)/1e6;return{missedTokens,missedCost:missedTokens*Math.max(0,paidPerToken-readPerToken),idleMs:Math.max(0,message.timestamp-prev.timestamp),modelChanged:`${message.provider}/${message.model}`!==prev.modelKey}}function asPreviousRequest(message,reportedCache){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!(promptTokens<=0))return{promptTokens,modelKey:`${message.provider}/${message.model}`,timestamp:message.timestamp,reportedCache:reportedCache||usage.cacheRead+usage.cacheWrite>0}}function scan(entries,models){let prev,totals={missedTokens:0,missedCost:0,missCount:0},misses=new Map;for(let entry of entries){if(entry.type==="compaction"||entry.type==="branch_summary"){prev=void 0;continue}if(entry.type==="usage"&&entry.kind==="cache_warm"){let promptTokens=entry.usage.input+entry.usage.cacheRead+entry.usage.cacheWrite;promptTokens>0&&(prev={promptTokens,modelKey:`${entry.provider}/${entry.model}`,timestamp:Date.parse(entry.timestamp),reportedCache:!0})}else if(entry.type==="message"&&entry.message.role==="assistant"){let miss=detectMiss(prev,entry.message,models);miss&&(totals.missedTokens+=miss.missedTokens,totals.missedCost+=miss.missedCost,totals.missCount+=1,misses.set(entry.message,miss)),prev=asPreviousRequest(entry.message,prev?.reportedCache??!1)??prev}}return{prev,totals,misses}}function computeCacheWaste(entries,models){return scan(entries,models).totals}function collectCacheMisses(entries,models){return scan(entries,models).misses}function detectCacheMiss(entries,message,models){return detectMiss(scan(entries,models).prev,message,models)}import{mkdirSync as mkdirSync14,readFileSync as readFileSync18,rmSync as rmSync4,writeFileSync as writeFileSync12}from"node:fs";import{dirname as dirname23,join as join39}from"node:path";var MAX_CRASH_RECORDS=5,MAX_AGE=10080*60*1e3;function crashLogPath(agentDir=getAgentDir()){return join39(agentDir,"crashes.json")}function readCrashLog(path14=crashLogPath()){try{let records=JSON.parse(readFileSync18(path14,"utf8"));return Array.isArray(records)?records.filter(record=>typeof record=="object"&&record!==null&&typeof record.timestamp=="string"&&typeof record.message=="string"):[]}catch{return[]}}function writeCrashLog(records,path14){mkdirSync14(dirname23(path14),{recursive:!0}),writeFileSync12(path14,`${JSON.stringify(records,null,2)}
|
|
1768
|
+
`;content.addChild(new Markdown(header2+this.skillBlock.content,0,0,this.markdownTheme,{color:text2=>theme.fg("customMessageText",text2)}))}else{let line=theme.fg("customMessageLabel","\x1B[1m[skill]\x1B[22m ")+theme.fg("customMessageText",this.skillBlock.name)+theme.fg("dim",` (${keyText("app.tools.expand")} to expand)`);content.addChild(new Text(line,0,0))}this.addChild(new MouseRegion(content,event=>{if(!(event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}}))}};var THINKING_SELECT_LIST_LAYOUT={minPrimaryColumnWidth:12,maxPrimaryColumnWidth:32},LEVEL_DESCRIPTIONS={off:"No reasoning",minimal:"Very brief reasoning (~1k tokens)",low:"Light reasoning (~2k tokens)",medium:"Moderate reasoning (~8k tokens)",high:"Deep reasoning (~16k tokens)",xhigh:"Extra-high reasoning (~32k tokens)",max:"Maximum reasoning"},ThinkingSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(currentLevel,availableLevels,onSelect,onCancel,onSelectAsDefault,defaultThinkingLevel){super(),this._focused=!1,this.onSelect=onSelect,this.onCancel=onCancel,this.onSelectAsDefault=onSelectAsDefault,this.allItems=availableLevels.map(level=>({value:level,label:`${level===currentLevel?"\u2713 ":" "}${level}`,description:level===defaultThinkingLevel?`${LEVEL_DESCRIPTIONS[level]} \xB7 default`:LEVEL_DESCRIPTIONS[level]})),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text("Thinking Level",0,0)),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyDisplayText("app.thinking.cycle")} cycles thinking levels in-session`,0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.searchInput.onSubmit=()=>this.selectList.handleInput("\r"),this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.selectList=this.buildSelectList(this.allItems,currentLevel),this.selectListChildIndex=this.children.length,this.addChild(this.selectList),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("dim",` ${keyDisplayText("tui.select.confirm")} to select \xB7 ${keyDisplayText("app.thinking.save")} to set as default \xB7 ${keyDisplayText("tui.select.cancel")} to cancel`),0,0)),this.addChild(new DynamicBorder)}buildSelectList(items,preselect){let list2=new SelectList(items,Math.max(1,items.length),getSelectListTheme(),THINKING_SELECT_LIST_LAYOUT),currentIndex=items.findIndex(item=>item.value===preselect);return currentIndex!==-1&&list2.setSelectedIndex(currentIndex),list2.onSelect=item=>this.onSelect(item.value),list2.onCancel=()=>this.onCancel(),list2}applyFilter(query){let filtered=query?fuzzyFilter(this.allItems,query,item=>`${item.value} ${item.description??""}`):this.allItems,selectedValue=this.selectList.getSelectedItem()?.value,newList=this.buildSelectList(filtered,selectedValue);this.children[this.selectListChildIndex]=newList,this.selectList=newList}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.thinking.save")&&this.onSelectAsDefault){let item=this.selectList.getSelectedItem();item&&this.onSelectAsDefault(item.value);return}if(kb.matches(keyData,"tui.select.up")||kb.matches(keyData,"tui.select.down")||kb.matches(keyData,"tui.select.confirm")||kb.matches(keyData,"tui.select.cancel")){this.selectList.handleInput(keyData);return}this.searchInput.handleInput(keyData),this.applyFilter(this.searchInput.getValue())}getSelectList(){return this.selectList}};var FALLBACK_PREVIEW_LINES=10,DEFAULT_TOOL_ROW_GAP={afterTool:1,afterMultilineTool:1,afterOther:1},ToolExecutionComponent=class extends Container{constructor(toolName,toolCallId,args,options={},toolDefinition,ui,cwd){super(),this.leadingGap=1,this.selfRenderOffset=1,this.selfRenderHeight=0,this.rendererState={},this.imageComponents=[],this.imageSources=[],this.imageSpacers=[],this.expanded=!1,this.isPartial=!0,this.executionStarted=!1,this.argsComplete=!1,this.hideComponent=!1,this.disposed=!1,this.toolName=toolName,this.toolCallId=toolCallId,this.args=args,this.toolDefinition=toolDefinition,this.showImages=options.showImages??!0,this.imageWidthCells=options.imageWidthCells??60,this.outputPad=options.outputPad??1,this.ui=ui,this.cwd=cwd,this.gap=new Spacer(this.leadingGap),this.addChild(this.gap),this.contentBox=new Box(1,1,text2=>theme.bg("toolPendingBg",text2)),this.contentText=new Text("",1,1,text2=>theme.bg("toolPendingBg",text2)),this.contentTextRegion=this.createResultRegion(this.contentText),this.selfRenderContainer=new Container,this.hasRendererDefinition()?this.addChild(this.getRenderShell()==="self"?this.selfRenderContainer:this.contentBox):this.addChild(this.contentTextRegion),this.updateDisplay()}getShell(){if(this.toolDefinition?.renderShell!=="self")return this.toolDefinition?.shell}getCallRenderer(){return this.toolDefinition?.renderCall??this.getShell()?.renderCall}getResultRenderer(){return this.toolDefinition?.renderResult??this.getShell()?.renderResult}hasRendererDefinition(){return this.toolDefinition!==void 0}getRenderShell(){return this.toolDefinition?.renderShell==="self"||this.getShell()?"self":"default"}setLeadingGap(lines){this.leadingGap=Math.max(0,Math.floor(lines)),this.gap.setLines(this.leadingGap)}getToolRowGap(){return this.getShell()?.gap??DEFAULT_TOOL_ROW_GAP}getRenderContext(lastComponent){return{args:this.args,toolCallId:this.toolCallId,invalidate:()=>{this.disposed||(this.invalidate(),this.ui.requestRender())},lastComponent,state:this.rendererState,cwd:this.cwd,executionStarted:this.executionStarted,argsComplete:this.argsComplete,isPartial:this.isPartial,expanded:this.expanded,showImages:this.showImages,isError:this.result?.isError??!1,durationMs:this.isPartial?void 0:this.result?.durationMs,outputPad:this.outputPad,result:this.result?{content:this.result.content,details:this.result.details}:void 0}}frame(component,kind,lastComponent){let shell=this.getShell();return shell?shell.frame(component,kind,this.getRenderContext(lastComponent)):component}createCallFallback(){let shell=this.getShell();return shell?.renderCall?shell.renderCall(this.args,theme,this.getRenderContext(this.callRendererComponent)):new Text(formatToolCallWithArgs(this.toolName,this.args,theme,this.expanded),0,0)}createResultFallback(){let shell=this.getShell();if(shell?.renderResult&&this.result)return shell.renderResult({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));let output=this.getTextOutput();if(!output)return;let lines=output.split(`
|
|
1769
|
+
`),displayLines=this.expanded?lines:lines.slice(0,FALLBACK_PREVIEW_LINES),remaining=lines.length-displayLines.length,text2=displayLines.map(line=>theme.fg("toolOutput",line)).join(`
|
|
1770
|
+
`);return remaining>0&&(text2+=`${theme.fg("muted",`
|
|
1771
|
+
... (${remaining} more lines,`)} ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`),new Text(text2,0,0)}hidesCollapsedResult(){return this.getShell()?.shouldHideResult?.(this.getRenderContext(this.resultRendererComponent))??!1}createResultRegion(component){return new MouseRegion(component,event=>{if(!(!this.result||event.type!=="click"||event.button!=="left"))return this.setExpanded(!this.expanded),{handled:!0}})}updateArgs(args){this.args=args,this.updateDisplay()}markExecutionStarted(){this.disposed||(this.executionStarted=!0,this.updateDisplay(),this.ui.requestRender())}setArgsComplete(){this.argsComplete=!0,this.updateDisplay(),this.ui.requestRender()}updateResult(result2,isPartial=!1){this.result=result2,this.isPartial=isPartial,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}setOutputPad(outputPad){this.outputPad=outputPad,this.updateDisplay()}setShowImages(show){this.showImages=show,this.updateDisplay()}setImageWidthCells(width){this.imageWidthCells=Math.max(1,Math.floor(width)),this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}render(width){if(this.hideComponent)return[];if(this.hasRendererDefinition()&&this.getRenderShell()==="self"){let contentLines=this.selfRenderContainer.render(width);this.selfRenderHeight=contentLines.length;let leadingLines=contentLines.length>0?this.gap.render(width):[];if(this.selfRenderOffset=leadingLines.length,contentLines.length===0&&this.imageComponents.length===0)return[];let lines=[...leadingLines,...contentLines];for(let i=0;i<this.imageComponents.length;i++){let spacer=this.imageSpacers[i];spacer&&lines.push(...spacer.render(width));let imageComponent=this.imageComponents[i];imageComponent&&lines.push(...imageComponent.render(width))}return lines}return super.render(width)}handleMouse(event){if(!this.hasRendererDefinition()||this.getRenderShell()!=="self")return super.handleMouse(event);if(!(event.y<this.selfRenderOffset||event.y>=this.selfRenderOffset+this.selfRenderHeight))return this.selfRenderContainer.handleMouse({...event,y:event.y-this.selfRenderOffset,height:this.selfRenderHeight})}updateDisplay(){let bgFn=this.isPartial?text2=>theme.bg("toolPendingBg",text2):this.result?.isError?text2=>theme.bg("toolErrorBg",text2):text2=>theme.bg("toolSuccessBg",text2),hasContent=!1;if(this.hideComponent=!1,this.hasRendererDefinition()){let renderContainer=this.getRenderShell()==="self"?this.selfRenderContainer:this.contentBox;renderContainer instanceof Box&&(renderContainer.setBgFn(bgFn),renderContainer.setPaddingX(this.outputPad)),renderContainer.clear();let addCall=component=>{renderContainer.addChild(this.createResultRegion(this.frame(component,"header",this.callRendererComponent))),hasContent=!0},addResult=component=>{renderContainer.addChild(this.createResultRegion(this.frame(component,"body",this.resultRendererComponent))),hasContent=!0},callRenderer=this.getCallRenderer();if(!callRenderer)addCall(this.createCallFallback());else try{let component=callRenderer(this.args,theme,this.getRenderContext(this.callRendererComponent));this.callRendererComponent=component,addCall(component)}catch{this.callRendererComponent=void 0,addCall(this.createCallFallback())}if(this.result&&!this.hidesCollapsedResult()){let resultRenderer=this.getResultRenderer();if(resultRenderer)try{let component=resultRenderer({content:this.result.content,details:this.result.details},{expanded:this.expanded,isPartial:this.isPartial},theme,this.getRenderContext(this.resultRendererComponent));this.resultRendererComponent=component,addResult(component)}catch{this.resultRendererComponent=void 0;let component=this.createResultFallback();component&&addResult(component)}else{let component=this.createResultFallback();component&&addResult(component)}}}else this.contentText.setCustomBgFn(bgFn),this.contentText.setPaddingX(this.outputPad),this.contentText.setText(this.formatToolExecution()),hasContent=!0;let previousImages=this.imageComponents,previousSources=this.imageSources;for(let img of this.imageComponents)this.removeChild(img);this.imageComponents=[],this.imageSources=[];for(let spacer of this.imageSpacers)this.removeChild(spacer);if(this.imageSpacers=[],this.result){let imageBlocks=this.result.content.filter(c=>c.type==="image"),caps=getCapabilities();for(let img of imageBlocks)if(caps.images&&this.showImages&&img.data&&img.mimeType){let spacer=new Spacer(1);this.addChild(spacer),this.imageSpacers.push(spacer);let source={data:img.data,mimeType:img.mimeType,widthCells:this.imageWidthCells},index3=this.imageComponents.length,previous=previousSources[index3],imageComponent=previous?.data===source.data&&previous.mimeType===source.mimeType&&previous.widthCells===source.widthCells?previousImages[index3]:new Image(source.data,source.mimeType,{fallbackColor:s=>theme.fg("toolOutput",s)},{maxWidthCells:source.widthCells});source.mimeType!=="image/png"&&ensurePngTranscoder(()=>{this.disposed||(this.invalidate(),this.ui.requestRender())}),this.imageComponents.push(imageComponent),this.imageSources.push(source),this.addChild(imageComponent)}}this.hasRendererDefinition()&&!hasContent&&this.imageComponents.length===0&&(this.hideComponent=!0)}getTextOutput(){return getTextOutput(this.result,this.showImages)}formatToolExecution(){let text2=theme.fg("toolTitle",theme.bold(this.toolName)),content=JSON.stringify(this.args,null,2);content&&(text2+=`
|
|
1772
|
+
|
|
1773
|
+
${content}`);let output=this.getTextOutput();return output&&(text2+=`
|
|
1774
|
+
${output}`),text2}dispose(){this.disposed||(this.disposed=!0,this.rendererState.dispose?.())}};var TREE_GUTTER_WIDTH=2,MIN_VISIBLE_ANCHOR_CONTENT_WIDTH=4,MAX_VISIBLE_ANCHOR_CONTENT_WIDTH=20,MIN_ANCHOR_CONTEXT_WIDTH=2,MAX_ANCHOR_CONTEXT_WIDTH=12;function renderHorizontalViewport(rows,width){let viewportWidth=Math.max(0,width-TREE_GUTTER_WIDTH),maxBodyWidth=rows.reduce((max,row)=>Math.max(max,row.bodyWidth),0),maxHorizontalScroll=Math.max(0,maxBodyWidth-viewportWidth),selectedRow=rows.find(row=>row.isSelected),horizontalScroll=0;if(selectedRow&&maxHorizontalScroll>0){let minVisibleAnchorContentWidth=Math.min(MAX_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.max(MIN_VISIBLE_ANCHOR_CONTENT_WIDTH,Math.floor(viewportWidth/3)));if(selectedRow.anchorCol>viewportWidth-minVisibleAnchorContentWidth){let anchorContextWidth=Math.min(MAX_ANCHOR_CONTEXT_WIDTH,Math.max(MIN_ANCHOR_CONTEXT_WIDTH,Math.floor(viewportWidth/4)));horizontalScroll=Math.min(maxHorizontalScroll,selectedRow.anchorCol-anchorContextWidth)}}return rows.map(row=>{let line=horizontalScroll>0?`${row.gutter}${sliceByColumn(row.body,horizontalScroll,viewportWidth,!0)}\x1B[0m`:row.gutter+row.body;return truncateToWidth(line,width,"")})}var TreeList=class{constructor(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode){this.flatNodes=[],this.filteredNodes=[],this.selectedIndex=0,this.filterMode="default",this.searchQuery="",this.toolCallMap=new Map,this.multipleRoots=!1,this.showLabelTimestamps=!1,this.activePathIds=new Set,this.visibleParentMap=new Map,this.visibleChildrenMap=new Map,this.lastSelectedId=null,this.foldedNodes=new Set,this.currentLeafId=currentLeafId,this.maxVisibleLines=maxVisibleLines,this.filterMode=initialFilterMode??"default",this.multipleRoots=tree.length>1,this.flatNodes=this.flattenTree(tree),this.buildActivePath(),this.applyFilter();let targetId=initialSelectedId??currentLeafId;this.selectedIndex=this.findNearestVisibleIndex(targetId),this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??null}findNearestVisibleIndex(entryId){if(this.filteredNodes.length===0)return 0;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let visibleIdToIndex=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=entryId;for(;currentId!==null;){let index3=visibleIdToIndex.get(currentId);if(index3!==void 0)return index3;let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}return this.filteredNodes.length-1}buildActivePath(){if(this.activePathIds.clear(),!this.currentLeafId)return;let entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let currentId=this.currentLeafId;for(;currentId;){this.activePathIds.add(currentId);let node=entryMap.get(currentId);if(!node)break;currentId=node.node.entry.parentId??null}}flattenTree(roots){let result2=[];this.toolCallMap.clear();let stack=[],containsActive=new Map,leafId=this.currentLeafId;{let allNodes=[],preOrderStack=[...roots];for(;preOrderStack.length>0;){let node=preOrderStack.pop();allNodes.push(node);for(let i=node.children.length-1;i>=0;i--)preOrderStack.push(node.children[i])}for(let i=allNodes.length-1;i>=0;i--){let node=allNodes[i],has=leafId!==null&&node.entry.id===leafId;for(let child of node.children)containsActive.get(child)&&(has=!0);containsActive.set(node,has)}}let multipleRoots=roots.length>1,orderedRoots=[...roots].sort((a,b2)=>Number(containsActive.get(b2))-Number(containsActive.get(a)));for(let i=orderedRoots.length-1;i>=0;i--){let isLast=i===orderedRoots.length-1;stack.push([orderedRoots[i],multipleRoots?1:0,multipleRoots,multipleRoots,isLast,[],multipleRoots])}for(;stack.length>0;){let[node,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),entry=node.entry;if(entry.type==="message"&&entry.message.role==="assistant"){let content=entry.message.content;if(Array.isArray(content)){for(let block of content)if(typeof block=="object"&&block!==null&&"type"in block&&block.type==="toolCall"){let tc=block;this.toolCallMap.set(tc.id,{name:tc.name,arguments:tc.arguments})}}}result2.push({node,indent,showConnector,isLast,gutters,isVirtualRootChild});let children=node.children,multipleChildren=children.length>1,orderedChildren=(()=>{let prioritized=[],rest=[];for(let child of children)containsActive.get(child)?prioritized.push(child):rest.push(child);return[...prioritized,...rest]})(),childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=orderedChildren.length-1;i>=0;i--){let childIsLast=i===orderedChildren.length-1;stack.push([orderedChildren[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}return result2}applyFilter(){this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId);let searchTokens=this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);if(this.filteredNodes=this.flatNodes.filter(flatNode=>{let entry=flatNode.node.entry;if(entry.type==="usage")return!1;let isCurrentLeaf=entry.id===this.currentLeafId;if(entry.type==="message"&&entry.message.role==="assistant"&&!isCurrentLeaf){let msg=entry.message,hasText=this.hasTextContent(msg.content),isErrorOrAborted=msg.stopReason&&msg.stopReason!=="stop"&&msg.stopReason!=="toolUse";if(!hasText&&!isErrorOrAborted)return!1}let passesFilter=!0,isSettingsEntry=entry.type==="label"||entry.type==="context_edit"||entry.type==="custom"||entry.type==="model_change"||entry.type==="thinking_level_change"||entry.type==="session_info";switch(this.filterMode){case"user-only":passesFilter=entry.type==="message"&&entry.message.role==="user";break;case"no-tools":passesFilter=!isSettingsEntry&&!(entry.type==="message"&&entry.message.role==="toolResult");break;case"labeled-only":passesFilter=flatNode.node.label!==void 0;break;case"all":passesFilter=!0;break;default:passesFilter=!isSettingsEntry;break}if(!passesFilter)return!1;if(searchTokens.length>0){let nodeText=this.getSearchableText(flatNode.node).toLowerCase();return searchTokens.every(token=>nodeText.includes(token))}return!0}),this.foldedNodes.size>0){let skipSet=new Set;for(let flatNode of this.flatNodes){let{id,parentId}=flatNode.node.entry;parentId!=null&&(this.foldedNodes.has(parentId)||skipSet.has(parentId))&&skipSet.add(id)}this.filteredNodes=this.filteredNodes.filter(flatNode=>!skipSet.has(flatNode.node.entry.id))}this.recalculateVisualStructure(),this.lastSelectedId?this.selectedIndex=this.findNearestVisibleIndex(this.lastSelectedId):this.selectedIndex>=this.filteredNodes.length&&(this.selectedIndex=Math.max(0,this.filteredNodes.length-1)),this.filteredNodes.length>0&&(this.lastSelectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id??this.lastSelectedId)}recalculateVisualStructure(){if(this.filteredNodes.length===0)return;let visibleIds=new Set(this.filteredNodes.map(n=>n.node.entry.id)),entryMap=new Map;for(let flatNode of this.flatNodes)entryMap.set(flatNode.node.entry.id,flatNode);let findVisibleAncestor=nodeId=>{let currentId=entryMap.get(nodeId)?.node.entry.parentId??null;for(;currentId!==null;){if(visibleIds.has(currentId))return currentId;currentId=entryMap.get(currentId)?.node.entry.parentId??null}return null},visibleParent=new Map,visibleChildren=new Map;visibleChildren.set(null,[]);for(let flatNode of this.filteredNodes){let nodeId=flatNode.node.entry.id,ancestorId=findVisibleAncestor(nodeId);visibleParent.set(nodeId,ancestorId),visibleChildren.has(ancestorId)||visibleChildren.set(ancestorId,[]),visibleChildren.get(ancestorId).push(nodeId)}let visibleRootIds=visibleChildren.get(null);this.multipleRoots=visibleRootIds.length>1;let filteredNodeMap=new Map;for(let flatNode of this.filteredNodes)filteredNodeMap.set(flatNode.node.entry.id,flatNode);let stack=[];for(let i=visibleRootIds.length-1;i>=0;i--){let isLast=i===visibleRootIds.length-1;stack.push([visibleRootIds[i],this.multipleRoots?1:0,this.multipleRoots,this.multipleRoots,isLast,[],this.multipleRoots])}for(;stack.length>0;){let[nodeId,indent,justBranched,showConnector,isLast,gutters,isVirtualRootChild]=stack.pop(),flatNode=filteredNodeMap.get(nodeId);if(!flatNode)continue;flatNode.indent=indent,flatNode.showConnector=showConnector,flatNode.isLast=isLast,flatNode.gutters=gutters,flatNode.isVirtualRootChild=isVirtualRootChild;let children=visibleChildren.get(nodeId)||[],multipleChildren=children.length>1,childIndent;multipleChildren||justBranched&&indent>0?childIndent=indent+1:childIndent=indent;let connectorDisplayed=showConnector&&!isVirtualRootChild,currentDisplayIndent=this.multipleRoots?Math.max(0,indent-1):indent,connectorPosition=Math.max(0,currentDisplayIndent-1),childGutters=connectorDisplayed?[...gutters,{position:connectorPosition,show:!isLast}]:gutters;for(let i=children.length-1;i>=0;i--){let childIsLast=i===children.length-1;stack.push([children[i],childIndent,multipleChildren,multipleChildren,childIsLast,childGutters,!1])}}this.visibleParentMap=visibleParent,this.visibleChildrenMap=visibleChildren}getSearchableText(node){let entry=node.entry,parts=[];switch(node.label&&parts.push(node.label),entry.type){case"message":{let msg=entry.message;if(parts.push(msg.role),"content"in msg&&msg.content&&parts.push(this.extractContent(msg.content)),msg.role==="bashExecution"){let bashMsg=msg;bashMsg.command&&parts.push(bashMsg.command)}break}case"custom_message":{parts.push(entry.customType),typeof entry.content=="string"?parts.push(entry.content):parts.push(this.extractContent(entry.content));break}case"compaction":parts.push("compaction");break;case"branch_summary":parts.push("branch summary",entry.summary);break;case"session_info":parts.push("title"),entry.name&&parts.push(entry.name);break;case"model_change":parts.push("model",entry.modelId);break;case"thinking_level_change":parts.push("thinking",entry.thinkingLevel);break;case"custom":parts.push("custom",entry.customType);break;case"context_edit":parts.push("context edit",entry.replacement===null?"omit":"replace",entry.targetId);break;case"label":parts.push("label",entry.label??"");break}return parts.join(" ")}invalidate(){}getSearchQuery(){return this.searchQuery}getSelectedNode(){return this.filteredNodes[this.selectedIndex]?.node}copySelected(){let node=this.getSelectedNode();this.onCopy?.(node?this.getEntryCopyText(node):void 0)}updateNodeLabel(entryId,label,labelTimestamp){for(let flatNode of this.flatNodes)if(flatNode.node.entry.id===entryId){flatNode.node.label=label,flatNode.node.labelTimestamp=label?labelTimestamp??new Date().toISOString():void 0;break}}getStatusLabels(){let labels="";switch(this.filterMode){case"no-tools":labels+=" [no-tools]";break;case"user-only":labels+=" [user]";break;case"labeled-only":labels+=" [labeled]";break;case"all":labels+=" [all]";break}return this.showLabelTimestamps&&(labels+=" [+label time]"),labels}render(width){let lines=[];if(this.filteredNodes.length===0)return lines.push(truncateToWidth(theme.fg("muted"," No entries found"),width)),lines.push(truncateToWidth(theme.fg("muted",` (0/0)${this.getStatusLabels()}`),width)),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisibleLines/2),this.filteredNodes.length-this.maxVisibleLines)),endIndex=Math.min(startIndex+this.maxVisibleLines,this.filteredNodes.length),renderedRows=[];for(let i=startIndex;i<endIndex;i++){let flatNode=this.filteredNodes[i],entry=flatNode.node.entry,isSelected2=i===this.selectedIndex,cursor=isSelected2?theme.fg("accent","\u203A "):" ",displayIndent=this.multipleRoots?Math.max(0,flatNode.indent-1):flatNode.indent,connector=flatNode.showConnector&&!flatNode.isVirtualRootChild?flatNode.isLast?"\u2514\u2500 ":"\u251C\u2500 ":"",connectorPosition=connector?displayIndent-1:-1,totalChars=displayIndent*3,prefixChars=[],isFolded=this.foldedNodes.has(entry.id);for(let i2=0;i2<totalChars;i2++){let level=Math.floor(i2/3),posInLevel=i2%3,gutter2=flatNode.gutters.find(g=>g.position===level);if(gutter2)posInLevel===0?prefixChars.push(gutter2.show?"\u2502":" "):prefixChars.push(" ");else if(connector&&level===connectorPosition)if(posInLevel===0)prefixChars.push(flatNode.isLast?"\u2514":"\u251C");else if(posInLevel===1){let foldable=this.isFoldable(entry.id);prefixChars.push(isFolded?"\u229E":foldable?"\u229F":"\u2500")}else prefixChars.push(" ");else prefixChars.push(" ")}let prefix=prefixChars.join(""),showsFoldInConnector=flatNode.showConnector&&!flatNode.isVirtualRootChild,foldMarker=isFolded&&!showsFoldInConnector?theme.fg("accent","\u229E "):"",pathMarker=this.activePathIds.has(entry.id)?theme.fg("accent","\u2022 "):"",label=flatNode.node.label?theme.fg("warning",`[${flatNode.node.label}] `):"",labelTimestamp=this.showLabelTimestamps&&flatNode.node.label&&flatNode.node.labelTimestamp?theme.fg("muted",`${this.formatLabelTimestamp(flatNode.node.labelTimestamp)} `):"",content=this.getEntryDisplayText(flatNode.node,isSelected2),prefixPart=theme.fg("dim",prefix)+foldMarker+pathMarker,anchorCol=visibleWidth(prefixPart),gutter=cursor,body2=prefixPart+label+labelTimestamp+content;isSelected2&&(gutter=theme.bg("selectedBg",gutter),body2=theme.bg("selectedBg",body2)),renderedRows.push({gutter,body:body2,anchorCol,bodyWidth:visibleWidth(body2),isSelected:isSelected2})}return lines.push(...renderHorizontalViewport(renderedRows,width)),lines.push(truncateToWidth(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredNodes.length})${this.getStatusLabels()}`),width)),lines}getEntryDisplayText(node,isSelected2){let entry=node.entry,result2,normalize2=s=>s.replace(/[\n\t]/g," ").trim();switch(entry.type){case"message":{let msg=entry.message,role=msg.role;if(role==="user"){let msgWithContent=msg,content=normalize2(this.extractContent(msgWithContent.content));result2=theme.fg("accent","user: ")+content}else if(role==="assistant"){let msgWithContent=msg,textContent=normalize2(this.extractContent(msgWithContent.content));if(textContent)result2=theme.fg("success","assistant: ")+textContent;else if(msgWithContent.stopReason==="aborted")result2=theme.fg("success","assistant: ")+theme.fg("muted","(aborted)");else if(msgWithContent.errorMessage){let errMsg=normalize2(msgWithContent.errorMessage).slice(0,80);result2=theme.fg("success","assistant: ")+theme.fg("error",errMsg)}else result2=theme.fg("success","assistant: ")+theme.fg("muted","(no content)")}else if(role==="toolResult"){let toolMsg=msg,toolCall=toolMsg.toolCallId?this.toolCallMap.get(toolMsg.toolCallId):void 0;toolCall?result2=theme.fg("muted",this.formatToolCall(toolCall.name,toolCall.arguments)):result2=theme.fg("muted",`[${toolMsg.toolName??"tool"}]`)}else if(role==="bashExecution"){let bashMsg=msg;result2=theme.fg("dim",`[bash]: ${normalize2(bashMsg.command??"")}`)}else result2=theme.fg("dim",`[${role}]`);break}case"custom_message":{let content=typeof entry.content=="string"?entry.content:entry.content.filter(c=>c.type==="text").map(c=>c.text).join("");result2=theme.fg("customMessageLabel",`[${entry.customType}]: `)+normalize2(content);break}case"compaction":{let tokens2=Math.round(entry.tokensBefore/1e3);result2=theme.fg("borderAccent",`[compaction: ${tokens2}k tokens]`);break}case"branch_summary":result2=theme.fg("warning","[branch summary]: ")+normalize2(entry.summary);break;case"model_change":result2=theme.fg("dim",`[model: ${entry.modelId}]`);break;case"thinking_level_change":result2=theme.fg("dim",`[thinking: ${entry.thinkingLevel}]`);break;case"custom":result2=theme.fg("dim",`[custom: ${entry.customType}]`);break;case"context_edit":result2=theme.fg("dim",`[context ${entry.replacement===null?"omit":"replace"}: ${entry.targetId}]`);break;case"label":result2=theme.fg("dim",`[label: ${entry.label??"(cleared)"}]`);break;case"session_info":result2=entry.name?[theme.fg("dim","[title: "),theme.fg("dim",entry.name),theme.fg("dim","]")].join(""):[theme.fg("dim","[title: "),theme.italic(theme.fg("dim","empty")),theme.fg("dim","]")].join("");break;default:result2=""}return isSelected2?theme.bold(result2):result2}formatLabelTimestamp(timestamp){let date=new Date(timestamp),now=new Date,hours=date.getHours().toString().padStart(2,"0"),minutes=date.getMinutes().toString().padStart(2,"0"),time2=`${hours}:${minutes}`;if(date.getFullYear()===now.getFullYear()&&date.getMonth()===now.getMonth()&&date.getDate()===now.getDate())return time2;let month=date.getMonth()+1,day=date.getDate();return date.getFullYear()===now.getFullYear()?`${month}/${day} ${time2}`:`${date.getFullYear().toString().slice(-2)}/${month}/${day} ${time2}`}extractContent(content){return this.extractFullContent(content).slice(0,200)}extractFullContent(content){if(typeof content=="string")return content;if(!Array.isArray(content))return"";let result2="";for(let block of content)typeof block=="object"&&block!==null&&"type"in block&&block.type==="text"&&(result2+=block.text);return result2}getEntryCopyText(node){let entry=node.entry,text2;switch(entry.type){case"message":entry.message.role==="bashExecution"?text2=entry.message.command:"content"in entry.message&&(text2=this.extractFullContent(entry.message.content),!text2&&entry.message.role==="assistant"&&(text2=entry.message.errorMessage));break;case"custom_message":text2=this.extractFullContent(entry.content);break;case"compaction":text2=entry.summary;break;case"branch_summary":text2=entry.summary;break}return text2?.trim()?text2:void 0}hasTextContent(content){if(typeof content=="string")return content.trim().length>0;if(Array.isArray(content)){for(let c of content)if(typeof c=="object"&&c!==null&&"type"in c&&c.type==="text"){let text2=c.text;if(text2&&text2.trim().length>0)return!0}}return!1}formatToolCall(name,args){let shortenPath3=p=>{let home=process.env.HOME||process.env.USERPROFILE||"";return home&&p.startsWith(home)?`~${p.slice(home.length)}`:p};switch(name){case"read":return`[read: ${shortenPath3(String(args.path||args.file_path||""))}${formatReadLineRange(args.offset,args.limit)}]`;case"write":return`[write: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"edit":return`[edit: ${shortenPath3(String(args.path||args.file_path||""))}]`;case"bash":{let rawCmd=String(args.command||"");return`[bash: ${rawCmd.replace(/[\n\t]/g," ").trim().slice(0,50)}${rawCmd.length>50?"...":""}]`}case"grep":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[grep: /${pattern}/ in ${path14}]`}case"find":{let pattern=String(args.pattern||""),path14=shortenPath3(String(args.path||"."));return`[find: ${pattern} in ${path14}]`}case"ls":return`[ls: ${shortenPath3(String(args.path||"."))}]`;default:{let argsStr=JSON.stringify(args).slice(0,40);return`[${name}: ${argsStr}${JSON.stringify(args).length>40?"...":""}]`}}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.filteredNodes.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.filteredNodes.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"app.tree.foldOrUp")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.isFoldable(currentId)&&!this.foldedNodes.has(currentId)?(this.foldedNodes.add(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("up")}else if(kb.matches(keyData,"app.tree.unfoldOrDown")){let currentId=this.filteredNodes[this.selectedIndex]?.node.entry.id;currentId&&this.foldedNodes.has(currentId)?(this.foldedNodes.delete(currentId),this.applyFilter()):this.selectedIndex=this.findBranchSegmentStart("down")}else if(kb.matches(keyData,"tui.editor.cursorLeft")||kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisibleLines);else if(kb.matches(keyData,"tui.editor.cursorRight")||kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredNodes.length-1,this.selectedIndex+this.maxVisibleLines);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.node.entry.id)}else if(kb.matches(keyData,"app.message.copy"))this.copySelected();else if(kb.matches(keyData,"tui.select.cancel"))this.searchQuery?(this.searchQuery="",this.foldedNodes.clear(),this.applyFilter()):this.onCancel?.();else if(kb.matches(keyData,"app.tree.filter.default"))this.filterMode="default",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.noTools"))this.filterMode=this.filterMode==="no-tools"?"default":"no-tools",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.userOnly"))this.filterMode=this.filterMode==="user-only"?"default":"user-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.labeledOnly"))this.filterMode=this.filterMode==="labeled-only"?"default":"labeled-only",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.all"))this.filterMode=this.filterMode==="all"?"default":"all",this.foldedNodes.clear(),this.applyFilter();else if(kb.matches(keyData,"app.tree.filter.cycleBackward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex-1+modes.length)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"app.tree.filter.cycleForward")){let modes=["default","no-tools","user-only","labeled-only","all"],currentIndex=modes.indexOf(this.filterMode);this.filterMode=modes[(currentIndex+1)%modes.length],this.foldedNodes.clear(),this.applyFilter()}else if(kb.matches(keyData,"tui.editor.deleteCharBackward"))this.searchQuery.length>0&&(this.searchQuery=this.searchQuery.slice(0,-1),this.foldedNodes.clear(),this.applyFilter());else if(kb.matches(keyData,"app.tree.editLabel")){let selected=this.filteredNodes[this.selectedIndex];selected&&this.onLabelEdit&&this.onLabelEdit(selected.node.entry.id,selected.node.label)}else kb.matches(keyData,"app.tree.toggleLabelTimestamp")?this.showLabelTimestamps=!this.showLabelTimestamps:![...keyData].some(ch=>{let code=ch.charCodeAt(0);return code<32||code===127||code>=128&&code<=159})&&keyData.length>0&&(this.searchQuery+=keyData,this.foldedNodes.clear(),this.applyFilter())}isFoldable(entryId){let children=this.visibleChildrenMap.get(entryId);if(!children||children.length===0)return!1;let parentId=this.visibleParentMap.get(entryId);if(parentId==null)return!0;let siblings=this.visibleChildrenMap.get(parentId);return siblings!==void 0&&siblings.length>1}findBranchSegmentStart(direction){let selectedId=this.filteredNodes[this.selectedIndex]?.node.entry.id;if(!selectedId)return this.selectedIndex;let indexByEntryId=new Map(this.filteredNodes.map((node,i)=>[node.node.entry.id,i])),currentId=selectedId;if(direction==="down")for(;;){let children=this.visibleChildrenMap.get(currentId)??[];if(children.length===0)return indexByEntryId.get(currentId);if(children.length>1)return indexByEntryId.get(children[0]);currentId=children[0]}for(;;){let parentId=this.visibleParentMap.get(currentId)??null;if(parentId===null)return indexByEntryId.get(currentId);if((this.visibleChildrenMap.get(parentId)??[]).length>1){let segmentStart=indexByEntryId.get(currentId);if(segmentStart<this.selectedIndex)return segmentStart}currentId=parentId}}},SearchLine=class{constructor(treeList){this.treeList=treeList}invalidate(){}render(width){let query=this.treeList.getSearchQuery();return query?[truncateToWidth(` ${theme.fg("muted","Type to search:")} ${theme.fg("accent",query)}`,width)]:[truncateToWidth(` ${theme.fg("muted","Type to search:")}`,width)]}handleInput(_keyData){}},TreeHelp=class{invalidate(){}render(width){let items=TREE_HELP_ITEMS.map(({keys,label,labelFirst})=>{let text2=formatHelpKeys(keys);return text2?labelFirst?`${label} ${text2}`:`${text2} ${label}`:label}),availableWidth=Math.max(1,width),indent=" ",separator=" \xB7 ",lines=[],currentLine="";for(let item of items){let candidate=currentLine?`${currentLine}${separator}${item}`:visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item;if(!currentLine||visibleWidth(candidate)<=availableWidth){currentLine=candidate;continue}lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),currentLine=visibleWidth(`${indent}${item}`)<=availableWidth?`${indent}${item}`:item}return currentLine&&lines.push(...wrapTextWithAnsi(currentLine.trimEnd(),availableWidth)),lines.map(line=>theme.fg("muted",line))}},TREE_HELP_ITEMS=[{keys:["tui.select.up","tui.select.down"],label:"move"},{keys:["tui.editor.cursorLeft","tui.editor.cursorRight"],label:"page"},{keys:["app.tree.foldOrUp","app.tree.unfoldOrDown"],label:"branch"},{keys:["app.message.copy"],label:"copy"},{keys:["app.tree.editLabel"],label:"label"},{keys:["app.tree.toggleLabelTimestamp"],label:"label time"},{keys:["app.tree.filter.default","app.tree.filter.noTools","app.tree.filter.userOnly","app.tree.filter.labeledOnly","app.tree.filter.all"],label:"filters",labelFirst:!0},{keys:["app.tree.filter.cycleForward","app.tree.filter.cycleBackward"],label:"cycle",labelFirst:!0}];function formatHelpKeys(keybindings){let keys=[];for(let keybinding of keybindings){let key=getKeybindings().getKeys(keybinding)[0];key!==void 0&&keys.push(key)}return keys.length===0?"":formatKeyText(compactRawKeys(keys)).replace(/\bpageUp\b/g,"pgup").replace(/\bpageDown\b/g,"pgdn").replace(/\bup\b/g,"\u2191").replace(/\bdown\b/g,"\u2193").replace(/\bleft\b/g,"\u2190").replace(/\bright\b/g,"\u2192")}function compactRawKeys(keys){if(keys.length===1)return keys[0];let parts=keys.map(key=>{let separatorIndex=key.lastIndexOf("+");return separatorIndex===-1?{prefix:"",suffix:key}:{prefix:key.slice(0,separatorIndex+1),suffix:key.slice(separatorIndex+1)}}),prefix=parts[0].prefix;return prefix&&parts.every(part=>part.prefix===prefix)?`${prefix}${parts.map(part=>part.suffix).join("/")}`:keys.join("/")}var LabelInput=class{get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(entryId,currentLabel){this._focused=!1,this.entryId=entryId,this.input=new Input,currentLabel&&this.input.setValue(currentLabel)}invalidate(){}render(width){let lines=[],availableWidth=width-2;return lines.push(truncateToWidth(` ${theme.fg("muted","Label (empty to remove):")}`,width)),lines.push(...this.input.render(availableWidth).map(line=>truncateToWidth(` ${line}`,width))),lines.push(truncateToWidth(` ${keyHint("tui.select.confirm","save")} ${keyHint("tui.select.cancel","cancel")}`,width)),lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.confirm")){let value=this.input.getValue().trim();this.onSubmit?.(this.entryId,value||void 0)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel?.():this.input.handleInput(keyData)}},TreeSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.labelInput&&(this.labelInput.focused=value)}constructor(tree,currentLeafId,terminalHeight,onSelect,onCancel,onLabelChange,initialSelectedId,initialFilterMode){super(),this.labelInput=null,this._focused=!1,this.onLabelChangeCallback=onLabelChange;let maxVisibleLines=Math.max(5,Math.floor(terminalHeight/2));this.treeList=new TreeList(tree,currentLeafId,maxVisibleLines,initialSelectedId,initialFilterMode),this.treeList.onSelect=onSelect,this.treeList.onCancel=onCancel,this.treeList.onCopy=text2=>this.onCopy?.(text2),this.treeList.onLabelEdit=(entryId,currentLabel)=>this.showLabelInput(entryId,currentLabel),this.treeContainer=new Container,this.treeContainer.addChild(this.treeList),this.labelInputContainer=new Container,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Text(theme.bold(" Session Tree"),1,0)),this.addChild(new TreeHelp),this.addChild(new SearchLine(this.treeList)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(this.treeContainer),this.addChild(this.labelInputContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),tree.length===0&&setTimeout(()=>onCancel(),100)}showLabelInput(entryId,currentLabel){this.labelInput=new LabelInput(entryId,currentLabel),this.labelInput.onSubmit=(id,label)=>{this.treeList.updateNodeLabel(id,label),this.onLabelChangeCallback?.(id,label),this.hideLabelInput()},this.labelInput.onCancel=()=>this.hideLabelInput(),this.labelInput.focused=this._focused,this.treeContainer.clear(),this.labelInputContainer.clear(),this.labelInputContainer.addChild(this.labelInput)}hideLabelInput(){this.labelInput=null,this.labelInputContainer.clear(),this.treeContainer.clear(),this.treeContainer.addChild(this.treeList)}handleInput(keyData){this.labelInput?this.labelInput.handleInput(keyData):this.treeList.handleInput(keyData)}getTreeList(){return this.treeList}};var OSC133_ZONE_START2="\x1B]133;A\x07",OSC133_ZONE_END2="\x1B]133;B\x07",OSC133_ZONE_FINAL2="\x1B]133;C\x07",UserMessageComponent=class extends Container{constructor(text2,markdownTheme=getMarkdownTheme(),outputPad=1,markdownTransformers=[]){super(),this.text=text2,this.markdownTheme=markdownTheme,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.rebuild()}setOutputPad(padding){this.outputPad=padding,this.rebuild()}rebuild(){this.clear(),this.addChild(new Markdown(this.text,this.outputPad,1,this.markdownTheme,{color:content=>theme.fg("userMessageText",content),bgColor:content=>theme.bg("userMessageBg",content)},{preserveOrderedListMarkers:!0,preserveBackslashEscapes:!0,transform:createMarkdownTransform("user",!1,this.markdownTransformers)}))}render(width){let lines=super.render(width);return lines.length===0||(lines[0]=OSC133_ZONE_START2+lines[0],lines[lines.length-1]=OSC133_ZONE_END2+OSC133_ZONE_FINAL2+lines[lines.length-1]),lines}};var UserMessageList=class{constructor(messages,initialSelectedId){this.messages=[],this.selectedIndex=0,this.maxVisible=10,this.messages=messages;let initialIndex=initialSelectedId?messages.findIndex(message=>message.id===initialSelectedId):-1;this.selectedIndex=initialIndex>=0?initialIndex:Math.max(0,messages.length-1)}invalidate(){}render(width){let lines=[];if(this.messages.length===0)return lines.push(theme.fg("muted"," No user messages found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.messages.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.messages.length);for(let i=startIndex;i<endIndex;i++){let message=this.messages[i],isSelected2=i===this.selectedIndex,normalizedMessage=message.text.replace(/\n/g," ").trim(),cursor=isSelected2?theme.fg("accent","\u203A "):" ",maxMsgWidth=width-2,truncatedMsg=truncateToWidth(normalizedMessage,maxMsgWidth),messageLine=cursor+(isSelected2?theme.bold(truncatedMsg):truncatedMsg);lines.push(messageLine);let metadata=` Message ${i+1} of ${this.messages.length}`,metadataLine=theme.fg("muted",metadata);lines.push(metadataLine),lines.push("")}if(startIndex>0||endIndex<this.messages.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.messages.length})`);lines.push(scrollInfo)}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up"))this.selectedIndex=this.selectedIndex===0?this.messages.length-1:this.selectedIndex-1;else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=this.selectedIndex===this.messages.length-1?0:this.selectedIndex+1;else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.messages[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.id)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancel&&this.onCancel()}},UserMessageSelectorComponent=class extends Container{constructor(messages,onSelect,onCancel,initialSelectedId){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold("Fork from Message"),1,0)),this.addChild(new Text(theme.fg("muted","Select a user message to copy the active path up to that point into a new session"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.messageList=new UserMessageList(messages,initialSelectedId),this.messageList.onSelect=onSelect,this.messageList.onCancel=onCancel,this.addChild(this.messageList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),messages.length===0&&setTimeout(()=>onCancel(),100)}getMessageList(){return this.messageList}};import*as crypto3 from"node:crypto";import*as fs8 from"node:fs";import*as os7 from"node:os";import*as path13 from"node:path";import{spawn as spawn12}from"child_process";function detectMiss(prev,message,models){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!prev||promptTokens<=0||usage.cacheRead+usage.cacheWrite===0&&!prev.reportedCache)return;let missedTokens=Math.min(prev.promptTokens,promptTokens)-usage.cacheRead;if(missedTokens<=1024)return;let paidTokens=usage.input+usage.cacheWrite,paidPerToken=paidTokens>0?(usage.cost.input+usage.cost.cacheWrite)/paidTokens:0,readPerToken=usage.cacheRead>0?usage.cost.cacheRead/usage.cacheRead:(models.getModel(message.provider,message.model)?.cost.cacheRead??0)/1e6;return{missedTokens,missedCost:missedTokens*Math.max(0,paidPerToken-readPerToken),idleMs:Math.max(0,message.timestamp-prev.timestamp),modelChanged:`${message.provider}/${message.model}`!==prev.modelKey}}function asPreviousRequest(message,reportedCache){let usage=message.usage,promptTokens=usage.input+usage.cacheRead+usage.cacheWrite;if(!(promptTokens<=0))return{promptTokens,modelKey:`${message.provider}/${message.model}`,timestamp:message.timestamp,reportedCache:reportedCache||usage.cacheRead+usage.cacheWrite>0}}function scan(entries,models){let prev,totals={missedTokens:0,missedCost:0,missCount:0},misses=new Map;for(let entry of entries){if(entry.type==="compaction"||entry.type==="branch_summary"){prev=void 0;continue}if(entry.type==="usage"&&entry.kind==="cache_warm"){let promptTokens=entry.usage.input+entry.usage.cacheRead+entry.usage.cacheWrite;promptTokens>0&&(prev={promptTokens,modelKey:`${entry.provider}/${entry.model}`,timestamp:Date.parse(entry.timestamp),reportedCache:!0})}else if(entry.type==="message"&&entry.message.role==="assistant"){let miss=detectMiss(prev,entry.message,models);miss&&(totals.missedTokens+=miss.missedTokens,totals.missedCost+=miss.missedCost,totals.missCount+=1,misses.set(entry.message,miss)),prev=asPreviousRequest(entry.message,prev?.reportedCache??!1)??prev}}return{prev,totals,misses}}function computeCacheWaste(entries,models){return scan(entries,models).totals}function collectCacheMisses(entries,models){return scan(entries,models).misses}function detectCacheMiss(entries,message,models){return detectMiss(scan(entries,models).prev,message,models)}import{mkdirSync as mkdirSync14,readFileSync as readFileSync18,rmSync as rmSync4,writeFileSync as writeFileSync12}from"node:fs";import{dirname as dirname23,join as join39}from"node:path";var MAX_CRASH_RECORDS=5,MAX_AGE=10080*60*1e3;function crashLogPath(agentDir=getAgentDir()){return join39(agentDir,"crashes.json")}function readCrashLog(path14=crashLogPath()){try{let records=JSON.parse(readFileSync18(path14,"utf8"));return Array.isArray(records)?records.filter(record=>typeof record=="object"&&record!==null&&typeof record.timestamp=="string"&&typeof record.message=="string"):[]}catch{return[]}}function writeCrashLog(records,path14){mkdirSync14(dirname23(path14),{recursive:!0}),writeFileSync12(path14,`${JSON.stringify(records,null,2)}
|
|
1801
1775
|
`)}function normalizeStackPath(value){return value.replace(/\\/g,"/").replace(/\/+$/u,"")}function stackContainsPath(stack,targetPath,includeDescendants){let target=normalizeStackPath(targetPath);if(!target||isSyntheticPath(target))return!1;let caseInsensitive=/^[a-z]:\//iu.test(target),haystack=caseInsensitive?stack.toLowerCase():stack,needle=caseInsensitive?target.toLowerCase():target;if(includeDescendants)return haystack.includes(`${needle}/`);let index3=haystack.indexOf(needle);for(;index3!==-1;){let next=haystack[index3+needle.length];if(next===void 0||next===":"||next===")"||/\s/u.test(next))return!0;index3=haystack.indexOf(needle,index3+needle.length)}return!1}function findExtensionStackMatches(stack,extensions){if(!stack)return[];let normalizedStack=stack.split(`
|
|
1802
1776
|
`).slice(1).filter(line=>/^\s+at\s/u.test(line)).map(line=>{try{return decodeURI(line)}catch{return line}}).join(`
|
|
1803
|
-
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var RADIUS_PROVIDER_ID="radius",ENV_RADIUS_GATEWAY="PI_RADIUS_GATEWAY",RADIUS_MCP_URL=`${normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)}/mcp`;function getRadiusGatewayUrl(){return normalizeRadiusGatewayUrl(process.env[ENV_RADIUS_GATEWAY]??DEFAULT_RADIUS_GATEWAY)}var BUILTIN_SLASH_COMMANDS=[{name:"
|
|
1777
|
+
`).replace(/\\/g,"/"),matches=[],seen=new Set;for(let extension of extensions){let resolvedPath=normalizeStackPath(extension.resolvedPath),singleFilePackage=extension.sourceInfo.origin==="package"&&!/^(?:npm:|git:|https?:\/\/|ssh:\/\/)/u.test(extension.sourceInfo.source)&&/\.[cm]?[jt]s$/u.test(extension.sourceInfo.source),packageRoot=extension.sourceInfo.origin==="package"&&!singleFilePackage&&extension.sourceInfo.baseDir?extension.sourceInfo.baseDir:void 0,slashIndex=resolvedPath.lastIndexOf("/"),directoryEntry=/\/index\.[cm]?[jt]s$/u.test(resolvedPath);if(!(packageRoot?stackContainsPath(normalizedStack,packageRoot,!0):directoryEntry&&slashIndex!==-1?stackContainsPath(normalizedStack,resolvedPath.slice(0,slashIndex),!0):stackContainsPath(normalizedStack,resolvedPath,!1)))continue;let label=extension.sourceInfo.origin==="package"&&extension.sourceInfo.source?extension.sourceInfo.source:extension.path;seen.has(label)||(seen.add(label),matches.push(label))}return matches}function recordCrash(crash,path14=crashLogPath()){try{let{error}=crash,record={timestamp:new Date().toISOString(),version:VERSION,kind:crash.kind,message:error instanceof Error?error.message||error.name:String(error),stack:error instanceof Error&&error.stack?error.stack:null,sessionFile:crash.sessionFile??null,cwd:crash.cwd};return writeCrashLog([...readCrashLog(path14),record].slice(-MAX_CRASH_RECORDS),path14),record}catch{return}}function takeUnnotifiedCrash(path14=crashLogPath(),now=Date.now()){let records=readCrashLog(path14),crash=[...records].reverse().find(record=>!record.notified&&now-Date.parse(record.timestamp)<=MAX_AGE);if(crash){try{writeCrashLog(records.map(record=>record.notified?record:{...record,notified:!0}),path14)}catch{}return crash}}function clearCrashLog(path14=crashLogPath()){try{rmSync4(path14,{force:!0})}catch{}}var RADIUS_PROVIDER_ID="radius",ENV_RADIUS_GATEWAY="PI_RADIUS_GATEWAY",RADIUS_MCP_URL=`${normalizeRadiusGatewayUrl(DEFAULT_RADIUS_GATEWAY)}/mcp`;function getRadiusGatewayUrl(){return normalizeRadiusGatewayUrl(process.env[ENV_RADIUS_GATEWAY]??DEFAULT_RADIUS_GATEWAY)}var BUILTIN_SLASH_COMMANDS=[{name:"settings",description:"Open settings menu"},{name:"model",description:"Select model (opens selector UI)",argumentHint:"<provider/model>"},{name:"tree",description:"Navigate session tree (switch branches)"},{name:"thinking",description:"Set thinking level",argumentHint:"<level>"},{name:"scoped-models",description:"Enable/disable models for Ctrl+P cycling"},{name:"export",description:"Export session (HTML default, or specify path: .html/.jsonl)"},{name:"import",description:"Import and resume a session from a JSONL file"},{name:"share",description:"Share session via a Radius artifact or a GitHub gist"},{name:"bug",description:"Report a bug to the Pi developers",argumentHint:"<description>"},{name:"copy",description:"Copy last agent message to clipboard"},{name:"name",description:"Set session display name"},{name:"session",description:"Show session info and stats"},{name:"changelog",description:"Show changelog entries"},{name:"hotkeys",description:"Show all keyboard shortcuts"},{name:"fork",description:"Create a new fork from a previous user message"},{name:"clone",description:"Duplicate the current session at the current position"},{name:"trust",description:"Save project trust decision for future sessions"},{name:"login",description:"Configure provider authentication",argumentHint:"<provider>"},{name:"logout",description:"Remove provider authentication"},{name:"new",description:"Start a new session"},{name:"compact",description:"Manually compact the session context"},{name:"resume",description:"Resume a different session"},{name:"reload",description:"Reload keybindings, extensions, skills, prompts, themes, and context files"},{name:"quit",description:`Quit ${APP_NAME}`}];function createAllToolRenderers(){return{read:readRenderers,bash:createShellRenderers({name:"bash",prompt:"$"}),powershell:createShellRenderers({name:"powershell",prompt:"PS>"}),edit:editRenderers,write:writeRenderers,grep:grepRenderers,find:findRenderers,ls:lsRenderers}}function withBuiltInRenderers(toolName,definition){let builtIn=createAllToolRenderers()[toolName];return definition?builtIn?{...definition,renderCall:definition.renderCall??builtIn.renderCall,renderResult:definition.renderResult??builtIn.renderResult}:definition:builtIn}import path10 from"node:path";import{existsSync as existsSync21,readFileSync as readFileSync19}from"fs";var GITHUB_REPO="earendil-works/pi",CHANGELOG_LINK_BASE_PATH="packages/coding-agent",LEGACY_REPO_RE=/^https:\/\/github\.com\/(?:badlogic|earendil-works)\/pi-mono(?=\/|$)/,URL_SCHEME_RE=/^[a-z][a-z0-9+.-]*:/i,INLINE_MARKDOWN_LINK_RE=/(!?\[[^\]\n]+\]\()([^\s)]+)((?:\s+[^)]*)?\))/g;function entryVersion(entry){return`${entry.major}.${entry.minor}.${entry.patch}`}function normalizeTag(version2){let versionString=typeof version2=="string"?version2:entryVersion(version2);return versionString.startsWith("v")?versionString:`v${versionString}`}function splitLocalTarget(target){let hashIndex=target.indexOf("#"),beforeHash=hashIndex===-1?target:target.slice(0,hashIndex),fragment=hashIndex===-1?"":target.slice(hashIndex),queryIndex=beforeHash.indexOf("?");return queryIndex===-1?{fragment,pathPart:beforeHash,query:""}:{fragment,pathPart:beforeHash.slice(0,queryIndex),query:beforeHash.slice(queryIndex)}}function normalizePathPart(value){return value.replaceAll("\\","/")}function resolveRepositoryPath(targetPath){let normalizedTarget=normalizePathPart(targetPath),joined=normalizedTarget.startsWith("/")?path10.posix.normalize(normalizedTarget.replace(/^\/+/,"")):path10.posix.normalize(path10.posix.join(CHANGELOG_LINK_BASE_PATH,normalizedTarget));if(!(joined==="."||joined.startsWith("../")||joined===".."))return joined}function isDirectoryTarget(originalPath,repositoryPath){return originalPath.endsWith("/")?!0:!path10.posix.basename(repositoryPath).includes(".")}function normalizeChangelogLinkTarget(target,tag){let canonicalTarget=target.replace(LEGACY_REPO_RE,`https://github.com/${GITHUB_REPO}`),repoUrl=`https://github.com/${GITHUB_REPO}`;for(let route2 of["blob","tree"])for(let branch of["main","master"]){let floatingRefPrefix=`${repoUrl}/${route2}/${branch}/`;canonicalTarget.startsWith(floatingRefPrefix)&&(canonicalTarget=`${repoUrl}/${route2}/${tag}/${canonicalTarget.slice(floatingRefPrefix.length)}`)}if(canonicalTarget.startsWith("#")||canonicalTarget.startsWith("//")||URL_SCHEME_RE.test(canonicalTarget))return canonicalTarget;let{fragment,pathPart,query}=splitLocalTarget(canonicalTarget);if(!pathPart)return canonicalTarget;let repositoryPath=resolveRepositoryPath(pathPart);if(!repositoryPath)return canonicalTarget;let route=isDirectoryTarget(pathPart,repositoryPath)?"tree":"blob";return`https://github.com/${GITHUB_REPO}/${route}/${tag}/${encodeURI(repositoryPath)}${query}${fragment}`}function normalizeChangelogLinks(markdown,version2){let tag=normalizeTag(version2);return markdown.replace(INLINE_MARKDOWN_LINK_RE,(_match,prefix,target,suffix)=>`${prefix}${normalizeChangelogLinkTarget(target,tag)}${suffix}`)}function parseChangelog(changelogPath){if(!existsSync21(changelogPath))return[];try{let lines=readFileSync19(changelogPath,"utf-8").split(`
|
|
1804
1778
|
`),entries=[],currentLines=[],currentVersion=null;for(let line of lines)if(line.startsWith("## ")){currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1805
1779
|
`).trim()});let versionMatch=line.match(/##\s+\[?(\d+)\.(\d+)\.(\d+)\]?/);versionMatch?(currentVersion={major:Number.parseInt(versionMatch[1],10),minor:Number.parseInt(versionMatch[2],10),patch:Number.parseInt(versionMatch[3],10)},currentLines=[line]):(currentVersion=null,currentLines=[])}else currentVersion&¤tLines.push(line);return currentVersion&¤tLines.length>0&&entries.push({...currentVersion,content:currentLines.join(`
|
|
1806
1780
|
`).trim()}),entries}catch(error){return console.error(`Warning: Could not parse changelog: ${error}`),[]}}function compareVersions(v1,v2){return v1.major!==v2.major?v1.major-v2.major:v1.minor!==v2.minor?v1.minor-v2.minor:v1.patch-v2.patch}function getNewEntries(entries,lastVersion){let parts=lastVersion.split(".").map(Number),last={major:parts[0]||0,minor:parts[1]||0,patch:parts[2]||0,content:""};return entries.filter(entry=>compareVersions(entry,last)>0)}import{randomUUID as randomUUID5}from"crypto";import{readFileSync as readFileSync20,unlinkSync as unlinkSync2}from"fs";import{tmpdir as tmpdir5}from"os";import{join as join40}from"path";var SUPPORTED_IMAGE_MIME_TYPES=["image/png","image/jpeg","image/webp","image/gif"],DEFAULT_LIST_TIMEOUT_MS=1e3,DEFAULT_POWERSHELL_TIMEOUT_MS=5e3;function isWaylandSession(env2=process.env){return!!env2.WAYLAND_DISPLAY||env2.XDG_SESSION_TYPE==="wayland"}function baseMimeType2(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function extensionForImageMimeType(mimeType){switch(baseMimeType2(mimeType)){case"image/png":return"png";case"image/jpeg":return"jpg";case"image/webp":return"webp";case"image/gif":return"gif";default:return null}}function selectPreferredImageMimeType(mimeTypes){let normalized=mimeTypes.map(t=>t.trim()).filter(Boolean).map(t=>({raw:t,base:baseMimeType2(t)}));for(let preferred of SUPPORTED_IMAGE_MIME_TYPES){let match2=normalized.find(t=>t.base===preferred);if(match2)return match2.raw}return normalized.find(t=>t.base.startsWith("image/"))?.raw??null}function isSupportedImageMimeType(mimeType){let base=baseMimeType2(mimeType);return SUPPORTED_IMAGE_MIME_TYPES.some(t=>t===base)}async function convertToPng2(bytes){let photon=await loadPhoton();if(!photon)return null;try{let image=photon.PhotonImage.new_from_byteslice(bytes);try{return image.get_bytes()}finally{image.free()}}catch{return null}}async function readClipboardImageViaWlPaste(){let list2=await runClipboardCommand("wl-paste",["--list-types"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(list2===void 0)return;let types2=list2.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean),selectedType=selectPreferredImageMimeType(types2);if(!selectedType)return null;let data=await runClipboardCommand("wl-paste",["--type",selectedType,"--no-newline"]);if(data!==void 0)return data.length===0?null:{bytes:data,mimeType:baseMimeType2(selectedType)}}async function readClipboardImageViaPowerShell(){let tmpFile=join40(tmpdir5(),`pi-wsl-clip-${randomUUID5()}.png`);try{let winPathResult=await runClipboardCommand("wslpath",["-w",tmpFile],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(winPathResult===void 0)return null;let winPath=winPathResult.toString("utf-8").trim();if(!winPath)return null;let psScript=["Add-Type -AssemblyName System.Windows.Forms","Add-Type -AssemblyName System.Drawing",`$path = '${winPath.replaceAll("'","''")}'`,"$img = [System.Windows.Forms.Clipboard]::GetImage()","if ($img) { $img.Save($path, [System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'ok' } else { Write-Output 'empty' }"].join("; "),result2=await runClipboardCommand("powershell.exe",["-NoProfile","-Command",psScript],{timeoutMs:DEFAULT_POWERSHELL_TIMEOUT_MS});if(result2===void 0||result2.toString("utf-8").trim()!=="ok")return null;let bytes=readFileSync20(tmpFile);return bytes.length===0?null:{bytes:new Uint8Array(bytes),mimeType:"image/png"}}catch{return null}finally{try{unlinkSync2(tmpFile)}catch{}}}async function readClipboardImageViaXclip(){let targets=await runClipboardCommand("xclip",["-selection","clipboard","-t","TARGETS","-o"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(targets===void 0)return;let candidateTypes=targets.toString("utf-8").split(/\r?\n/).map(t=>t.trim()).filter(Boolean),preferred=selectPreferredImageMimeType(candidateTypes);if(!preferred)return null;let data=await runClipboardCommand("xclip",["-selection","clipboard","-t",preferred,"-o"]);if(data!==void 0)return data.length===0?null:{bytes:data,mimeType:baseMimeType2(preferred)}}async function readClipboardImageViaNativeClipboard(){let bytes=await getNativeClipboard()?.getImage();if(bytes!==void 0)return bytes?.length?{bytes,mimeType:detectSupportedImageMimeType(bytes)??"application/octet-stream"}:null}async function readClipboardImage(options){let env2=options?.env??process.env,platform3=options?.platform??process.platform;if(env2.TERMUX_VERSION)return null;let image;if(platform3==="linux"){let wsl=isWSL(env2);(isWaylandSession(env2)||wsl)&&(image=await readClipboardImageViaWlPaste()),image===void 0&&(image=await readClipboardImageViaXclip()),!image&&wsl&&(image=await readClipboardImageViaPowerShell()??image),image===void 0&&(image=await readClipboardImageViaNativeClipboard())}else image=await readClipboardImageViaNativeClipboard();if(!image)return null;if(!isSupportedImageMimeType(image.mimeType)){let pngBytes=await convertToPng2(image.bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png"}:null}return image}var import_semver2=__toESM(require_semver2(),1);var LATEST_VERSION_URL=`https://registry.npmjs.org/${encodeURIComponent(PACKAGE_NAME)}/latest`,DEFAULT_VERSION_CHECK_TIMEOUT_MS=1e4;function formatVersionCheckError(error){let rootMessage=error instanceof Error&&error.message?error.message:String(error),cause=error instanceof Error?error.cause:void 0,causes=cause instanceof AggregateError?cause.errors:cause===void 0?[]:[cause],codes=causes.map(value=>typeof value=="object"&&value!==null&&"code"in value&&typeof value.code=="string"?value.code:void 0).filter(code=>code!==void 0);if(codes.length>0)return`${rootMessage} (${[...new Set(codes)].join(", ")})`;let causeMessage=causes.find(value=>value instanceof Error&&!!value.message)?.message;return causeMessage?`${rootMessage} (cause: ${causeMessage})`:rootMessage}function comparePackageVersions(leftVersion,rightVersion){let left=(0,import_semver2.valid)(leftVersion.trim()),right=(0,import_semver2.valid)(rightVersion.trim());if(!(!left||!right))return(0,import_semver2.compare)(left,right)}function isNewerPackageVersion(candidateVersion,currentVersion){let comparison=comparePackageVersions(candidateVersion,currentVersion);return comparison!==void 0?comparison>0:candidateVersion.trim()!==currentVersion.trim()}async function getLatestPiRelease(currentVersion,options={}){if(process.env.PI_OFFLINE)return;let response=await fetchWithRetry(LATEST_VERSION_URL,{headers:{"User-Agent":getPiUserAgent(currentVersion),accept:"application/json"}},{maxRetries:options.retry?2:0,timeoutMs:options.timeoutMs??DEFAULT_VERSION_CHECK_TIMEOUT_MS});if(!response.ok)return;let data=await response.json();if(!(typeof data.version!="string"||!data.version.trim()))return{version:data.version.trim(),packageName:PACKAGE_NAME}}async function checkForNewPiVersion(currentVersion){if(!process.env.PI_SKIP_VERSION_CHECK)try{let latestRelease=await getLatestPiRelease(currentVersion);return latestRelease&&isNewerPackageVersion(latestRelease.version,currentVersion)?latestRelease:void 0}catch{return}}import*as path12 from"node:path";var AuthCommandError=class extends Error{},AUTH_COMMAND_USAGE={check:`${APP_NAME} auth check --provider <provider> [--json] [--credentials] [--no-refresh]`,api_key:`${APP_NAME} auth print-api-key --provider <provider> [--model <model>]`,bearer_token:`${APP_NAME} auth print-bearer-token --provider <provider> [--model <model>] [--min-expiry <duration>]`};function getAuthCommandName(kind){return kind==="check"?"auth check":kind==="api_key"?"auth print-api-key":"auth print-bearer-token"}function getAuthCommandUsage(kind){return AUTH_COMMAND_USAGE[kind]}function isAuthCommandHelp(args){return args[0]==="auth"&&(args[1]===void 0||args[1]==="help"||args.includes("--help")||args.includes("-h"))}function printAuthCommandHelp(){console.log(`Usage:
|
|
@@ -1826,7 +1800,7 @@ ${codeSpan(styledWarning)}
|
|
|
1826
1800
|
`)}
|
|
1827
1801
|
`}).join("")}}var CORAL2=rgbColor(228,138,122),BLUE2=rgbColor(79,142,179),YELLOW2=rgbColor(234,182,93),RESET="\x1B[0m";function piLogoLines(){let mode=theme.getColorMode(),fg=color2=>foregroundAnsi(color2,mode),top=`${fg(CORAL2)}${backgroundAnsi(BLUE2,mode)}\u2580${RESET}${fg(CORAL2)}\u2580\u2588${RESET} `,bottom=`${fg(BLUE2)}\u2588\u2580${RESET} ${fg(YELLOW2)}\u2588${RESET}`;return[top,bottom]}function supportsPiLogo(){return!isAppleTerminalSession()}function piWordmark(){let mode=theme.getColorMode();return`${foregroundAnsi(CORAL2,mode)}P${RESET}${foregroundAnsi(YELLOW2,mode)}i${RESET}`}var RADIUS_COLORS=["#4d9abf","#83ccd2","#f1be57","#f09082"].map(hex=>parseColor(hex)),CHARS_PER_COLOR=4,CHARS_PER_SECOND=10,ANIMATION_FRAME_MS=50;function radiusShimmer(text2,elapsedMs){let mode=theme.getColorMode(),cycle=RADIUS_COLORS.length*CHARS_PER_COLOR,offset=elapsedMs/1e3*CHARS_PER_SECOND,result2="",index3=0;for(let char of text2){let position=((index3-offset)%cycle+cycle)%cycle,band=Math.floor(position/CHARS_PER_COLOR),t=position/CHARS_PER_COLOR-band,amount=t*t*(3-2*t),from=RADIUS_COLORS[band],to=RADIUS_COLORS[(band+1)%RADIUS_COLORS.length];result2+=foregroundAnsi(mixColors(from,to,amount,"srgb"),mode)+char,index3++}return`${result2}\x1B[39m`}var RadiusLoginMenuComponent=class extends ExtensionSelectorComponent{constructor(tui,title,options,radiusOption,onSelect,onCancel){super(title,options,option=>{this.stopAnimation(),onSelect(option)},()=>{this.stopAnimation(),onCancel()}),this.animationStart=performance.now(),this.animating=!1,this.radiusOption=radiusOption,this.animationTimer=setInterval(()=>{this.animating&&tui.requestRender()},ANIMATION_FRAME_MS),this.animationTimer.unref?.()}render(width){let lines=super.render(width),{label,text:text2}=this.radiusOption,selectedLine=new Text(theme.fg("accent","\u2192 ")+theme.fg("accent",label),1,0).render(width)[0],index3=selectedLine===void 0?-1:lines.indexOf(selectedLine);if(this.animating=index3>=0,this.animating){let shimmer=radiusShimmer(text2,performance.now()-this.animationStart),animatedLine=theme.fg("accent","\u2192 ")+shimmer+label.slice(text2.length);lines[index3]=new Text(animatedLine,1,0).render(width)[0]??""}return lines}stopAnimation(){clearInterval(this.animationTimer),this.animationTimer=void 0,this.animating=!1}dispose(){this.stopAnimation(),super.dispose()}};function createLoginMenuSelector(tui,title,options,radiusOption,onSelect,onCancel){return new RadiusLoginMenuComponent(tui,title,options,radiusOption,onSelect,onCancel)}function isEnabled2(enabledIds,id){return enabledIds===null||enabledIds.includes(id)}function normalizeEnabled(result2,allIds){return result2.length===allIds.length&&result2.every(id=>allIds.includes(id))?null:result2}function toggle(enabledIds,allIds,id){if(enabledIds===null)return allIds.filter(modelId=>modelId!==id);let index3=enabledIds.indexOf(id);return index3>=0?[...enabledIds.slice(0,index3),...enabledIds.slice(index3+1)]:normalizeEnabled([...enabledIds,id],allIds)}function enableAll(enabledIds,allIds,targetIds){if(enabledIds===null)return null;let targets=targetIds??allIds,result2=[...enabledIds];for(let id of targets)result2.includes(id)||result2.push(id);return normalizeEnabled(result2,allIds)}function clearAll(enabledIds,allIds,targetIds){if(enabledIds===null)return targetIds?allIds.filter(id=>!targetIds.includes(id)):[];let targets=new Set(targetIds??enabledIds);return enabledIds.filter(id=>!targets.has(id))}function move(enabledIds,id,delta){if(enabledIds===null)return null;let list2=[...enabledIds],index3=list2.indexOf(id);if(index3<0)return list2;let newIndex=index3+delta;if(newIndex<0||newIndex>=list2.length)return list2;let result2=[...list2];return[result2[index3],result2[newIndex]]=[result2[newIndex],result2[index3]],result2}function getSortedIds(enabledIds,allIds){if(enabledIds===null)return allIds;let enabledSet=new Set(enabledIds);return[...enabledIds,...allIds.filter(id=>!enabledSet.has(id))]}var ScopedModelsSelectorComponent=class extends Container{get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(config,callbacks){super(),this.modelsById=new Map,this.allIds=[],this.enabledIds=null,this.filteredItems=[],this.selectedIndex=0,this._focused=!1,this.maxVisible=8,this.isDirty=!1,this.callbacks=callbacks;for(let model of config.allModels){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.enabledIds=config.enabledModelIds===null?null:[...config.enabledModelIds],this.filteredItems=this.buildItems(),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Model Configuration")),0,0)),this.addChild(new Text(theme.fg("muted",`Session-only. ${keyDisplayText("app.models.save")} to save to settings.`),0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),config.refreshStatus&&(this.refreshStatusText=new Text(theme.fg("muted",` ${config.refreshStatus}`),0,0),this.addChild(this.refreshStatusText)),this.footerText=new Text(this.getFooterText(),0,0),this.addChild(this.footerText),this.addChild(new DynamicBorder),this.updateList()}updateModels(models,enabledModelIds){let selectedId=this.filteredItems[this.selectedIndex]?.fullId;enabledModelIds!==void 0&&(this.enabledIds=enabledModelIds===null?null:[...enabledModelIds]),this.modelsById.clear(),this.allIds=[];for(let model of models){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.refresh();let refreshedIndex=selectedId?this.filteredItems.findIndex(item=>item.fullId===selectedId):-1;refreshedIndex>=0&&(this.selectedIndex=refreshedIndex,this.updateList())}setRefreshStatus(message,kind){this.refreshStatusText?.setText(theme.fg(kind,` ${message}`))}buildItems(){return getSortedIds(this.enabledIds,this.allIds).map(id=>({fullId:id,model:this.modelsById.get(id),enabled:isEnabled2(this.enabledIds,id)}))}getFooterText(){let enabledCount=this.enabledIds?.filter(id=>this.modelsById.has(id)).length??this.allIds.length,unavailableCount=this.enabledIds?.filter(id=>!this.modelsById.has(id)).length??0,countText=this.enabledIds===null?"all enabled":`${enabledCount}/${this.allIds.length} enabled${unavailableCount?` \xB7 ${unavailableCount} unavailable`:""}`,parts=[`${keyDisplayText("tui.select.confirm")} toggle`,`${keyDisplayText("app.models.enableAll")} all`,`${keyDisplayText("app.models.clearAll")} clear`,`${keyDisplayText("app.models.toggleProvider")} provider`,`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} reorder`,`${keyDisplayText("app.models.save")} save`,countText];return this.isDirty?theme.fg("dim",` ${parts.join(" \xB7 ")} `)+theme.fg("warning","(unsaved)"):theme.fg("dim",` ${parts.join(" \xB7 ")}`)}refresh(){let query=this.searchInput.getValue(),items=this.buildItems();this.filteredItems=query?fuzzyFilter(items,query,item=>item.model?getModelSearchText({id:item.model.id,provider:item.model.provider,name:item.model.name}):item.fullId):items,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredItems.length-1)),this.updateList(),this.footerText.setText(this.getFooterText())}notifyChange(){this.callbacks.onChange(this.enabledIds===null?null:[...this.enabledIds])}updateList(){if(this.listContainer.clear(),this.filteredItems.length===0){this.listContainer.addChild(new Text(theme.fg("muted"," No matching models"),0,0));return}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredItems.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredItems.length);for(let i=startIndex;i<endIndex;i++){let item=this.filteredItems[i],isSelected2=i===this.selectedIndex,prefix=isSelected2?theme.fg("accent","\u2192 "):" ",id=item.model?.id??item.fullId,styledId=item.model?id:theme.strikethrough(id),modelText2=isSelected2?theme.fg("accent",styledId):styledId,providerBadge=theme.fg("muted",item.model?` [${item.model.provider}]`:" [unavailable]"),status=item.model&&item.enabled?theme.fg("accent","\u2713 "):" ";this.listContainer.addChild(new Text(`${prefix}${status}${modelText2}${providerBadge}`,0,0))}if((startIndex>0||endIndex<this.filteredItems.length)&&this.listContainer.addChild(new Text(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredItems.length})`),0,0)),this.filteredItems.length>0){let selected=this.filteredItems[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` ${selected.model?`Model Name: ${selected.model.name}`:"Model unavailable"}`),0,0))}}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.up")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredItems.length-1:this.selectedIndex-1,this.updateList();return}if(kb.matches(data,"tui.select.down")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredItems.length-1?0:this.selectedIndex+1,this.updateList();return}let reorderUp=kb.matches(data,"app.models.reorderUp"),reorderDown=kb.matches(data,"app.models.reorderDown");if(reorderUp||reorderDown){if(this.enabledIds===null)return;let item=this.filteredItems[this.selectedIndex];if(item&&isEnabled2(this.enabledIds,item.fullId)){let delta=reorderUp?-1:1,newIndex=this.enabledIds.indexOf(item.fullId)+delta;newIndex>=0&&newIndex<this.enabledIds.length&&(this.enabledIds=move(this.enabledIds,item.fullId,delta),this.isDirty=!0,this.selectedIndex+=delta,this.refresh(),this.notifyChange())}return}if(kb.matches(data,"tui.select.confirm")){let item=this.filteredItems[this.selectedIndex];item&&(this.enabledIds=toggle(this.enabledIds,this.allIds,item.fullId),this.isDirty=!0,this.refresh(),this.notifyChange());return}if(kb.matches(data,"app.models.enableAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=enableAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.clearAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=clearAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.toggleProvider")){let item=this.filteredItems[this.selectedIndex];if(item?.model){let provider=item.model.provider,providerIds=this.allIds.filter(id=>this.modelsById.get(id).provider===provider),allEnabled=providerIds.every(id=>isEnabled2(this.enabledIds,id));this.enabledIds=allEnabled?clearAll(this.enabledIds,this.allIds,providerIds):enableAll(this.enabledIds,this.allIds,providerIds),this.isDirty=!0,this.refresh(),this.notifyChange()}return}if(kb.matches(data,"app.models.save")){this.callbacks.onPersist(this.enabledIds===null?null:[...this.enabledIds]),this.isDirty=!1,this.footerText.setText(this.getFooterText());return}if(matchesKey(data,Key.ctrl("c"))){this.searchInput.getValue()?(this.searchInput.setValue(""),this.refresh()):this.callbacks.onCancel();return}if(matchesKey(data,Key.escape)){this.callbacks.onCancel();return}this.searchInput.handleInput(data),this.refresh()}getSearchInput(){return this.searchInput}};var StatusIndicator=class extends Loader{constructor(kind,ui,spinnerColorFn,messageColorFn,message,indicator){super(ui,spinnerColorFn,messageColorFn,message,indicator),this.kind=kind}renderInBorder(width){let line=super.render(width+2)[1]??"";return truncateToWidth(line.startsWith(" ")?line.slice(1).trimEnd():line.trimEnd(),width,"")}renderSpinnerInBorder(width){return truncateToWidth(this.getRenderedIndicator(),width,"")}dispose(){this.stop()}},WorkingStatusIndicator=class extends StatusIndicator{constructor(ui,message,indicator,colorFn){super("working",ui,colorFn??(text2=>theme.fg("accent",text2)),colorFn??(text2=>theme.fg("muted",text2)),message,indicator)}},RetryStatusIndicator=class extends StatusIndicator{constructor(ui,attempt2,maxAttempts,delayMs){let retryMessage=seconds=>`Retrying (${attempt2}/${maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;super("retry",ui,spinner=>theme.fg("warning",spinner),text2=>theme.fg("muted",text2),retryMessage(Math.ceil(delayMs/1e3))),this.countdown=new CountdownTimer(delayMs,ui,seconds=>{this.setMessage(retryMessage(seconds))},()=>{this.countdown=void 0})}dispose(){this.countdown?.dispose(),this.countdown=void 0,super.dispose()}},CompactionStatusIndicator=class extends StatusIndicator{constructor(ui,reason,colorFn){let cancelHint=`(${keyText("app.interrupt")} to cancel)`,label=reason==="manual"?`Compacting context... ${cancelHint}`:`${reason==="overflow"?"Context overflow detected, ":""}Auto-compacting... ${cancelHint}`;super("compaction",ui,colorFn??(spinner=>theme.fg("accent",spinner)),colorFn??(text2=>theme.fg("muted",text2)),label)}},BranchSummaryStatusIndicator=class extends StatusIndicator{constructor(ui){super("branchSummary",ui,spinner=>theme.fg("accent",spinner),text2=>theme.fg("muted",text2),`Summarizing branch... (${keyText("app.interrupt")} to cancel)`)}},IdleStatus=class{invalidate(){}render(width){let emptyLine=" ".repeat(width);return[emptyLine,emptyLine]}};var ThemedText=class extends Text{constructor(build,paddingX=1,paddingY=1){super("",paddingX,paddingY),this.stale=!0,this.build=build}invalidate(){super.invalidate(),this.stale=!0}render(width){return this.stale&&(this.stale=!1,this.setText(this.build())),super.render(width)}};function formatDecision(trustPath,decision){if(decision===null)return"none";let label=decision.decision?"trusted":"untrusted";return trustPath!==void 0&&decision.path!==trustPath?`${label} (inherited from ${decision.path})`:`${label} (${decision.path})`}var TrustSelectorComponent=class extends Container{constructor(options){super(),this.savedDecision=options.savedDecision,this.trustOptions=getProjectTrustOptions(options.cwd),this.selectedIndex=Math.max(0,this.trustOptions.findIndex(option=>this.isSavedOption(option))),this.onSelectCallback=options.onSelect,this.onCancelCallback=options.onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold("Project trust")),1,0)),this.addChild(new Text(theme.fg("muted",options.cwd),1,0)),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",`Saved decision: ${formatDecision(this.trustOptions[0]?.savedPath,options.savedDecision)}`),1,0)),this.addChild(new Text(theme.fg("muted",`Current session: ${options.projectTrusted?"trusted":"untrusted"}`),1,0)),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new Text(rawKeyHint("\u2191\u2193","navigate")+" "+keyHint("tui.select.confirm","save")+" "+keyHint("tui.select.cancel","cancel"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}isSavedOption(option){return option.savedPath!==void 0&&this.savedDecision?.decision===option.trusted&&this.savedDecision.path===option.savedPath}updateList(){this.listContainer.clear();for(let i=0;i<this.trustOptions.length;i++){let option=this.trustOptions[i];if(!option)continue;let isSelected2=i===this.selectedIndex,currentMarker=this.isSavedOption(option)?theme.fg("accent","\u2713 "):" ",prefix=isSelected2?theme.fg("accent","\u2192 "):" ",label=isSelected2?theme.fg("accent",option.label):theme.fg("text",option.label);this.listContainer.addChild(new Text(`${prefix}${currentMarker}${label}`,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.trustOptions.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
1828
1802
|
`){let selected=this.trustOptions[this.selectedIndex];selected&&this.onSelectCallback({trusted:selected.trusted,updates:selected.updates})}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}};var HIDDEN_BUILTIN_COMMANDS=["debug","arminsayshi","dementedelves"],InteractiveEditorHost=class{constructor(options){this.submitHandlers=new Set,this.options=options}onSubmit(handler){return this.submitHandlers.add(handler),()=>this.submitHandlers.delete(handler)}getCursor(){return this.options.getEditor().getCursor?.()}onInput(handler){return this.options.addTerminalInputListener(data=>this.isEditorFocused()?handler(data):void 0)}isEditorFocused(){let editor=this.options.getEditor();return this.options.getFocusedComponent()===editor&&!this.options.hasOverlay()&&!editor.isShowingAutocomplete?.()}clear(){this.submitHandlers.clear()}classify(text2){if(text2.startsWith("!"))return"bash";if(!text2.startsWith("/"))return"prompt";let name=text2.slice(1).split(/\s/,1)[0];return BUILTIN_SLASH_COMMANDS.some(command=>command.name===name)||HIDDEN_BUILTIN_COMMANDS.includes(name)||this.options.isSessionCommand(name)?"command":"prompt"}intercept(text2,mode){if(mode==="steer"&&this.declinedFollowUp===text2||this.submitHandlers.size===0)return!1;let event={text:text2,mode,kind:this.classify(text2)};for(let handler of this.submitHandlers)try{let result2=handler(event);if(!result2?.handled)continue;return this.options.setEditorText(result2.editorText??""),this.options.requestRender(),!0}catch(error){return this.options.setEditorText(text2),this.options.showError(`Editor submit handler failed: ${error instanceof Error?error.message:String(error)}`),!0}return mode==="followUp"&&(this.declinedFollowUp=text2,queueMicrotask(()=>{this.declinedFollowUp=void 0})),!1}};function firstLine2(text2){return text2?.split(/\r?\n/,1)[0]?.trim()||"Error"}var ProgramStatusReporter=class{constructor(getTerminal,getSessionName){this.runActive=!1,this.compacting=!1,this.runResult={state:"done"},this.restingStatus={state:"idle"},this.blocked=new Map,this.getTerminal=getTerminal,this.getSessionName=getSessionName}handleEvent(event){switch(event.type){case"agent_start":this.runActive=!0,this.runResult={state:"done"};break;case"message_end":if(event.message.role!=="assistant")return;this.runResult=event.message.stopReason==="error"?{state:"error",message:firstLine2(event.message.errorMessage)}:{state:"done"};break;case"compaction_start":this.compacting=!0;break;case"compaction_end":this.compacting=!1,this.runActive?event.aborted?this.runResult={state:"idle"}:event.errorMessage&&(this.runResult={state:"error",message:firstLine2(event.errorMessage)}):event.aborted?this.restingStatus={state:"idle"}:event.reason==="manual"&&(this.restingStatus=event.errorMessage?{state:"error",message:firstLine2(event.errorMessage)}:{state:"done"});break;case"agent_settled":this.runActive=!1,this.restingStatus=event.aborted?{state:"idle"}:this.runResult;break;case"session_info_changed":break;default:return}this.report()}setBlocked(source,status){this.blocked.delete(source),status&&this.blocked.set(source,status),this.report()}reset(){this.runActive=!1,this.compacting=!1,this.runResult={state:"done"},this.restingStatus={state:"idle"},this.report()}report(){let status={...this.currentStatus(),app:APP_NAME},key=JSON.stringify(status);key!==this.lastReport&&(this.lastReport=key,this.getTerminal().setProgramStatus(status))}currentStatus(){let blocked=[...this.blocked.values()].at(-1);if(blocked)return{state:"blocked",...blocked};if(this.compacting)return{state:"working",message:"Compacting context"};let status=this.runActive?{state:"working"}:this.restingStatus;return status.state==="working"||status.state==="done"?{...status,message:this.getSessionName()}:status}};var TERMINAL_QUERY_TIMEOUT_MS=100;function requestTerminalColors(ui,apply){let query;try{query=ui.queryTerminalColors({timeoutMs:TERMINAL_QUERY_TIMEOUT_MS,onLateReply:apply})}catch{query=Promise.resolve({})}return query.then(apply,()=>apply({}))}function sameRgb(a,b2){return a===b2||a!==void 0&&b2!==void 0&&a.r===b2.r&&a.g===b2.g&&a.b===b2.b}function sameTerminalColors(a,b2){return!sameRgb(a.foreground,b2.foreground)||!sameRgb(a.background,b2.background)?!1:a.palette===b2.palette?!0:!a.palette||!b2.palette||a.palette.length!==b2.palette.length?!1:a.palette.every((color2,index3)=>sameRgb(color2,b2.palette?.[index3]))}var InteractiveThemeController=class{constructor(ui,options){this.autoSyncEnabled=!1,this.terminalColorQuery=Promise.resolve(),this.ui=ui,this.getSettingsManager=options.getSettingsManager,this.showError=options.showError,this.onChanged=options.onChanged,this.currentThemeSetting=options.initialThemeSetting,this.activeThemeName=this.resolveThemeName(),markTerminalColorsPending(),initTheme(this.activeThemeName,!0),this.bindTerminalColorSchemeListener()}rebindTui(){this.terminalColorSchemeUnsubscribe?.(),this.bindTerminalColorSchemeListener(),this.ui.setTerminalColorSchemeNotifications(this.autoSyncEnabled)}applyFromSettings(){let themeSetting=this.getThemeSetting(),themeName=this.resolveThemeName();this.setAutoSync(parseAutoThemeSetting(themeSetting)!==void 0||themeName===SYSTEM_THEME_NAME),this.applyThemeName(themeName,themeSetting!==void 0),this.queryTerminalColors()}waitForTerminalColors(){return this.terminalColorQuery}getThemeSelection(){return this.currentThemeSetting??this.getSettingsManager().getThemeSetting()??this.activeThemeName}setThemeName(themeName,showError=!1){this.setAutoSync(themeName===SYSTEM_THEME_NAME);let result2=this.applyThemeName(themeName,showError);return result2.success&&(this.currentThemeSetting=themeName),result2}setThemeSetting(themeSetting){this.currentThemeSetting=themeSetting,this.applyFromSettings()}setThemeInstance(themeInstance){return this.setAutoSync(!1),setThemeInstance(themeInstance),this.activeThemeName="<in-memory>",this.notifyChanged(),{success:!0}}preview(themeSettingOrName){let themeName=resolveThemeSetting(themeSettingOrName,getTerminalTheme())??this.activeThemeName;themeName&&setTheme(themeName,!0).success&&(this.ui.invalidate(),this.ui.requestRender())}disableAutoSync(){this.setAutoSync(!1)}dispose(){this.setAutoSync(!1),this.terminalColorSchemeUnsubscribe?.(),this.terminalColorSchemeUnsubscribe=void 0}getTerminalTheme(){return getTerminalTheme()}getThemeSetting(){return this.currentThemeSetting??this.getSettingsManager().getThemeSetting()}resolveThemeName(){return resolveThemeSetting(this.getThemeSetting(),getTerminalTheme())??SYSTEM_THEME_NAME}applyThemeName(themeName,showError=!1){let result2=setTheme(themeName,!0);return this.activeThemeName=result2.success?themeName:SYSTEM_THEME_NAME,this.notifyChanged(),!result2.success&&showError&&this.showError(`Failed to load theme "${themeName}": ${result2.error}
|
|
1829
|
-
Fell back to the system theme.`),result2}queryTerminalColors(){this.terminalColorQuery=requestTerminalColors(this.ui,colors=>this.applyTerminalColors(colors))}applyTerminalColors(reported){let previous=this.terminalColors,next={foreground:reported.foreground??previous?.foreground,background:reported.background??previous?.background,palette:reported.palette??previous?.palette};previous&&sameTerminalColors(previous,next)||(this.terminalColors=next,setTerminalColors(next),this.reapplyForTerminal(),this.ui.invalidate(),this.ui.requestRender())}reapplyForTerminal(){if(this.activeThemeName==="<in-memory>")return;let themeName=this.resolveThemeName();(themeName===SYSTEM_THEME_NAME||themeName!==this.activeThemeName)&&this.applyThemeName(themeName)}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalColorSchemeChange(terminalTheme))}applyTerminalColorSchemeChange(terminalTheme){if(!this.autoSyncEnabled)return;let previous=getTerminalTheme();setTerminalColorScheme(terminalTheme),getTerminalTheme()!==previous&&this.reapplyForTerminal(),this.queryTerminalColors()}notifyChanged(){this.ui.invalidate(),this.onChanged()}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{render(width){let previous,previousHeight=0;for(let child of this.children){if(child instanceof ToolExecutionComponent){child.setLeadingGap(0);let lines=child.render(width),start=lines.findIndex(line=>stripAnsi(line).trim().length>0);if(start===-1)continue;let{afterTool,afterMultilineTool,afterOther}=toolStyle.gap;child.setLeadingGap(previous instanceof ToolExecutionComponent?previousHeight>1?afterMultilineTool:afterTool:afterOther),previousHeight=lines.length-start}previous=child}return super.render(width)}clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat2){disposeAll(chat2.children)}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??"auto",copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isEmbeddedStatus(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends ThemedText{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){let state2={expanded};super(()=>state2.expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.state=state2}setExpanded(expanded){this.state.expanded=expanded,this.invalidate()}},BuiltInHeader=class extends ExpandableText{handleMouse(event){if(!(event.type!=="click"||event.y>1||event.x<1||event.x>4||!this.onLogoClick))return this.onLogoClick(event.screenX-event.x+1,event.screenY-event.y),{handled:!0}}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN","ENOTTY"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value){return value.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var RADIUS_LOGIN_INTRO="Radius is a service crafted for Pi by the builders of Pi, Earendil Works",AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType],subscription:provider.subscription})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType,provider.subscription)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(authType=>formatAuthSelectorProviderType(authType,provider.subscription)).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.defaultHiddenThinkingLabel="Thinking...",this.hiddenThinkingLabel=this.defaultHiddenThinkingLabel,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.lastStatusMessage="",this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.programStatus=new ProgramStatusReporter(()=>this.ui.terminal,()=>this.sessionManager.getSessionName()),this.bugReportHintShown=!1,this.installChangeWarningShown=!1,this.extensionDialogs=[],this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.tasksUI?.dispose(),this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo||sourceInfo.source==="builtin")return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new ThemedText(()=>theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&this.shouldShowStartupDetails()){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,this.programStatus.report(),this.ensurePngTranscoder(),this.themeController.applyFromSettings(),await this.themeController.waitForTerminalColors(),this.shouldShowStartupHeader()){let showDetails=this.shouldShowStartupDetails(),showLogo=supportsPiLogo(),withLogo=hints=>{if(!showLogo)return`${piWordmark()} ${theme.fg("dim",`v${this.version}`)}
|
|
1803
|
+
Fell back to the system theme.`),result2}queryTerminalColors(){this.terminalColorQuery=requestTerminalColors(this.ui,colors=>this.applyTerminalColors(colors))}applyTerminalColors(reported){let previous=this.terminalColors,next={foreground:reported.foreground??previous?.foreground,background:reported.background??previous?.background,palette:reported.palette??previous?.palette};previous&&sameTerminalColors(previous,next)||(this.terminalColors=next,setTerminalColors(next),this.reapplyForTerminal(),this.ui.invalidate(),this.ui.requestRender())}reapplyForTerminal(){if(this.activeThemeName==="<in-memory>")return;let themeName=this.resolveThemeName();(themeName===SYSTEM_THEME_NAME||themeName!==this.activeThemeName)&&this.applyThemeName(themeName)}setAutoSync(enabled){this.autoSyncEnabled!==enabled&&(this.autoSyncEnabled=enabled,this.ui.setTerminalColorSchemeNotifications(enabled))}bindTerminalColorSchemeListener(){this.terminalColorSchemeUnsubscribe=this.ui.onTerminalColorSchemeChange(terminalTheme=>this.applyTerminalColorSchemeChange(terminalTheme))}applyTerminalColorSchemeChange(terminalTheme){if(!this.autoSyncEnabled)return;let previous=getTerminalTheme();setTerminalColorScheme(terminalTheme),getTerminalTheme()!==previous&&this.reapplyForTerminal(),this.queryTerminalColors()}notifyChanged(){this.ui.invalidate(),this.onChanged()}};function disposeAll(components){for(let component of components){let disposable=component;typeof disposable.dispose=="function"&&disposable.dispose()}}var ToolChatContainer=class extends Container{render(width){let previous,previousHeight=0;for(let child of this.children){if(child instanceof ToolExecutionComponent){child.setLeadingGap(0);let lines=child.render(width),start=lines.findIndex(line=>stripAnsi(line).trim().length>0);if(start===-1)continue;let{afterTool,afterMultilineTool,afterOther}=child.getToolRowGap();child.setLeadingGap(previous instanceof ToolExecutionComponent?previousHeight>1?afterMultilineTool:afterTool:afterOther),previousHeight=lines.length-start}previous=child}return super.render(width)}clear(){disposeAll(this.children),super.clear()}},PendingToolMap=class extends Map{clear(){disposeAll(this.values()),super.clear()}};function disposeChatRows(chat2){disposeAll(chat2.children)}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text2=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text2));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text2=>theme.underline(styleSearchMatch(text2)),searchCurrentMatchStyle:text2=>theme.bold(theme.inverse(styleSearchMatch(text2))),searchNavigationButtonStyle:(text2,hovered)=>hovered?theme.underline(text2):text2,scrollToEndIndicator:()=>{let shortcut=keyDisplayText("tui.altScreen.bottom"),label=` \u2193 Jump to latest message${shortcut?` \xB7 ${shortcut}`:""} `;return theme.bg("selectedBg",theme.fg("text",label))},openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??"auto",copySelection:async text2=>{try{return await copyToClipboard(text2),!0}catch(error){return error instanceof Error?error.message:String(error)}}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(`TUI property ${String(property)} is not callable`);methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}function isEmbeddedStatus(editor){return"embedWorkingStatus"in editor&&editor.embedWorkingStatus===!0&&"setWorkingStatusIndicator"in editor&&typeof editor.setWorkingStatusIndicator=="function"}function isExpandable(obj){return typeof obj=="object"&&obj!==null&&"setExpanded"in obj&&typeof obj.setExpanded=="function"}var ExpandableText=class extends ThemedText{constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){let state2={expanded};super(()=>state2.expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.state=state2}setExpanded(expanded){this.state.expanded=expanded,this.invalidate()}},BuiltInHeader=class extends ExpandableText{handleMouse(event){if(!(event.type!=="click"||event.y>1||event.x<1||event.x>4||!this.onLogoClick))return this.onLogoClick(event.screenX-event.x+1,event.screenY-event.y),{handled:!0}}};function isCustomSessionEntry(item){return"type"in item&&item.type==="custom"}function isCompactionCostNotice(item){return"type"in item&&item.type==="compaction_cost"}function isUsageSessionEntry(item){return"type"in item&&item.type==="usage"}var DEAD_TERMINAL_ERROR_CODES=new Set(["EIO","EPIPE","ENOTCONN","ENOTTY"]);function isDeadTerminalError(error){if(!error||typeof error!="object"||!("code"in error))return!1;let code=error.code;return code!==void 0&&DEAD_TERMINAL_ERROR_CODES.has(code)}function formatCrashExtensionHint(extensionMatches){let matches=Array.isArray(extensionMatches)?extensionMatches.filter(match2=>typeof match2=="string"&&match2.length>0):[];if(matches.length===0)return;let quoted=matches.map(match2=>`\`${match2}\``),labels=quoted.length===1?quoted[0]:quoted.length===2?quoted.join(" and "):`${quoted.slice(0,-1).join(", ")}, and ${quoted[quoted.length-1]}`,noun=matches.length===1?"extension":"extensions",pronoun=matches.length===1?"it":"them";return`A stack frame came from loaded ${noun} ${labels}, which may be involved. Try disabling ${pronoun} with \`${APP_NAME} config\`, or run \`${APP_NAME} -ne\` to confirm.`}var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function isAnthropicSubscriptionAuthKey(apiKey){return typeof apiKey=="string"&&apiKey.startsWith("sk-ant-oat")}function isUnknownModel(model){return!!model&&model.provider==="unknown"&&model.id==="unknown"&&model.api==="unknown"}function quoteIfNeeded(value){return value.length>0&&!/[^a-zA-Z0-9_\-./~:@]/.test(value)?value:`'${value.replace(/'/g,"'\\''")}'`}function formatResumeCommand(sessionManager){if(!process.stdout.isTTY||!sessionManager.isPersisted())return;let sessionFile=sessionManager.getSessionFile();if(!sessionFile||!fs8.existsSync(sessionFile))return;let args=[APP_NAME];return sessionManager.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(sessionManager.getSessionDir())),args.push("--session",sessionManager.getSessionId()),args.join(" ")}function hasDefaultModelProvider(providerId){return providerId in defaultModelPerProvider}function llamaCppPostLoginGuidance(actionLabel,loadedModelCount){return loadedModelCount===0?`${actionLabel}. No llama.cpp models are loaded. Use /llama to load a model, then /model to select it.`:`${actionLabel}. Use /model to select a loaded llama.cpp model, or /llama to manage models.`}var RADIUS_LOGIN_INTRO="Radius is a service crafted for Pi by the builders of Pi, Earendil Works",AUTH_TYPE_ORDER={oauth:0,api_key:1};function createFuzzyAutocompleteItems(items,prefix,getSearchText,toAutocompleteItem){let filtered=fuzzyFilter(items,prefix,getSearchText);return filtered.length===0?null:filtered.map(toAutocompleteItem)}function getLoginProviderCompletionOptions(providerOptions){let byId=new Map;for(let provider of providerOptions){let existing=byId.get(provider.id);if(existing){existing.authTypes.includes(provider.authType)||(existing.authTypes.push(provider.authType),existing.authTypes.sort((a,b2)=>AUTH_TYPE_ORDER[a]-AUTH_TYPE_ORDER[b2]));continue}byId.set(provider.id,{id:provider.id,name:provider.name,authTypes:[provider.authType],subscription:provider.subscription})}return Array.from(byId.values()).sort((a,b2)=>a.name.localeCompare(b2.name))}function getLoginProviderSearchText(provider){let authTypes=provider.authTypes.map(authType=>`${authType} ${formatAuthSelectorProviderType(authType,provider.subscription)}`).join(" ");return`${provider.id} ${provider.name} ${authTypes}`}function formatLoginProviderCompletionDescription(provider){let authTypes=provider.authTypes.map(authType=>formatAuthSelectorProviderType(authType,provider.subscription)).join("/");return provider.name===provider.id?authTypes:`${provider.name} \xB7 ${authTypes}`}var InteractiveMode=class _InteractiveMode{get session(){return this.runtimeHost.session}get agent(){return this.session.agent}get sessionManager(){return this.session.sessionManager}get settingsManager(){return this.session.settingsManager}constructor(runtimeHost,options={}){this.autocompleteProviderWrappers=[],this.isInitialized=!1,this.pendingUserInputs=[],this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.idleStatus=new IdleStatus,this.workingMessage=void 0,this.workingVisible=!0,this.workingIndicatorOptions=void 0,this.defaultWorkingMessage="Working",this.activeThinkingLabel=DEFAULT_ACTIVE_THINKING_LABEL,this.lastSigintTime=0,this.lastEscapeTime=0,this.changelogMarkdown=void 0,this.startupNoticesShown=!1,this.anthropicSubscriptionWarningShown=!1,this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.lastStatusMessage="",this.managedToolStatusStarted=!1,this.streamingComponent=void 0,this.entriesRenderedByBoundaryCompaction=new Set,this.streamingMessage=void 0,this.pendingTools=new PendingToolMap,this.editorHost=new InteractiveEditorHost({isSessionCommand:name=>this.session.extensionRunner.getCommand(name)!==void 0||this.session.promptTemplates.some(template=>template.name===name)||this.skillCommands.has(name),getEditor:()=>this.editor,getFocusedComponent:()=>this.renderer.getFocusedComponent(),hasOverlay:()=>this.ui.hasOverlay(),addTerminalInputListener:handler=>this.addExtensionTerminalInputListener(handler),setEditorText:text2=>this.editor.setText(text2),requestRender:()=>this.ui.requestRender(),showError:message=>this.showError(message)}),this.toolOutputExpanded=!1,this.hideThinkingBlock=!1,this.outputPad=1,this.mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme}),this.skillCommands=new Map,this.signalCleanupHandlers=[],this.isBashMode=!1,this.bashComponent=void 0,this.pendingBashComponents=[],this.compactionQueuedMessages=[],this.shutdownRequested=!1,this.programStatus=new ProgramStatusReporter(()=>this.ui.terminal,()=>this.sessionManager.getSessionName()),this.bugReportHintShown=!1,this.installChangeWarningShown=!1,this.extensionDialogs=[],this.extensionTerminalInputSubscriptions=new Set,this.extensionWidgetsAbove=new Map,this.extensionWidgetsBelow=new Map,this.customFooter=void 0,this.builtInHeader=void 0,this.customHeader=void 0,this.onRightClickPaste=()=>{this.handleRightClickPaste()},this.isShuttingDown=!1,this.runtimeHost=runtimeHost,setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options={...options,tuiMode},this.autoTrustOnReloadCwd=options.autoTrustOnReloadCwd,this.runtimeHost.setBeforeSessionInvalidate(()=>{this.resetExtensionUI()}),this.runtimeHost.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),terminal:options.terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new ToolChatContainer,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible,embedWorkingStatus:!0}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.sessionManager.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo||sourceInfo.source==="builtin")return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}getBuiltInCommandConflictDiagnostics(extensionRunner){let builtinNames=new Set(BUILTIN_SLASH_COMMANDS.map(command=>command.name));return extensionRunner.getRegisteredCommands().filter(command=>builtinNames.has(command.name)).map(command=>({type:"warning",message:command.invocationName===command.name?`Extension command '/${command.name}' conflicts with built-in interactive command. Skipping in autocomplete.`:`Extension command '/${command.name}' conflicts with built-in interactive command. Available as '/${command.invocationName}'.`,path:command.sourceInfo.path}))}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.session.scopedModels.length>0?this.session.scopedModels.map(s=>s.model):this.session.modelRuntime.getAvailableSnapshot();if(models.length===0)return null;let items=models.map(m2=>({id:m2.id,provider:m2.provider,name:m2.name,label:`${m2.provider}/${m2.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.session.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let templateCommands=this.session.promptTemplates.map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),extensionCommands=this.session.extensionRunner.getRegisteredCommands().filter(cmd=>!builtinCommandNames.has(cmd.name)).map(cmd=>({name:cmd.invocationName,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),getArgumentCompletions:cmd.getArgumentCompletions}));this.skillCommands.clear();let skillCommandList=[];if(this.settingsManager.getEnableSkillCommands())for(let skill of this.session.resourceLoader.getSkills().skills){let commandName=`skill:${skill.name}`;this.skillCommands.set(commandName,skill.filePath),skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...extensionCommands,...skillCommandList],this.sessionManager.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider(),triggerCharacters=[];for(let wrapProvider of this.autocompleteProviderWrappers)provider=wrapProvider(provider),triggerCharacters.push(...provider.triggerCharacters??[]);triggerCharacters.length>0&&(provider.triggerCharacters=[...new Set(triggerCharacters)]),this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),condensedText=`Updated to v${versionMatch?versionMatch[1]:this.version}. Use ${theme.bold("/changelog")} to view full changelog.`;this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new ThemedText(()=>theme.bold(theme.fg("accent","What's New")),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error("Fullscreen layout is not initialized");tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),this.rebindExtensionTerminalInputListeners(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.session.isStreaming||this.session.isCompacting)&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.session.scopedModels.length>0&&this.shouldShowStartupDetails()){let modelList=this.session.scopedModels.map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` (${formatKeyText(cycleKeys.join("/"),{capitalize:!0})} to cycle)`):"";console.log(theme.fg("dim",`Model scope: ${modelList}${cycleHint}`))}this.renderWidgets();let viewport=createChatViewport({document:this.documentContainer,pendingMessages:this.pendingMessagesContainer,status:this.statusContainer,widgetsAbove:this.widgetContainerAbove,editor:this.editorContainer,widgetsBelow:this.widgetContainerBelow,footer:this.footerContainer,scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarTrackStyle:text2=>theme.fg("scrollbarTrack",text2),scrollbarThumbStyle:text2=>theme.fg("scrollbarThumb",text2)});if(this.transcriptScrollView=viewport.transcript,this.fullscreenLayoutRoot=viewport.root,this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text2=>this.handleStartupSubmit(text2),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,this.programStatus.report(),this.ensurePngTranscoder(),this.themeController.applyFromSettings(),await this.themeController.waitForTerminalColors(),this.shouldShowStartupHeader()){let showDetails=this.shouldShowStartupDetails(),showLogo=supportsPiLogo(),withLogo=hints=>{if(!showLogo)return`${piWordmark()} ${theme.fg("dim",`v${this.version}`)}
|
|
1830
1804
|
${hints}`;let[top,bottom]=piLogoLines();return`${top} ${theme.fg("dim",`v${this.version}`)}
|
|
1831
1805
|
${bottom} ${hints}`},hint=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=()=>[hint("app.interrupt","to interrupt"),hint("app.clear","to clear"),rawKeyHint(`${keyText("app.clear")} twice`,"to exit"),hint("app.exit","to exit (empty)"),hint("app.suspend","to suspend"),keyHint("tui.editor.deleteToLineEnd","to delete to end"),hint("app.thinking.cycle","to cycle thinking level"),rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`,"to cycle models"),hint("app.model.select","to select model"),hint("app.tools.expand","to expand tools"),hint("app.thinking.toggle","to expand thinking"),hint("app.editor.external","for external editor"),rawKeyHint("/","for commands"),rawKeyHint("!","to run bash"),rawKeyHint("!!","to run bash (no context)"),hint("app.message.followUp","to queue follow-up"),hint("app.message.dequeue","to edit all queued messages"),hint("app.clipboard.pasteImage","to paste files on macOS, images, or text"),rawKeyHint("drop files","to attach")].join(`
|
|
1832
1806
|
`),compactInstructions=()=>[hint("app.interrupt","interrupt"),rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`,"clear/exit"),rawKeyHint("/","commands"),rawKeyHint("!","bash"),hint("app.tools.expand","more")].join(theme.fg("muted"," \xB7 ")),compactOnboarding=()=>theme.fg("dim",`Press ${keyText("app.tools.expand")} to show full startup help${showDetails?" and loaded resources":""}.`),onboarding=()=>theme.fg("dim","Pi can explain its own features and look up its docs. Ask it how to use or extend Pi."),header2=new BuiltInHeader(()=>`${withLogo(compactInstructions())}
|
|
@@ -1845,11 +1819,11 @@ ${expandedBody()}`,this.getStartupExpansionState(),0,0);this.loadedResourcesCont
|
|
|
1845
1819
|
${warningLines()}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let promptDiagnostics=promptsResult.diagnostics;if(promptDiagnostics.length>0){let warningLines=()=>this.formatDiagnostics(promptDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new ThemedText(()=>`${theme.fg("warning","[Prompt conflicts]")}
|
|
1846
1820
|
${warningLines()}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let extensionDiagnostics=[],extensionsResult=this.session.resourceLoader.getExtensions();for(let error of extensionsResult.errors)extensionDiagnostics.push({type:"error",message:error.error,path:error.path});for(let warning of extensionsResult.warnings??[])extensionDiagnostics.push({type:"warning",message:warning.warning,path:warning.path});let commandDiagnostics=this.session.extensionRunner.getCommandDiagnostics();extensionDiagnostics.push(...commandDiagnostics),extensionDiagnostics.push(...this.getBuiltInCommandConflictDiagnostics(this.session.extensionRunner));let shortcutDiagnostics=this.session.extensionRunner.getShortcutDiagnostics();if(extensionDiagnostics.push(...shortcutDiagnostics),extensionDiagnostics.length>0){let warningLines=()=>this.formatDiagnostics(extensionDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new ThemedText(()=>`${theme.fg("warning","[Extension issues]")}
|
|
1847
1821
|
${warningLines()}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}let themeDiagnostics=themesResult.diagnostics;if(themeDiagnostics.length>0){let warningLines=()=>this.formatDiagnostics(themeDiagnostics,sourceInfos);this.loadedResourcesContainer.addChild(new ThemedText(()=>`${theme.fg("warning","[Theme conflicts]")}
|
|
1848
|
-
${warningLines()}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}}}async bindCurrentSessionExtensions(){this.tasksUI?.dispose();let uiContext=this.createExtensionUIContext();await this.session.bindExtensions({uiContext,mode:"tui",tasksEnabled:!0,abortHandler:()=>{this.restoreQueuedMessagesToEditor({abort:!0})},commandContextActions:{waitForIdle:()=>this.session.waitForIdle(),newSession:async options=>{this.clearStatusIndicator();try{return await this.runtimeHost.newSession(options)}catch(error){return this.handleFatalRuntimeError("Failed to create session",error)}},fork:async(entryId,options)=>{try{let result2=await this.runtimeHost.fork(entryId,options);return result2.cancelled||(this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")),{cancelled:result2.cancelled}}catch(error){return this.handleFatalRuntimeError("Failed to fork session",error)}},navigateTree:async(targetId,options)=>{let result2=await this.session.navigateTree(targetId,{summarize:options?.summarize,customInstructions:options?.customInstructions,replaceInstructions:options?.replaceInstructions,label:options?.label});return result2.cancelled?{cancelled:!0}:(this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1}),{cancelled:!1})},switchSession:async(sessionPath,options)=>this.handleResumeSession(sessionPath,options),reload:async()=>{await this.handleReloadCommand()}},shutdownHandler:()=>{this.shutdownRequested=!0,this.session.isIdle&&this.shutdown()},onError:error=>{this.showExtensionError(error.extensionPath,error.error,error.stack)}}),this.tasksUI=bindTasksUI({tasks:this.session.tasks,ui:uiContext}),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.setupAutocompleteProvider();let extensionRunner=this.session.extensionRunner;this.setupExtensionShortcuts(extensionRunner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0}),this.showStartupNoticesIfNeeded()}applyFullscreenScrollbarSetting(){this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar())}ensurePngTranscoder(){ensurePngTranscoder(()=>{this.ui.invalidate(),this.ui.requestRender()})}applyRuntimeSettings(){setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides()),this.ensurePngTranscoder(),configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs()),this.applyFullscreenScrollbarSetting(),this.renderer instanceof TuiAltScreen&&(this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect()),this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines())),this.footer.setSession(this.session),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerDataProvider.setCwd(this.sessionManager.getCwd()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());let clearOnShrink=this.settingsManager.getClearOnShrink();this.ui.setClearOnShrink(clearOnShrink),!clearOnShrink&&!this.activeStatusIndicator&&this.statusContainer.clear();let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor.setPaddingX(editorPaddingX),this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible),this.editor!==this.defaultEditor&&(this.editor.setPaddingX?.(editorPaddingX),this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible))}async rebindCurrentSession(options={}){let session=this.session;this.unsubscribe?.(),this.unsubscribe=void 0,this.programStatus.reset(),this.applyRuntimeSettings(),options.renderBeforeBind&&(this.renderCurrentSessionState(),this.subscribeToAgent()),await this.bindCurrentSessionExtensions(),this.session===session&&(options.renderBeforeBind||this.subscribeToAgent(),await this.updateAvailableProviderCount(),this.updateEditorBorderColor(),this.updateTerminalTitle())}async handleFatalRuntimeError(prefix,error){let message=error instanceof Error?error.message:String(error);this.showError(`${prefix}: ${message}`);let extensionHint=this.getCrashExtensionHint(error);if(extensionHint&&this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",extensionHint),this.outputPad,0)),this.recordCrash("fatal_error",error)){let instructions=this.crashReportInstructions();this.chatContainer.addChild(new ThemedText(()=>theme.fg("muted",instructions),this.outputPad,0))}stopThemeWatcher(),this.stop("transcript"),process.exit(1)}getCrashExtensionHint(error){try{return formatCrashExtensionHint(findExtensionStackMatches(error instanceof Error?error.stack:void 0,this.session.resourceLoader.getExtensions().extensions))}catch{return}}recordCrash(kind,error){try{return recordCrash({kind,error,sessionFile:this.session.sessionFile,cwd:this.session.sessionManager.getCwd()})!==void 0}catch{return!1}}crashReportInstructions(){return`To report this crash: ${this.session.sessionFile?`run \`${APP_NAME} -r\` to resume the session, then`:"start pi and"} run /bug. The crash details are attached automatically.`}suggestBugReport(){this.bugReportHintShown||(this.bugReportHintShown=!0,this.chatContainer.addChild(new ThemedText(()=>theme.fg("muted",`If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`),this.outputPad,0)),this.ui.requestRender())}maybeSuggestBugReport(message){message.stopReason!=="error"||isRetryableAssistantError(message)||/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage??"")||this.maybeShowInstallChangeWarning()||this.suggestBugReport()}maybeShowInstallChangeWarning(){if(this.installChangeWarningShown)return!0;let change=detectInstallChange();if(!change)return!1;this.installChangeWarningShown=!0;let cause=change.kind==="updated"?`${APP_NAME} was updated to ${change.version} while this session was running (${VERSION})`:`The ${APP_NAME} installation this session runs from was removed or replaced`,resumeCommand=formatResumeCommand(this.sessionManager),restart=resumeCommand?`Restart with \`${resumeCommand}\` to continue this session.`:`Restart ${APP_NAME}.`;return this.showWarning(`${cause}. Features that load code on demand can fail until restart. ${restart}`),!0}renderCurrentSessionState(){this.loadedResourcesContainer.clear(),this.chatContainer.clear(),this.pendingMessagesContainer.clear(),this.compactionQueuedMessages=[],this.streamingComponent=void 0,this.streamingMessage=void 0,this.pendingTools.clear(),this.renderInitialMessages()}getRegisteredToolDefinition(toolName){return this.session.extensionRunner.resolveToolRenderers(toolName,()=>withBuiltInRenderers(toolName,this.session.getToolDefinition(toolName)))}getMarkdownTransformers(){return[this.mermaidMarkdownTransformer,...this.session.extensionRunner.getMarkdownTransformers()]}setupExtensionShortcuts(extensionRunner){let shortcuts=extensionRunner.getShortcuts(this.keybindings.getEffectiveConfig());shortcuts.size!==0&&(this.defaultEditor.onExtensionShortcut=data=>{for(let[shortcutStr,shortcut]of shortcuts)if(matchesKey(data,shortcutStr))return Promise.resolve(shortcut.handler(extensionRunner.createContext())).catch(err=>{this.showError(`Shortcut handler error: ${err instanceof Error?err.message:String(err)}`)}),!0;return!1})}setExtensionStatus(key,text2){this.footerDataProvider.setExtensionStatus(key,text2),this.ui.requestRender()}setEditorWorkingStatusIndicator(indicator){return this.defaultEditor.setWorkingStatusIndicator(void 0),isEmbeddedStatus(this.editor)?(this.editor.setWorkingStatusIndicator(indicator),!0):!1}showStatusIndicator(indicator){if(this.activeStatusIndicator?.dispose(),this.activeStatusIndicator=indicator,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),this.setEditorWorkingStatusIndicator(indicator)){this.activeWorkingIndicatorEmbedded=!0;return}this.statusContainer.addChild(indicator)}clearStatusIndicator(kind){if(kind&&this.activeStatusIndicator?.kind!==kind)return;let clearedIndicator=this.activeStatusIndicator,clearedIndicatorWasEmbedded=this.activeWorkingIndicatorEmbedded;clearedIndicator?.dispose(),this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),clearedIndicator&&!clearedIndicatorWasEmbedded&&this.options.tuiMode==="regular"&&this.ui.getClearOnShrink()&&this.statusContainer.addChild(this.idleStatus)}showWorkingStatusIndicator(){let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new WorkingStatusIndicator(this.ui,this.workingMessage??this.defaultWorkingMessage,this.workingIndicatorOptions,colorFn))}setWorkingVisible(visible){if(this.workingVisible=visible,!visible){this.clearStatusIndicator("working"),this.ui.requestRender();return}this.session.isStreaming&&this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator(),this.ui.requestRender()}setWorkingIndicator(options){this.workingIndicatorOptions=options,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setIndicator(options),this.ui.requestRender()}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label??this.defaultHiddenThinkingLabel;for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHiddenThinkingLabel(this.hiddenThinkingLabel);this.streamingComponent&&this.streamingComponent.setHiddenThinkingLabel(this.hiddenThinkingLabel),this.ui.requestRender()}setExtensionWidget(key,content,options){let placement=options?.placement??"aboveEditor",removeExisting=map=>{let existing=map.get(key);existing?.dispose&&existing.dispose(),map.delete(key)};if(removeExisting(this.extensionWidgetsAbove),removeExisting(this.extensionWidgetsBelow),content===void 0){this.renderWidgets();return}let component;if(Array.isArray(content)){let container=new Container;for(let line of content.slice(0,_InteractiveMode.MAX_WIDGET_LINES))container.addChild(new Text(line,1,0));content.length>_InteractiveMode.MAX_WIDGET_LINES&&container.addChild(new ThemedText(()=>theme.fg("muted","... (widget truncated)"),1,0)),component=container}else component=content(this.ui,theme);(placement==="belowEditor"?this.extensionWidgetsBelow:this.extensionWidgetsAbove).set(key,component),this.renderWidgets()}clearExtensionWidgets(){for(let widget of this.extensionWidgetsAbove.values())widget.dispose?.();for(let widget of this.extensionWidgetsBelow.values())widget.dispose?.();this.extensionWidgetsAbove.clear(),this.extensionWidgetsBelow.clear(),this.renderWidgets()}resetExtensionUI(){if(this.editorHost.clear(),this.extensionDialogs.length>0){for(let dialog of this.extensionDialogs)dialog.component.dispose?.();this.extensionDialogs=[],this.showTopExtensionDialog()}this.ui.hideOverlay(),this.clearExtensionTerminalInputListeners(),this.setExtensionFooter(void 0),this.setExtensionHeader(void 0),this.clearExtensionWidgets(),this.footerDataProvider.clearExtensionStatuses(),this.footer.invalidate(),this.autocompleteProviderWrappers=[],this.setCustomEditorComponent(void 0),this.setupAutocompleteProvider(),this.defaultEditor.onExtensionShortcut=void 0,this.updateTerminalTitle(),this.workingMessage=void 0,this.workingVisible=!0,this.setWorkingIndicator(),this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`),this.setHiddenThinkingLabel()}static{this.MAX_WIDGET_LINES=10}renderWidgets(){!this.widgetContainerAbove||!this.widgetContainerBelow||(this.renderWidgetContainer(this.widgetContainerAbove,this.extensionWidgetsAbove,!0,!0),this.renderWidgetContainer(this.widgetContainerBelow,this.extensionWidgetsBelow,!1,!1),this.ui.requestRender())}renderWidgetContainer(container,widgets,spacerWhenEmpty,leadingSpacer){if(container.clear(),widgets.size===0){spacerWhenEmpty&&container.addChild(new Spacer(1));return}leadingSpacer&&container.addChild(new Spacer(1));for(let component of widgets.values())container.addChild(component)}setExtensionFooter(factory){this.customFooter?.dispose&&this.customFooter.dispose(),this.footerContainer.clear(),factory?(this.customFooter=factory(this.ui,theme,this.footerDataProvider),this.footerContainer.addChild(this.customFooter)):(this.customFooter=void 0,this.footerContainer.addChild(this.footer)),this.ui.requestRender()}setExtensionHeader(factory){if(!this.builtInHeader)return;this.customHeader?.dispose&&this.customHeader.dispose();let currentHeader=this.customHeader||this.builtInHeader,index3=this.headerContainer.children.indexOf(currentHeader);factory?(this.customHeader=factory(this.ui,theme),isExpandable(this.customHeader)&&this.customHeader.setExpanded(this.toolOutputExpanded),index3!==-1?this.headerContainer.children[index3]=this.customHeader:this.headerContainer.children.unshift(this.customHeader)):(this.customHeader=void 0,isExpandable(this.builtInHeader)&&this.builtInHeader.setExpanded(this.toolOutputExpanded),index3!==-1&&(this.headerContainer.children[index3]=this.builtInHeader)),this.ui.requestRender()}addExtensionTerminalInputListener(handler){let subscription={handler,unsubscribe:this.ui.addInputListener(handler)};return this.extensionTerminalInputSubscriptions.add(subscription),()=>{subscription.unsubscribe(),this.extensionTerminalInputSubscriptions.delete(subscription)}}rebindExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe(),subscription.unsubscribe=this.ui.addInputListener(subscription.handler)}clearExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe();this.extensionTerminalInputSubscriptions.clear()}createProjectTrustContext(cwd){let ui=this.createExtensionUIContext();return{cwd,mode:"tui",hasUI:!0,ui:{select:ui.select,confirm:ui.confirm,input:ui.input,notify:ui.notify}}}createExtensionUIContext(){return{select:(title,options,opts)=>this.showExtensionSelector(title,options,opts),confirm:(title,message,opts)=>this.showExtensionConfirm(title,message,opts),input:(title,placeholder,opts)=>this.showExtensionInput(title,placeholder,opts),notify:(message,type)=>this.showExtensionNotify(message,type),onTerminalInput:handler=>this.addExtensionTerminalInputListener(handler),editorHost:this.editorHost,setStatus:(key,text2)=>this.setExtensionStatus(key,text2),setWorkingMessage:message=>{this.workingMessage=message,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(message??this.defaultWorkingMessage)},setWorkingVisible:visible=>this.setWorkingVisible(visible),setWorkingIndicator:options=>this.setWorkingIndicator(options),setHiddenThinkingLabel:label=>this.setHiddenThinkingLabel(label),setWidget:(key,content,options)=>this.setExtensionWidget(key,content,options),setFooter:factory=>this.setExtensionFooter(factory),setHeader:factory=>this.setExtensionHeader(factory),setTitle:title=>this.ui.terminal.setTitle(title),custom:(factory,options)=>this.showExtensionCustom(factory,options),pasteToEditor:text2=>this.editor.handleInput(`\x1B[200~${text2}\x1B[201~`),setEditorText:text2=>this.editor.setText(text2),getEditorText:()=>this.editor.getExpandedText?.()??this.editor.getText(),editor:(title,prefill)=>this.showExtensionEditor(title,prefill),addAutocompleteProvider:factory=>{this.autocompleteProviderWrappers.push(factory),this.setupAutocompleteProvider()},setEditorComponent:factory=>this.setCustomEditorComponent(factory),getEditorComponent:()=>this.editorComponentFactory,get theme(){return theme},getAllThemes:()=>getAvailableThemesWithPaths(),getTheme:name=>getThemeByName(name),setTheme:themeOrName=>{if(themeOrName instanceof Theme)return this.themeController.setThemeInstance(themeOrName);let result2=this.themeController.setThemeName(themeOrName);return result2.success&&this.settingsManager.getTheme()!==themeOrName&&this.settingsManager.setTheme(themeOrName),result2},getToolsExpanded:()=>this.toolOutputExpanded,setToolsExpanded:expanded=>this.setToolsExpanded(expanded)}}pushExtensionDialog(component,blocked){this.disposeActiveSelector(),this.extensionDialogs.push({component,blocked}),this.showTopExtensionDialog()}removeExtensionDialog(component){let index3=this.extensionDialogs.findIndex(dialog=>dialog.component===component);index3!==-1&&(this.extensionDialogs.splice(index3,1),index3===this.extensionDialogs.length&&this.showTopExtensionDialog())}showTopExtensionDialog(){let top=this.extensionDialogs.at(-1),component=top?.component??this.editor;this.editorContainer.clear(),this.editorContainer.addChild(component),this.ui.setFocus(component),this.programStatus.setBlocked("extension-dialog",top?.blocked),this.ui.requestRender()}showExtensionSelector(title,options,opts,blocked={kind:"question",message:title}){return new Promise(resolve20=>{if(opts?.signal?.aborted){resolve20(void 0);return}let finish=option=>{opts?.signal?.removeEventListener("abort",onAbort),selector.dispose(),this.removeExtensionDialog(selector),resolve20(option)},onAbort=()=>finish(void 0);opts?.signal?.addEventListener("abort",onAbort,{once:!0});let selector=new ExtensionSelectorComponent(title,options,option=>finish(option),()=>finish(void 0),{tui:this.ui,timeout:opts?.timeout,description:opts?.description,onToggleToolsExpanded:()=>this.toggleToolOutputExpansion()});this.pushExtensionDialog(selector,blocked)})}async showExtensionConfirm(title,message,opts){return await this.showExtensionSelector(title,["Yes","No"],{...opts,description:message},{kind:"permission",message:title})==="Yes"}async promptForMissingSessionCwd(error){return await this.showExtensionConfirm("Session cwd not found",formatMissingSessionCwdPrompt(error.issue))?error.issue.fallbackCwd:void 0}showExtensionInput(title,placeholder,opts){return new Promise(resolve20=>{if(opts?.signal?.aborted){resolve20(void 0);return}let finish=value=>{opts?.signal?.removeEventListener("abort",onAbort),input2.dispose(),this.removeExtensionDialog(input2),resolve20(value)},onAbort=()=>finish(void 0);opts?.signal?.addEventListener("abort",onAbort,{once:!0});let input2=new ExtensionInputComponent(title,placeholder,value=>finish(value),()=>finish(void 0),{tui:this.ui,timeout:opts?.timeout});this.pushExtensionDialog(input2,{kind:"question",message:title})})}showExtensionEditor(title,prefill){return new Promise(resolve20=>{let finish=value=>{this.removeExtensionDialog(editor),resolve20(value)},editor=new ExtensionEditorComponent(this.ui,this.keybindings,title,prefill,value=>finish(value),()=>finish(void 0),void 0,this.settingsManager.getExternalEditorCommand());this.pushExtensionDialog(editor,{kind:"question",message:title})})}setCustomEditorComponent(factory){this.editorComponentFactory=factory;let currentText=this.editor.getText();if(this.disposeActiveSelector(),this.editorContainer.clear(),factory){let newEditor=factory(this.ui,getEditorTheme(),this.keybindings);newEditor.onSubmit=this.defaultEditor.onSubmit,newEditor.onChange=this.defaultEditor.onChange,newEditor.setText(currentText),newEditor.borderColor!==void 0&&(newEditor.borderColor=this.defaultEditor.borderColor),newEditor.setPaddingX!==void 0&&newEditor.setPaddingX(this.defaultEditor.getPaddingX()),newEditor.setAutocompleteMaxVisible!==void 0&&newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible()),newEditor.setAutocompleteProvider&&this.autocompleteProvider&&newEditor.setAutocompleteProvider(this.autocompleteProvider);let customEditor=newEditor;if("actionHandlers"in customEditor&&customEditor.actionHandlers instanceof Map){customEditor.onEscape||(customEditor.onEscape=()=>this.defaultEditor.onEscape?.()),customEditor.onCtrlD||(customEditor.onCtrlD=()=>this.defaultEditor.onCtrlD?.()),customEditor.onPasteImage||(customEditor.onPasteImage=()=>this.defaultEditor.onPasteImage?.()),customEditor.onExtensionShortcut||(customEditor.onExtensionShortcut=data=>this.defaultEditor.onExtensionShortcut?.(data));for(let[action,handler]of this.defaultEditor.actionHandlers)customEditor.actionHandlers.set(action,handler)}this.editor=newEditor}else this.defaultEditor.setText(currentText),this.editor=this.defaultEditor;this.editorContainer.addChild(this.editor),this.activeStatusIndicator&&(this.statusContainer.clear(),this.activeWorkingIndicatorEmbedded=this.setEditorWorkingStatusIndicator(this.activeStatusIndicator),this.activeWorkingIndicatorEmbedded||this.statusContainer.addChild(this.activeStatusIndicator)),this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionNotify(message,type){type==="error"?this.showError(message):type==="warning"?this.showWarning(message):this.showStatus(message)}async showExtensionCustom(factory,options){let savedText2=this.editor.getText(),isOverlay=options?.overlay??!1;return new Promise((resolve20,reject)=>{let component,overlayHandle,closed=!1,restoreEditor3=()=>{component&&this.removeExtensionDialog(component),this.editor.setText(savedText2),this.ui.requestRender()},close=result2=>{if(!closed){closed=!0,isOverlay?overlayHandle?.hide():restoreEditor3(),resolve20(result2);try{component?.dispose?.()}catch{}}};Promise.resolve(factory(this.ui,theme,this.keybindings,close)).then(c=>{if(!closed)if(component=c,isOverlay){let resolveOptions=()=>{if(options?.overlayOptions)return typeof options.overlayOptions=="function"?options.overlayOptions():options.overlayOptions;let w=c.width;return w?{width:w}:void 0};overlayHandle=this.ui.showOverlay(c,resolveOptions()),options?.onHandle?.(overlayHandle)}else this.pushExtensionDialog(c)}).catch(err=>{closed||(isOverlay||restoreEditor3(),reject(err))})})}showExtensionError(extensionPath,error,stack){let errorMsg=`Extension "${extensionPath}" error: ${error}`,errorText3=new ThemedText(()=>theme.fg("error",errorMsg),1,0);if(this.chatContainer.addChild(errorText3),stack){let stackLines=stack.split(`
|
|
1822
|
+
${warningLines()}`,0,0)),this.loadedResourcesContainer.addChild(new Spacer(1))}}}async bindCurrentSessionExtensions(){let uiContext=this.createExtensionUIContext();await this.session.bindExtensions({uiContext,mode:"tui",tasksEnabled:!0,abortHandler:()=>{this.restoreQueuedMessagesToEditor({abort:!0})},commandContextActions:{waitForIdle:()=>this.session.waitForIdle(),newSession:async options=>{this.clearStatusIndicator();try{return await this.runtimeHost.newSession(options)}catch(error){return this.handleFatalRuntimeError("Failed to create session",error)}},fork:async(entryId,options)=>{try{let result2=await this.runtimeHost.fork(entryId,options);return result2.cancelled||(this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")),{cancelled:result2.cancelled}}catch(error){return this.handleFatalRuntimeError("Failed to fork session",error)}},navigateTree:async(targetId,options)=>{let result2=await this.session.navigateTree(targetId,{summarize:options?.summarize,customInstructions:options?.customInstructions,replaceInstructions:options?.replaceInstructions,label:options?.label});return result2.cancelled?{cancelled:!0}:(this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1}),{cancelled:!1})},switchSession:async(sessionPath,options)=>this.handleResumeSession(sessionPath,options),reload:async()=>{await this.handleReloadCommand()}},shutdownHandler:()=>{this.shutdownRequested=!0,this.session.isIdle&&this.shutdown()},onError:error=>{this.showExtensionError(error.extensionPath,error.error,error.stack)}}),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.setupAutocompleteProvider();let extensionRunner=this.session.extensionRunner;this.setupExtensionShortcuts(extensionRunner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0}),this.showStartupNoticesIfNeeded()}applyFullscreenScrollbarSetting(){this.transcriptScrollView?.setScrollbar(this.settingsManager.getFullscreenScrollbar())}ensurePngTranscoder(){ensurePngTranscoder(()=>{this.ui.invalidate(),this.ui.requestRender()})}applyRuntimeSettings(){setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides()),this.ensurePngTranscoder(),configureHttpDispatcher(this.settingsManager.getHttpIdleTimeoutMs()),this.applyFullscreenScrollbarSetting(),this.renderer instanceof TuiAltScreen&&(this.renderer.setCopyOnSelect(this.settingsManager.getFullscreenCopyOnSelect()),this.renderer.setWheelScrollLines(this.settingsManager.getFullscreenWheelScrollLines())),this.footer.setSession(this.session),this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled),this.footerDataProvider.setCwd(this.sessionManager.getCwd()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());let clearOnShrink=this.settingsManager.getClearOnShrink();this.ui.setClearOnShrink(clearOnShrink),!clearOnShrink&&!this.activeStatusIndicator&&this.statusContainer.clear();let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor.setPaddingX(editorPaddingX),this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible),this.editor!==this.defaultEditor&&(this.editor.setPaddingX?.(editorPaddingX),this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible))}async rebindCurrentSession(options={}){let session=this.session;this.unsubscribe?.(),this.unsubscribe=void 0,this.programStatus.reset(),this.applyRuntimeSettings(),options.renderBeforeBind&&(this.renderCurrentSessionState(),this.subscribeToAgent()),await this.bindCurrentSessionExtensions(),this.session===session&&(options.renderBeforeBind||this.subscribeToAgent(),await this.updateAvailableProviderCount(),this.updateEditorBorderColor(),this.updateTerminalTitle())}async handleFatalRuntimeError(prefix,error){let message=error instanceof Error?error.message:String(error);this.showError(`${prefix}: ${message}`);let extensionHint=this.getCrashExtensionHint(error);if(extensionHint&&this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",extensionHint),this.outputPad,0)),this.recordCrash("fatal_error",error)){let instructions=this.crashReportInstructions();this.chatContainer.addChild(new ThemedText(()=>theme.fg("muted",instructions),this.outputPad,0))}stopThemeWatcher(),this.stop("transcript"),process.exit(1)}getCrashExtensionHint(error){try{return formatCrashExtensionHint(findExtensionStackMatches(error instanceof Error?error.stack:void 0,this.session.resourceLoader.getExtensions().extensions))}catch{return}}recordCrash(kind,error){try{return recordCrash({kind,error,sessionFile:this.session.sessionFile,cwd:this.session.sessionManager.getCwd()})!==void 0}catch{return!1}}crashReportInstructions(){return`To report this crash: ${this.session.sessionFile?`run \`${APP_NAME} -r\` to resume the session, then`:"start pi and"} run /bug. The crash details are attached automatically.`}suggestBugReport(){this.bugReportHintShown||(this.bugReportHintShown=!0,this.chatContainer.addChild(new ThemedText(()=>theme.fg("muted",`If this looks like a ${APP_NAME} bug, /bug sends a report to the developers.`),this.outputPad,0)),this.ui.requestRender())}maybeSuggestBugReport(message){message.stopReason!=="error"||isRetryableAssistantError(message)||/\b(?:abort(?:ed)?|cancel(?:l?ed)?)\b/i.test(message.errorMessage??"")||this.maybeShowInstallChangeWarning()||this.suggestBugReport()}maybeShowInstallChangeWarning(){if(this.installChangeWarningShown)return!0;let change=detectInstallChange();if(!change)return!1;this.installChangeWarningShown=!0;let cause=change.kind==="updated"?`${APP_NAME} was updated to ${change.version} while this session was running (${VERSION})`:`The ${APP_NAME} installation this session runs from was removed or replaced`,resumeCommand=formatResumeCommand(this.sessionManager),restart=resumeCommand?`Restart with \`${resumeCommand}\` to continue this session.`:`Restart ${APP_NAME}.`;return this.showWarning(`${cause}. Features that load code on demand can fail until restart. ${restart}`),!0}renderCurrentSessionState(){this.loadedResourcesContainer.clear(),this.chatContainer.clear(),this.pendingMessagesContainer.clear(),this.compactionQueuedMessages=[],this.streamingComponent=void 0,this.streamingMessage=void 0,this.pendingTools.clear(),this.renderInitialMessages()}getRegisteredToolDefinition(toolName){return this.session.extensionRunner.resolveToolRenderers(toolName,()=>withBuiltInRenderers(toolName,this.session.getToolDefinition(toolName)))}getMarkdownTransformers(){return[this.mermaidMarkdownTransformer,...this.session.extensionRunner.getMarkdownTransformers()]}setupExtensionShortcuts(extensionRunner){let shortcuts=extensionRunner.getShortcuts(this.keybindings.getEffectiveConfig());shortcuts.size!==0&&(this.defaultEditor.onExtensionShortcut=data=>{for(let[shortcutStr,shortcut]of shortcuts)if(matchesKey(data,shortcutStr))return Promise.resolve(shortcut.handler(extensionRunner.createContext())).catch(err=>{this.showError(`Shortcut handler error: ${err instanceof Error?err.message:String(err)}`)}),!0;return!1})}setExtensionStatus(key,text2){this.footerDataProvider.setExtensionStatus(key,text2),this.ui.requestRender()}setEditorWorkingStatusIndicator(indicator){return this.defaultEditor.setWorkingStatusIndicator(void 0),isEmbeddedStatus(this.editor)?(this.editor.setWorkingStatusIndicator(indicator),!0):!1}showStatusIndicator(indicator){if(this.activeStatusIndicator?.dispose(),this.activeStatusIndicator=indicator,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),this.setEditorWorkingStatusIndicator(indicator)){this.activeWorkingIndicatorEmbedded=!0;return}this.statusContainer.addChild(indicator)}clearStatusIndicator(kind){if(kind&&this.activeStatusIndicator?.kind!==kind)return;let clearedIndicator=this.activeStatusIndicator,clearedIndicatorWasEmbedded=this.activeWorkingIndicatorEmbedded;clearedIndicator?.dispose(),this.activeStatusIndicator=void 0,this.activeWorkingIndicatorEmbedded=!1,this.statusContainer.clear(),this.setEditorWorkingStatusIndicator(void 0),clearedIndicator&&!clearedIndicatorWasEmbedded&&this.options.tuiMode==="regular"&&this.ui.getClearOnShrink()&&this.statusContainer.addChild(this.idleStatus)}showWorkingStatusIndicator(){let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new WorkingStatusIndicator(this.ui,this.workingMessage??this.defaultWorkingMessage,this.workingIndicatorOptions,colorFn))}setWorkingVisible(visible){if(this.workingVisible=visible,!visible){this.clearStatusIndicator("working"),this.ui.requestRender();return}this.session.isStreaming&&this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator(),this.ui.requestRender()}setWorkingIndicator(options){this.workingIndicatorOptions=options,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setIndicator(options),this.ui.requestRender()}setHiddenThinkingLabel(label){this.activeThinkingLabel=label??DEFAULT_ACTIVE_THINKING_LABEL;for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHiddenThinkingLabel(this.activeThinkingLabel);this.streamingComponent&&this.streamingComponent.setHiddenThinkingLabel(this.activeThinkingLabel),this.ui.requestRender()}setExtensionWidget(key,content,options){let placement=options?.placement??"aboveEditor",removeExisting=map=>{let existing=map.get(key);existing?.dispose&&existing.dispose(),map.delete(key)};if(removeExisting(this.extensionWidgetsAbove),removeExisting(this.extensionWidgetsBelow),content===void 0){this.renderWidgets();return}let component;if(Array.isArray(content)){let container=new Container;for(let line of content.slice(0,_InteractiveMode.MAX_WIDGET_LINES))container.addChild(new Text(line,1,0));content.length>_InteractiveMode.MAX_WIDGET_LINES&&container.addChild(new ThemedText(()=>theme.fg("muted","... (widget truncated)"),1,0)),component=container}else component=content(this.ui,theme);(placement==="belowEditor"?this.extensionWidgetsBelow:this.extensionWidgetsAbove).set(key,component),this.renderWidgets()}clearExtensionWidgets(){for(let widget of this.extensionWidgetsAbove.values())widget.dispose?.();for(let widget of this.extensionWidgetsBelow.values())widget.dispose?.();this.extensionWidgetsAbove.clear(),this.extensionWidgetsBelow.clear(),this.renderWidgets()}resetExtensionUI(){if(this.editorHost.clear(),this.extensionDialogs.length>0){for(let dialog of this.extensionDialogs)dialog.component.dispose?.();this.extensionDialogs=[],this.showTopExtensionDialog()}this.ui.hideOverlay(),this.clearExtensionTerminalInputListeners(),this.setExtensionFooter(void 0),this.setExtensionHeader(void 0),this.clearExtensionWidgets(),this.footerDataProvider.clearExtensionStatuses(),this.footer.invalidate(),this.autocompleteProviderWrappers=[],this.setCustomEditorComponent(void 0),this.setupAutocompleteProvider(),this.defaultEditor.onExtensionShortcut=void 0,this.updateTerminalTitle(),this.workingMessage=void 0,this.workingVisible=!0,this.setWorkingIndicator(),this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`),this.setHiddenThinkingLabel()}static{this.MAX_WIDGET_LINES=10}renderWidgets(){!this.widgetContainerAbove||!this.widgetContainerBelow||(this.renderWidgetContainer(this.widgetContainerAbove,this.extensionWidgetsAbove,!0,!0),this.renderWidgetContainer(this.widgetContainerBelow,this.extensionWidgetsBelow,!1,!1),this.ui.requestRender())}renderWidgetContainer(container,widgets,spacerWhenEmpty,leadingSpacer){if(container.clear(),widgets.size===0){spacerWhenEmpty&&container.addChild(new Spacer(1));return}leadingSpacer&&container.addChild(new Spacer(1));for(let component of widgets.values())container.addChild(component)}setExtensionFooter(factory){this.customFooter?.dispose&&this.customFooter.dispose(),this.footerContainer.clear(),factory?(this.customFooter=factory(this.ui,theme,this.footerDataProvider),this.footerContainer.addChild(this.customFooter)):(this.customFooter=void 0,this.footerContainer.addChild(this.footer)),this.ui.requestRender()}setExtensionHeader(factory){if(!this.builtInHeader)return;this.customHeader?.dispose&&this.customHeader.dispose();let currentHeader=this.customHeader||this.builtInHeader,index3=this.headerContainer.children.indexOf(currentHeader);factory?(this.customHeader=factory(this.ui,theme),isExpandable(this.customHeader)&&this.customHeader.setExpanded(this.toolOutputExpanded),index3!==-1?this.headerContainer.children[index3]=this.customHeader:this.headerContainer.children.unshift(this.customHeader)):(this.customHeader=void 0,isExpandable(this.builtInHeader)&&this.builtInHeader.setExpanded(this.toolOutputExpanded),index3!==-1&&(this.headerContainer.children[index3]=this.builtInHeader)),this.ui.requestRender()}addExtensionTerminalInputListener(handler){let subscription={handler,unsubscribe:this.ui.addInputListener(handler)};return this.extensionTerminalInputSubscriptions.add(subscription),()=>{subscription.unsubscribe(),this.extensionTerminalInputSubscriptions.delete(subscription)}}rebindExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe(),subscription.unsubscribe=this.ui.addInputListener(subscription.handler)}clearExtensionTerminalInputListeners(){for(let subscription of this.extensionTerminalInputSubscriptions)subscription.unsubscribe();this.extensionTerminalInputSubscriptions.clear()}createProjectTrustContext(cwd){let ui=this.createExtensionUIContext();return{cwd,mode:"tui",hasUI:!0,ui:{select:ui.select,confirm:ui.confirm,input:ui.input,notify:ui.notify}}}createExtensionUIContext(){return{select:(title,options,opts)=>this.showExtensionSelector(title,options,opts),confirm:(title,message,opts)=>this.showExtensionConfirm(title,message,opts),input:(title,placeholder,opts)=>this.showExtensionInput(title,placeholder,opts),notify:(message,type)=>this.showExtensionNotify(message,type),onTerminalInput:handler=>this.addExtensionTerminalInputListener(handler),editorHost:this.editorHost,setStatus:(key,text2)=>this.setExtensionStatus(key,text2),setWorkingMessage:message=>{this.workingMessage=message,this.activeStatusIndicator?.kind==="working"&&this.activeStatusIndicator.setMessage(message??this.defaultWorkingMessage)},setWorkingVisible:visible=>this.setWorkingVisible(visible),setWorkingIndicator:options=>this.setWorkingIndicator(options),setHiddenThinkingLabel:label=>this.setHiddenThinkingLabel(label),setWidget:(key,content,options)=>this.setExtensionWidget(key,content,options),setFooter:factory=>this.setExtensionFooter(factory),setHeader:factory=>this.setExtensionHeader(factory),setTitle:title=>this.ui.terminal.setTitle(title),custom:(factory,options)=>this.showExtensionCustom(factory,options),pasteToEditor:text2=>this.editor.handleInput(`\x1B[200~${text2}\x1B[201~`),setEditorText:text2=>this.editor.setText(text2),getEditorText:()=>this.editor.getExpandedText?.()??this.editor.getText(),editor:(title,prefill)=>this.showExtensionEditor(title,prefill),addAutocompleteProvider:factory=>{this.autocompleteProviderWrappers.push(factory),this.setupAutocompleteProvider()},setEditorComponent:factory=>this.setCustomEditorComponent(factory),getEditorComponent:()=>this.editorComponentFactory,get theme(){return theme},getAllThemes:()=>getAvailableThemesWithPaths(),getTheme:name=>getThemeByName(name),setTheme:themeOrName=>{if(themeOrName instanceof Theme)return this.themeController.setThemeInstance(themeOrName);let result2=this.themeController.setThemeName(themeOrName);return result2.success&&this.settingsManager.getTheme()!==themeOrName&&this.settingsManager.setTheme(themeOrName),result2},getToolsExpanded:()=>this.toolOutputExpanded,setToolsExpanded:expanded=>this.setToolsExpanded(expanded)}}pushExtensionDialog(component,blocked){this.disposeActiveSelector(),this.extensionDialogs.push({component,blocked}),this.showTopExtensionDialog()}removeExtensionDialog(component){let index3=this.extensionDialogs.findIndex(dialog=>dialog.component===component);index3!==-1&&(this.extensionDialogs.splice(index3,1),index3===this.extensionDialogs.length&&this.showTopExtensionDialog())}showTopExtensionDialog(){let top=this.extensionDialogs.at(-1),component=top?.component??this.editor;this.editorContainer.clear(),this.editorContainer.addChild(component),this.ui.setFocus(component),this.programStatus.setBlocked("extension-dialog",top?.blocked),this.ui.requestRender()}showExtensionSelector(title,options,opts,blocked={kind:"question",message:title}){return new Promise(resolve20=>{if(opts?.signal?.aborted){resolve20(void 0);return}let finish=option=>{opts?.signal?.removeEventListener("abort",onAbort),selector.dispose(),this.removeExtensionDialog(selector),resolve20(option)},onAbort=()=>finish(void 0);opts?.signal?.addEventListener("abort",onAbort,{once:!0});let selector=new ExtensionSelectorComponent(title,options,option=>finish(option),()=>finish(void 0),{tui:this.ui,timeout:opts?.timeout,description:opts?.description,onToggleToolsExpanded:()=>this.toggleToolOutputExpansion()});this.pushExtensionDialog(selector,blocked)})}async showExtensionConfirm(title,message,opts){return await this.showExtensionSelector(title,["Yes","No"],{...opts,description:message},{kind:"permission",message:title})==="Yes"}async promptForMissingSessionCwd(error){return await this.showExtensionConfirm("Session cwd not found",formatMissingSessionCwdPrompt(error.issue))?error.issue.fallbackCwd:void 0}showExtensionInput(title,placeholder,opts){return new Promise(resolve20=>{if(opts?.signal?.aborted){resolve20(void 0);return}let finish=value=>{opts?.signal?.removeEventListener("abort",onAbort),input2.dispose(),this.removeExtensionDialog(input2),resolve20(value)},onAbort=()=>finish(void 0);opts?.signal?.addEventListener("abort",onAbort,{once:!0});let input2=new ExtensionInputComponent(title,placeholder,value=>finish(value),()=>finish(void 0),{tui:this.ui,timeout:opts?.timeout});this.pushExtensionDialog(input2,{kind:"question",message:title})})}showExtensionEditor(title,prefill){return new Promise(resolve20=>{let finish=value=>{this.removeExtensionDialog(editor),resolve20(value)},editor=new ExtensionEditorComponent(this.ui,this.keybindings,title,prefill,value=>finish(value),()=>finish(void 0),void 0,this.settingsManager.getExternalEditorCommand());this.pushExtensionDialog(editor,{kind:"question",message:title})})}setCustomEditorComponent(factory){this.editorComponentFactory=factory;let currentText=this.editor.getText();if(this.disposeActiveSelector(),this.editorContainer.clear(),factory){let newEditor=factory(this.ui,getEditorTheme(),this.keybindings);newEditor.onSubmit=this.defaultEditor.onSubmit,newEditor.onChange=this.defaultEditor.onChange,newEditor.setText(currentText),newEditor.borderColor!==void 0&&(newEditor.borderColor=this.defaultEditor.borderColor),newEditor.setPaddingX!==void 0&&newEditor.setPaddingX(this.defaultEditor.getPaddingX()),newEditor.setAutocompleteMaxVisible!==void 0&&newEditor.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible()),newEditor.setAutocompleteProvider&&this.autocompleteProvider&&newEditor.setAutocompleteProvider(this.autocompleteProvider);let customEditor=newEditor;if("actionHandlers"in customEditor&&customEditor.actionHandlers instanceof Map){customEditor.onEscape||(customEditor.onEscape=()=>this.defaultEditor.onEscape?.()),customEditor.onCtrlD||(customEditor.onCtrlD=()=>this.defaultEditor.onCtrlD?.()),customEditor.onPasteImage||(customEditor.onPasteImage=()=>this.defaultEditor.onPasteImage?.()),customEditor.onExtensionShortcut||(customEditor.onExtensionShortcut=data=>this.defaultEditor.onExtensionShortcut?.(data));for(let[action,handler]of this.defaultEditor.actionHandlers)customEditor.actionHandlers.set(action,handler)}this.editor=newEditor}else this.defaultEditor.setText(currentText),this.editor=this.defaultEditor;this.editorContainer.addChild(this.editor),this.activeStatusIndicator&&(this.statusContainer.clear(),this.activeWorkingIndicatorEmbedded=this.setEditorWorkingStatusIndicator(this.activeStatusIndicator),this.activeWorkingIndicatorEmbedded||this.statusContainer.addChild(this.activeStatusIndicator)),this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionNotify(message,type){type==="error"?this.showError(message):type==="warning"?this.showWarning(message):this.showStatus(message)}async showExtensionCustom(factory,options){let savedText2=this.editor.getText(),isOverlay=options?.overlay??!1;return new Promise((resolve20,reject)=>{let component,overlayHandle,closed=!1,restoreEditor3=()=>{component&&this.removeExtensionDialog(component),this.editor.setText(savedText2),this.ui.requestRender()},close=result2=>{if(!closed){closed=!0,isOverlay?overlayHandle?.hide():restoreEditor3(),resolve20(result2);try{component?.dispose?.()}catch{}}};Promise.resolve(factory(this.ui,theme,this.keybindings,close)).then(c=>{if(!closed)if(component=c,isOverlay){let resolveOptions=()=>{if(options?.overlayOptions)return typeof options.overlayOptions=="function"?options.overlayOptions():options.overlayOptions;let w=c.width;return w?{width:w}:void 0};overlayHandle=this.ui.showOverlay(c,resolveOptions()),options?.onHandle?.(overlayHandle)}else this.pushExtensionDialog(c)}).catch(err=>{closed||(isOverlay||restoreEditor3(),reject(err))})})}showExtensionError(extensionPath,error,stack){let errorMsg=`Extension "${extensionPath}" error: ${error}`,errorText3=new ThemedText(()=>theme.fg("error",errorMsg),1,0);if(this.chatContainer.addChild(errorText3),stack){let stackLines=stack.split(`
|
|
1849
1823
|
`).slice(1);if(stackLines.length>0){let renderStack=()=>stackLines.map(line=>theme.fg("dim",` ${line.trim()}`)).join(`
|
|
1850
1824
|
`);this.chatContainer.addChild(new ThemedText(renderStack,1,0))}}this.ui.requestRender()}setupKeyHandlers(){this.defaultEditor.onEscape=()=>{if(this.session.isStreaming)this.restoreQueuedMessagesToEditor({abort:!0});else if(this.session.isBashRunning)this.session.abortBash();else if(this.isBashMode)this.editor.setText(""),this.isBashMode=!1,this.updateEditorBorderColor();else if(!this.editor.getText().trim()){let action=this.settingsManager.getDoubleEscapeAction();if(action!=="none"){let now=Date.now();now-this.lastEscapeTime<500?(action==="tree"?this.showTreeSelector():this.showUserMessageSelector(),this.lastEscapeTime=0):this.lastEscapeTime=now}}},this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onAction("app.suspend",()=>this.handleCtrlZ()),this.defaultEditor.onAction("app.thinking.cycle",()=>this.cycleThinkingLevel()),this.defaultEditor.onAction("app.model.cycleForward",()=>this.cycleModel("forward")),this.defaultEditor.onAction("app.model.cycleBackward",()=>this.cycleModel("backward")),this.ui.onDebug=()=>this.handleDebugCommand(),this.defaultEditor.onAction("app.model.select",()=>this.showModelSelector()),this.defaultEditor.onAction("app.tools.expand",()=>this.toggleToolOutputExpansion()),this.defaultEditor.onAction("app.thinking.toggle",()=>this.toggleThinkingBlockVisibility()),this.defaultEditor.onAction("app.editor.external",()=>{this.handleOpenExternalEditor()}),this.defaultEditor.onAction("app.message.copy",()=>{this.handleCopyCommand({flashConfirmation:!0,preferSelection:!0})}),this.defaultEditor.onAction("app.message.followUp",()=>this.handleFollowUp()),this.defaultEditor.onAction("app.message.dequeue",()=>this.handleDequeue()),this.defaultEditor.onAction("app.session.new",()=>this.handleClearCommand()),this.defaultEditor.onAction("app.session.tree",()=>this.showTreeSelector()),this.defaultEditor.onAction("app.session.fork",()=>this.showUserMessageSelector()),this.defaultEditor.onAction("app.session.resume",()=>this.showSessionSelector()),this.defaultEditor.onChange=text2=>{let wasBashMode=this.isBashMode;this.isBashMode=text2.trimStart().startsWith("!"),wasBashMode!==this.isBashMode&&this.updateEditorBorderColor()},this.defaultEditor.onPasteImage=()=>{this.handleClipboardPaste()}}async handleRightClickPaste(){let target=this.renderer.getFocusedComponent(),handleInput=target?.handleInput;if(!(!target||!handleInput))try{let text2=await readClipboardText();if(!text2||this.renderer.getFocusedComponent()!==target)return;handleInput.call(target,`\x1B[200~${text2}\x1B[201~`),this.ui.requestRender()}catch{}}async handleClipboardPaste(){try{let filePaths=await readClipboardFilePaths();if(filePaths){if(filePaths.some(filePath=>new RegExp("\\p{Cc}","u").test(filePath)))throw new Error("Clipboard file path contains control characters");let paths=this.isBashMode?filePaths.map(quoteIfNeeded).join(" "):filePaths.join(`
|
|
1851
1825
|
`),cursor=this.editor.getCursor?.(),currentLine=cursor?this.editor.getText().split(`
|
|
1852
|
-
`)[cursor.line]??"":"",characterBeforeCursor=cursor&&cursor.col>0?currentLine[cursor.col-1]:"",characterAfterCursor=cursor?currentLine[cursor.col]:"",leadingSpace=characterBeforeCursor&&!/\s/.test(characterBeforeCursor)?" ":"",trailingSpace=characterAfterCursor&&!/\s/.test(characterAfterCursor)?" ":"";this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`),this.ui.requestRender();return}let image=await readClipboardImage();if(image){let tmpDir=os7.tmpdir(),ext2=extensionForImageMimeType(image.mimeType)??"png",fileName=`pi-clipboard-${crypto3.randomUUID()}.${ext2}`,filePath=path13.join(tmpDir,fileName);fs8.writeFileSync(filePath,Buffer.from(image.bytes)),this.editor.insertTextAtCursor?.(filePath),this.ui.requestRender();return}let text2=await readClipboardText();text2&&(this.editor.insertTextAtCursor?.(text2),this.ui.requestRender())}catch(error){this.showError(`Failed to paste from clipboard: ${error instanceof Error?error.message:String(error)}`)}}handleStartupSubmit(text2){this.editor.setText(text2),this.showStatus("Startup is still in progress")}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async text2=>{if(text2=text2.trim(),!!text2&&!this.editorHost.intercept(text2,"steer")){if(text2==="/tasks"){this.editor.setText(""),await this.tasksUI?.open();return}if(text2==="/settings"){this.showSettingsSelector(),this.editor.setText("");return}if(text2==="/scoped-models"){this.editor.setText(""),await this.showModelsSelector();return}if(text2==="/model"||text2.startsWith("/model ")){let searchTerm=text2.startsWith("/model ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleModelCommand(searchTerm);return}if(text2==="/thinking"||text2.startsWith("/thinking ")){let searchTerm=text2.startsWith("/thinking ")?text2.slice(10).trim():void 0;this.editor.setText(""),this.handleThinkingCommand(searchTerm);return}if(text2==="/export"||text2.startsWith("/export ")){await this.handleExportCommand(text2),this.editor.setText("");return}if(text2==="/import"||text2.startsWith("/import ")){await this.handleImportCommand(text2),this.editor.setText("");return}if(text2==="/share"){await this.handleShareCommand(),this.editor.setText("");return}if(text2==="/bug"||text2.startsWith("/bug ")){let hint=text2.slice(4).trim();this.editor.setText(""),await this.handleBugCommand(hint||void 0);return}if(text2==="/copy"){await this.handleCopyCommand(),this.editor.setText("");return}if(text2==="/name"||text2.startsWith("/name ")){this.handleNameCommand(text2),this.editor.setText("");return}if(text2==="/session"){this.handleSessionCommand(),this.editor.setText("");return}if(text2==="/changelog"){this.handleChangelogCommand(),this.editor.setText("");return}if(text2==="/hotkeys"){this.handleHotkeysCommand(),this.editor.setText("");return}if(text2==="/fork"){this.showUserMessageSelector(),this.editor.setText("");return}if(text2==="/clone"){this.editor.setText(""),await this.handleCloneCommand();return}if(text2==="/tree"){this.showTreeSelector(),this.editor.setText("");return}if(text2==="/trust"){this.showTrustSelector(),this.editor.setText("");return}if(text2==="/login"||text2.startsWith("/login ")){let providerRef=text2.startsWith("/login ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleLoginCommand(providerRef);return}if(text2==="/logout"){this.showOAuthSelector("logout"),this.editor.setText("");return}if(text2==="/new"){this.editor.setText(""),await this.handleClearCommand();return}if(text2==="/compact"||text2.startsWith("/compact ")){let customInstructions=text2.startsWith("/compact ")?text2.slice(9).trim():void 0;this.editor.setText(""),await this.handleCompactCommand(customInstructions);return}if(text2==="/reload"){this.editor.setText(""),await this.handleReloadCommand();return}if(text2==="/debug"){this.handleDebugCommand(),this.editor.setText("");return}if(text2==="/arminsayshi"){this.handleArminSaysHi(),this.editor.setText("");return}if(text2==="/dementedelves"){this.handleDementedDelves(),this.editor.setText("");return}if(text2==="/resume"){this.showSessionSelector(),this.editor.setText("");return}if(text2==="/quit"){this.editor.setText(""),await this.shutdown();return}if(text2.startsWith("!")){let isExcluded=text2.startsWith("!!"),command=isExcluded?text2.slice(2).trim():text2.slice(1).trim();if(command){if(this.session.isBashRunning){this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(text2);return}this.editor.addToHistory?.(text2),await this.handleBashCommand(command,isExcluded),this.isBashMode=!1,this.updateEditorBorderColor();return}}if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"steer");return}if(this.session.isStreaming){this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(text2):this.pendingUserInputs.push(text2),this.editor.addToHistory?.(text2)}}}subscribeToAgent(){this.unsubscribe=this.session.subscribe(async event=>{await this.handleEvent(event)})}async handleEvent(event){switch(this.isInitialized||await this.init(),this.footer.invalidate(),this.programStatus.handleEvent(event),event.type){case"agent_start":this.pendingTools.clear(),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0);break;case"turn_start":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.workingVisible?this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator():this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":if(this.entriesRenderedByBoundaryCompaction.delete(event.entry.id))break;if(event.entry.type==="custom")this.addCustomEntryToChat(event.entry),this.ui.requestRender();else if(event.entry.type==="usage"&&event.entry.kind==="cache_warm")this.addCacheWarmingUsage(event.entry),this.ui.requestRender();else if(event.entry.type==="custom_message"&&event.entry.display)this.addMessageToChat(createCustomMessage(event.entry.customType,event.entry.content,event.entry.display,event.entry.details,event.entry.timestamp)),this.ui.requestRender();else if(event.entry.type==="compaction"){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.id!==event.entry.id)break;this.chatContainer.clear();let branch=this.sessionManager.getBranch(),compactionIndex=branch.findIndex(entry=>entry.id===event.entry.id),entriesAfterCompaction=new Set(branch.slice(compactionIndex+1).map(entry=>entry.id)),retainedEntries=entries.slice(1);this.renderSessionEntries(retainedEntries.filter(entry=>!entriesAfterCompaction.has(entry.id))),this.addMessageToChat(createCompactionSummaryMessage(event.entry.summary,event.entry.tokensBefore,event.entry.timestamp)),event.entry.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.entry.usage}),this.renderSessionEntries(retainedEntries.filter(entry=>entriesAfterCompaction.has(entry.id)));for(let entryId of entriesAfterCompaction)this.entriesRenderedByBoundaryCompaction.add(entryId);this.footer.invalidate(),this.ui.requestRender()}break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":event.message.role==="custom"?(this.addMessageToChat(event.message),this.ui.requestRender()):event.message.role==="user"?(this.addMessageToChat(event.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):event.message.role==="assistant"&&(this.streamingComponent=new AssistantMessageComponent(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=event.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let content of this.streamingMessage.content)if(content.type==="toolCall")if(this.pendingTools.has(content.id)){let component=this.pendingTools.get(content.id);component&&component.updateArgs(content.arguments)}else{let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(content.id,component)}this.ui.requestRender()}break;case"message_end":if(event.message.role==="user")break;if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message;let errorMessage9;if(this.streamingMessage.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage9=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=errorMessage9}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){errorMessage9||(errorMessage9=this.streamingMessage.errorMessage||"Error");for(let[,component]of this.pendingTools.entries())component.updateResult({content:[{type:"text",text:errorMessage9}],isError:!0});this.pendingTools.clear(),this.maybeSuggestBugReport(this.streamingMessage)}else{for(let[,component]of this.pendingTools.entries())component.setArgsComplete();this.maybeShowThinkingDropNotice(this.streamingMessage),this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{if(event.parentToolCallId)break;let component=this.pendingTools.get(event.toolCallId);component||(component=new ToolExecutionComponent(event.toolName,event.toolCallId,event.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(event.toolName),this.ui,this.sessionManager.getCwd()),component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{event.isError&&this.maybeShowInstallChangeWarning();let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError,durationMs:event.durationMs}),this.pendingTools.delete(event.toolCallId),this.ui.requestRender());break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortCompaction()};let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason,colorFn)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else if(event.errorMessage)if(event.reason==="manual")this.showError(event.errorMessage);else{this.chatContainer.addChild(new Spacer(1));let errorMessage9=event.errorMessage;this.chatContainer.addChild(new ThemedText(()=>theme.fg("error",errorMessage9),1,0))}this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{if(this.clearStatusIndicator("retry"),event.source==="branchSummary")this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));else{let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason,colorFn))}this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c=>c.type==="text")).map(c=>c.text).join("")}showManagedToolStatus(status){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status.type==="warning"?`Warning: ${status.message}`:status.message,color2=status.type==="warning"?"warning":"dim";this.chatContainer.addChild(new ThemedText(()=>theme.fg(color2,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusMessage=message,this.lastStatusText.invalidate(),this.ui.requestRender();return}let spacer=new Spacer(1);this.lastStatusMessage=message;let text2=new ThemedText(()=>theme.fg("dim",this.lastStatusMessage),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text2),this.lastStatusSpacer=spacer,this.lastStatusText=text2,this.ui.requestRender()}addCustomEntryToChat(entry){let renderer=this.session.extensionRunner.getEntryRenderer(entry.customType);if(!renderer)return;let component=new CustomEntryComponent(entry,renderer,this.outputPad);if(component.setExpanded(this.toolOutputExpanded),!!component.hasContent()){if(this.streamingComponent){let streamingIndex=this.chatContainer.children.indexOf(this.streamingComponent);if(streamingIndex>=0){this.chatContainer.children.splice(streamingIndex,0,component);return}}this.chatContainer.addChild(component)}}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext,this.outputPad);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let renderer=this.session.extensionRunner.getMessageRenderer(message.customType),component=new CustomMessageComponent(message,renderer,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"system":break;case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings(),this.outputPad);if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.sessionManager.getEntries(),this.session.modelRuntime):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item)){this.addCustomEntryToChat(item);continue}if(isUsageSessionEntry(item)){this.addCacheWarmingUsage(item);continue}if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage9;if(message.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage9=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage9=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage9}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){this.renderer instanceof TuiAltScreen&&this.renderer.resetTextSelection();let items=entries.flatMap(entry=>{if(entry.type==="custom"||entry.type==="usage"&&entry.kind==="cache_warm")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCacheWarmingUsage(entry){if(!this.settingsManager.getShowCacheMissNotices())return;this.chatContainer.addChild(new Spacer(1));let usage=formatCacheWarmingUsage(entry);this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",usage),1,0))}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens2=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`${label}: ${formatTokens(tokens2)} tokens billed${cost}`),1,0))}static countDroppedThinkingBlocks(message){let count=0;for(let diagnostic of message.diagnostics??[]){if(diagnostic.type!=="anthropic_input_transformations")continue;let transformations=diagnostic.details?.transformations;Array.isArray(transformations)&&(count+=transformations.filter(transformation=>typeof transformation=="object"&&transformation!==null&&transformation.type==="thinking_dropped").length)}return count}maybeShowThinkingDropNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let droppedCount=_InteractiveMode.countDroppedThinkingBlocks(message);if(droppedCount===0)return;let previousDroppedCount=0,branch=this.sessionManager.getBranch();for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="message"&&entry.message.role==="assistant"){previousDroppedCount=_InteractiveMode.countDroppedThinkingBlocks(entry.message);break}}if(droppedCount<=previousDroppedCount)return;let noun=droppedCount===1?"thinking block":"thinking blocks";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`Anthropic dropped ${droppedCount} ${noun} (details in session)`),1,0))}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.sessionManager.getEntries(),message,this.session.modelRuntime);miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`${label}: ${reBilled}`),1,0))}renderInitialMessages(){let entries=this.sessionManager.buildContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0}),this.renderProjectTrustWarningIfNeeded();let compactionCount=this.sessionManager.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}renderProjectTrustWarningIfNeeded(){this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(this.sessionManager.getCwd())||(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`),1,0)))}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve20=>{this.onInputCallback=text2=>{this.onInputCallback=void 0,resolve20(text2)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.sessionManager.buildContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,this.tasksUI?.dispose(),this.session.tasks.close(),options?.fromSignal&&(await this.runtimeHost.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeHost.dispose();let resumeCommand=formatResumeCommand(this.sessionManager);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1826
|
+
`)[cursor.line]??"":"",characterBeforeCursor=cursor&&cursor.col>0?currentLine[cursor.col-1]:"",characterAfterCursor=cursor?currentLine[cursor.col]:"",leadingSpace=characterBeforeCursor&&!/\s/.test(characterBeforeCursor)?" ":"",trailingSpace=characterAfterCursor&&!/\s/.test(characterAfterCursor)?" ":"";this.editor.insertTextAtCursor?.(`${leadingSpace}${paths}${trailingSpace}`),this.ui.requestRender();return}let image=await readClipboardImage();if(image){let tmpDir=os7.tmpdir(),ext2=extensionForImageMimeType(image.mimeType)??"png",fileName=`pi-clipboard-${crypto3.randomUUID()}.${ext2}`,filePath=path13.join(tmpDir,fileName);fs8.writeFileSync(filePath,Buffer.from(image.bytes)),this.editor.insertTextAtCursor?.(filePath),this.ui.requestRender();return}let text2=await readClipboardText();text2&&(this.editor.insertTextAtCursor?.(text2),this.ui.requestRender())}catch(error){this.showError(`Failed to paste from clipboard: ${error instanceof Error?error.message:String(error)}`)}}handleStartupSubmit(text2){this.editor.setText(text2),this.showStatus("Startup is still in progress")}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async text2=>{if(text2=text2.trim(),!!text2&&!this.editorHost.intercept(text2,"steer")){if(text2==="/settings"){this.showSettingsSelector(),this.editor.setText("");return}if(text2==="/scoped-models"){this.editor.setText(""),await this.showModelsSelector();return}if(text2==="/model"||text2.startsWith("/model ")){let searchTerm=text2.startsWith("/model ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleModelCommand(searchTerm);return}if(text2==="/thinking"||text2.startsWith("/thinking ")){let searchTerm=text2.startsWith("/thinking ")?text2.slice(10).trim():void 0;this.editor.setText(""),this.handleThinkingCommand(searchTerm);return}if(text2==="/export"||text2.startsWith("/export ")){await this.handleExportCommand(text2),this.editor.setText("");return}if(text2==="/import"||text2.startsWith("/import ")){await this.handleImportCommand(text2),this.editor.setText("");return}if(text2==="/share"){await this.handleShareCommand(),this.editor.setText("");return}if(text2==="/bug"||text2.startsWith("/bug ")){let hint=text2.slice(4).trim();this.editor.setText(""),await this.handleBugCommand(hint||void 0);return}if(text2==="/copy"){await this.handleCopyCommand(),this.editor.setText("");return}if(text2==="/name"||text2.startsWith("/name ")){this.handleNameCommand(text2),this.editor.setText("");return}if(text2==="/session"){this.handleSessionCommand(),this.editor.setText("");return}if(text2==="/changelog"){this.handleChangelogCommand(),this.editor.setText("");return}if(text2==="/hotkeys"){this.handleHotkeysCommand(),this.editor.setText("");return}if(text2==="/fork"){this.showUserMessageSelector(),this.editor.setText("");return}if(text2==="/clone"){this.editor.setText(""),await this.handleCloneCommand();return}if(text2==="/tree"){this.showTreeSelector(),this.editor.setText("");return}if(text2==="/trust"){this.showTrustSelector(),this.editor.setText("");return}if(text2==="/login"||text2.startsWith("/login ")){let providerRef=text2.startsWith("/login ")?text2.slice(7).trim():void 0;this.editor.setText(""),await this.handleLoginCommand(providerRef);return}if(text2==="/logout"){this.showOAuthSelector("logout"),this.editor.setText("");return}if(text2==="/new"){this.editor.setText(""),await this.handleClearCommand();return}if(text2==="/compact"||text2.startsWith("/compact ")){let customInstructions=text2.startsWith("/compact ")?text2.slice(9).trim():void 0;this.editor.setText(""),await this.handleCompactCommand(customInstructions);return}if(text2==="/reload"){this.editor.setText(""),await this.handleReloadCommand();return}if(text2==="/debug"){this.handleDebugCommand(),this.editor.setText("");return}if(text2==="/arminsayshi"){this.handleArminSaysHi(),this.editor.setText("");return}if(text2==="/dementedelves"){this.handleDementedDelves(),this.editor.setText("");return}if(text2==="/resume"){this.showSessionSelector(),this.editor.setText("");return}if(text2==="/quit"){this.editor.setText(""),await this.shutdown();return}if(text2.startsWith("!")){let isExcluded=text2.startsWith("!!"),command=isExcluded?text2.slice(2).trim():text2.slice(1).trim();if(command){if(this.session.isBashRunning){this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(text2);return}this.editor.addToHistory?.(text2),await this.handleBashCommand(command,isExcluded),this.isBashMode=!1,this.updateEditorBorderColor();return}}if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"steer");return}if(this.session.isStreaming){this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(text2):this.pendingUserInputs.push(text2),this.editor.addToHistory?.(text2)}}}subscribeToAgent(){this.unsubscribe=this.session.subscribe(async event=>{await this.handleEvent(event)})}async handleEvent(event){switch(this.isInitialized||await this.init(),this.footer.invalidate(),this.programStatus.handleEvent(event),event.type){case"agent_start":this.pendingTools.clear(),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0);break;case"turn_start":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.workingVisible?this.activeStatusIndicator?.kind!=="working"&&this.showWorkingStatusIndicator():this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":if(this.entriesRenderedByBoundaryCompaction.delete(event.entry.id))break;if(event.entry.type==="custom")this.addCustomEntryToChat(event.entry),this.ui.requestRender();else if(event.entry.type==="usage"&&event.entry.kind==="cache_warm")this.addCacheWarmingUsage(event.entry),this.ui.requestRender();else if(event.entry.type==="custom_message"&&event.entry.display)this.addMessageToChat(createCustomMessage(event.entry.customType,event.entry.content,event.entry.display,event.entry.details,event.entry.timestamp)),this.ui.requestRender();else if(event.entry.type==="compaction"){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.id!==event.entry.id)break;this.chatContainer.clear();let branch=this.sessionManager.getBranch(),compactionIndex=branch.findIndex(entry=>entry.id===event.entry.id),entriesAfterCompaction=new Set(branch.slice(compactionIndex+1).map(entry=>entry.id)),retainedEntries=entries.slice(1);this.renderSessionEntries(retainedEntries.filter(entry=>!entriesAfterCompaction.has(entry.id))),this.addMessageToChat(createCompactionSummaryMessage(event.entry.summary,event.entry.tokensBefore,event.entry.timestamp)),event.entry.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.entry.usage}),this.renderSessionEntries(retainedEntries.filter(entry=>entriesAfterCompaction.has(entry.id)));for(let entryId of entriesAfterCompaction)this.entriesRenderedByBoundaryCompaction.add(entryId);this.footer.invalidate(),this.ui.requestRender()}break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":event.message.role==="custom"?(this.addMessageToChat(event.message),this.ui.requestRender()):event.message.role==="user"?(this.addMessageToChat(event.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):event.message.role==="assistant"&&(this.streamingComponent=new AssistantMessageComponent(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.activeThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=event.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let content of this.streamingMessage.content)if(content.type==="toolCall")if(this.pendingTools.has(content.id)){let component=this.pendingTools.get(content.id);component&&component.updateArgs(content.arguments)}else{let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(content.id,component)}this.ui.requestRender()}break;case"message_end":if(event.message.role==="user")break;if(this.streamingComponent&&event.message.role==="assistant"){this.streamingMessage=event.message;let errorMessage9;if(this.streamingMessage.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage9=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=errorMessage9}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){errorMessage9||(errorMessage9=this.streamingMessage.errorMessage||"Error");for(let[,component]of this.pendingTools.entries())component.updateResult({content:[{type:"text",text:errorMessage9}],isError:!0});this.pendingTools.clear(),this.maybeSuggestBugReport(this.streamingMessage)}else{for(let[,component]of this.pendingTools.entries())component.setArgsComplete();this.maybeShowThinkingDropNotice(this.streamingMessage),this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{if(event.parentToolCallId)break;let component=this.pendingTools.get(event.toolCallId);component||(component=new ToolExecutionComponent(event.toolName,event.toolCallId,event.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(event.toolName),this.ui,this.sessionManager.getCwd()),component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),this.pendingTools.set(event.toolCallId,component)),component.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{event.isError&&this.maybeShowInstallChangeWarning();let component=this.pendingTools.get(event.toolCallId);component&&(component.updateResult({...event.result,isError:event.isError,durationMs:event.durationMs}),this.pendingTools.delete(event.toolCallId),this.ui.requestRender());break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortCompaction()};let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason,colorFn)),this.ui.requestRender();break}case"compaction_end":{if(this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled");else if(event.result){let entries=this.sessionManager.buildContextEntries();if(entries[0]?.type!=="compaction")throw new Error("Completed compaction is missing from the session context");this.chatContainer.clear(),this.renderSessionEntries(entries.slice(1)),this.addMessageToChat(createCompactionSummaryMessage(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&this.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),this.footer.invalidate()}else if(event.errorMessage)if(event.reason==="manual")this.showError(event.errorMessage);else{this.chatContainer.addChild(new Spacer(1));let errorMessage9=event.errorMessage;this.chatContainer.addChild(new ThemedText(()=>theme.fg("error",errorMessage9),1,0))}this.flushCompactionQueue({willRetry:event.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortRetry()},this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),event.success||this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(event.errorMessage),this.showStatusIndicator(new RetryStatusIndicator(this.ui,event.attempt,event.maxAttempts,event.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{if(this.clearStatusIndicator("retry"),event.source==="branchSummary")this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));else{let colorFn=isEmbeddedStatus(this.editor)?text2=>(this.editor.borderColor??theme.getThinkingBorderColor(this.session.thinkingLevel||"off"))(text2):void 0;this.showStatusIndicator(new CompactionStatusIndicator(this.ui,event.reason,colorFn))}this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c=>c.type==="text")).map(c=>c.text).join("")}showManagedToolStatus(status){this.managedToolStatusStarted||(this.chatContainer.addChild(new Spacer(1)),this.managedToolStatusStarted=!0);let message=status.type==="warning"?`Warning: ${status.message}`:status.message,color2=status.type==="warning"?"warning":"dim";this.chatContainer.addChild(new ThemedText(()=>theme.fg(color2,message),1,0)),this.lastStatusSpacer=void 0,this.lastStatusText=void 0,this.ui.requestRender()}showStatus(message){let children=this.chatContainer.children,last=children.length>0?children[children.length-1]:void 0,secondLast=children.length>1?children[children.length-2]:void 0;if(last&&secondLast&&last===this.lastStatusText&&secondLast===this.lastStatusSpacer){this.lastStatusMessage=message,this.lastStatusText.invalidate(),this.ui.requestRender();return}let spacer=new Spacer(1);this.lastStatusMessage=message;let text2=new ThemedText(()=>theme.fg("dim",this.lastStatusMessage),1,0);this.chatContainer.addChild(spacer),this.chatContainer.addChild(text2),this.lastStatusSpacer=spacer,this.lastStatusText=text2,this.ui.requestRender()}addCustomEntryToChat(entry){let renderer=this.session.extensionRunner.getEntryRenderer(entry.customType);if(!renderer)return;let component=new CustomEntryComponent(entry,renderer,this.outputPad);if(component.setExpanded(this.toolOutputExpanded),!!component.hasContent()){if(this.streamingComponent){let streamingIndex=this.chatContainer.children.indexOf(this.streamingComponent);if(streamingIndex>=0){this.chatContainer.children.splice(streamingIndex,0,component);return}}this.chatContainer.addChild(component)}}addMessageToChat(message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,this.ui,message.excludeFromContext,this.outputPad);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),this.chatContainer.addChild(component);break}case"custom":{if(message.display){let renderer=this.session.extensionRunner.getMessageRenderer(message.customType),component=new CustomMessageComponent(message,renderer,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component)}break}case"compactionSummary":{this.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"branchSummary":{this.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,this.getMarkdownThemeWithSettings(),this.outputPad);component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component);break}case"system":break;case"user":{let textContent=this.getUserMessageText(message);if(textContent){this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,this.getMarkdownThemeWithSettings(),this.outputPad);if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),skillBlock.userMessage){this.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(userComponent)}options?.populateHistory&&this.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.activeThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}renderSessionItems(items,options={}){this.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=this.settingsManager.getShowCacheMissNotices()?collectCacheMisses(this.sessionManager.getEntries(),this.session.modelRuntime):new Map;options.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item)){this.addCustomEntryToChat(item);continue}if(isUsageSessionEntry(item)){this.addCacheWarmingUsage(item);continue}if(isCompactionCostNotice(item)){this.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){this.addMessageToChat(message);for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),outputPad:this.outputPad},this.getRegisteredToolDefinition(content.name),this.ui,this.sessionManager.getCwd());if(component.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage9;if(message.stopReason==="aborted"){let retryAttempt=this.session.retryAttempt;errorMessage9=retryAttempt>0?`Aborted after ${retryAttempt} retry attempt${retryAttempt>1?"s":""}`:"Operation aborted"}else errorMessage9=message.errorMessage||"Error";component.updateResult({content:[{type:"text",text:errorMessage9}],isError:!0})}else renderedPendingTools.set(content.id,component)}if(message.stopReason!=="aborted"&&message.stopReason!=="error"){let miss=cacheMisses.get(message);miss&&this.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),renderedPendingTools.delete(message.toolCallId))}else this.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)this.pendingTools.set(toolCallId,component);this.ui.requestRender()}renderSessionEntries(entries,options={}){this.renderer instanceof TuiAltScreen&&this.renderer.resetTextSelection();let items=entries.flatMap(entry=>{if(entry.type==="custom"||entry.type==="usage"&&entry.kind==="cache_warm")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});this.renderSessionItems(items,options)}addCacheWarmingUsage(entry){if(!this.settingsManager.getShowCacheMissNotices())return;this.chatContainer.addChild(new Spacer(1));let usage=formatCacheWarmingUsage(entry);this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",usage),1,0))}addCompactionCostNotice(notice){if(!this.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens2=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?"Compaction":"Branch summary";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`${label}: ${formatTokens(tokens2)} tokens billed${cost}`),1,0))}static countDroppedThinkingBlocks(message){let count=0;for(let diagnostic of message.diagnostics??[]){if(diagnostic.type!=="anthropic_input_transformations")continue;let transformations=diagnostic.details?.transformations;Array.isArray(transformations)&&(count+=transformations.filter(transformation=>typeof transformation=="object"&&transformation!==null&&transformation.type==="thinking_dropped").length)}return count}maybeShowThinkingDropNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let droppedCount=_InteractiveMode.countDroppedThinkingBlocks(message);if(droppedCount===0)return;let previousDroppedCount=0,branch=this.sessionManager.getBranch();for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="message"&&entry.message.role==="assistant"){previousDroppedCount=_InteractiveMode.countDroppedThinkingBlocks(entry.message);break}}if(droppedCount<=previousDroppedCount)return;let noun=droppedCount===1?"thinking block":"thinking blocks";this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`Anthropic dropped ${droppedCount} ${noun} (details in session)`),1,0))}maybeShowCacheMissNotice(message){if(!this.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(this.sessionManager.getEntries(),message,this.session.modelRuntime);miss&&this.addCacheMissNotice(miss)}addCacheMissNotice(miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=`${formatTokens(miss.missedTokens)} tokens re-billed${cost}`,label="Cache miss";miss.modelChanged?label="Cache miss after model switch":miss.idleMs>=3e5&&(label=`Cache miss after ${Math.round(miss.idleMs/6e4)}m idle`),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`${label}: ${reBilled}`),1,0))}renderInitialMessages(){let entries=this.sessionManager.buildContextEntries();this.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0}),this.renderProjectTrustWarningIfNeeded();let compactionCount=this.sessionManager.getEntries().filter(e=>e.type==="compaction").length;if(compactionCount>0){let times=compactionCount===1?"1 time":`${compactionCount} times`;this.showStatus(`Session compacted ${times}`)}}renderProjectTrustWarningIfNeeded(){this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(this.sessionManager.getCwd())||(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`This project is not trusted. Project ${CONFIG_DIR_NAME} resources and packages are ignored. Use /trust to save a trust decision, then restart pi.`),1,0)))}async getUserInput(){let queuedInput=this.pendingUserInputs.shift();return queuedInput!==void 0?queuedInput:new Promise(resolve20=>{this.onInputCallback=text2=>{this.onInputCallback=void 0,resolve20(text2)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.sessionManager.buildContextEntries())}handleCtrlC(){let now=Date.now();now-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=now)}handleCtrlD(){this.shutdown()}async shutdown(options){if(this.isShuttingDown)return;this.isShuttingDown=!0,this.session.tasks.close(),options?.fromSignal&&(await this.runtimeHost.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeHost.dispose();let resumeCommand=formatResumeCommand(this.sessionManager);resumeCommand&&process.stdout.write(`${source_default.dim("To resume this session:")} ${resumeCommand}
|
|
1853
1827
|
`),process.exit(0)}emergencyTerminalExit(){this.isShuttingDown=!0,this.unregisterSignalHandlers(),killTrackedDetachedChildren(),process.exit(129)}uncaughtCrash(error){isDeadTerminalError(error)&&this.emergencyTerminalExit(),this.isShuttingDown&&process.exit(1),this.isShuttingDown=!0;try{this.unregisterSignalHandlers()}catch{}try{killTrackedDetachedChildren()}catch{}try{this.ui.stop()}catch{}console.error(`${APP_NAME} exiting due to uncaughtException:`),console.error(error);let extensionHint=this.getCrashExtensionHint(error);extensionHint&&console.error(`
|
|
1854
1828
|
${extensionHint}`),this.recordCrash("uncaught_exception",error)&&console.error(`
|
|
1855
1829
|
${this.crashReportInstructions()}`),process.exit(1)}async checkShutdownRequested(){this.shutdownRequested&&await this.shutdown()}registerSignalHandlers(){this.unregisterSignalHandlers();let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),this.shutdown({fromSignal:!0})};process.prependListener(signal,handler),this.signalCleanupHandlers.push(()=>process.off(signal,handler))}let terminalErrorHandler=error=>{throw isDeadTerminalError(error)&&this.emergencyTerminalExit(),error};for(let stream2 of[process.stdin,process.stdout,process.stderr])stream2.on("error",terminalErrorHandler),this.signalCleanupHandlers.push(()=>stream2.off("error",terminalErrorHandler));let uncaughtExceptionHandler=error=>this.uncaughtCrash(error);process.prependListener("uncaughtException",uncaughtExceptionHandler),this.signalCleanupHandlers.push(()=>process.off("uncaughtException",uncaughtExceptionHandler))}unregisterSignalHandlers(){for(let cleanup of this.signalCleanupHandlers)cleanup();this.signalCleanupHandlers=[]}handleCtrlZ(){if(process.platform==="win32"){this.showStatus("Suspend to background is not supported on Windows");return}let suspendKeepAlive=setInterval(()=>{},2**30),ignoreSigint=()=>{};process.on("SIGINT",ignoreSigint),process.once("SIGCONT",()=>{clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),this.ui.start(),this.ui.requestRender(!0)});try{this.ui.stop(),process.kill(0,"SIGTSTP")}catch(error){throw clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),error}}async handleFollowUp(){let text2=(this.editor.getExpandedText?.()??this.editor.getText()).trim();if(text2&&!this.editorHost.intercept(text2,"followUp")){if(this.session.isCompacting){this.isExtensionCommand(text2)?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2)):this.queueCompactionMessage(text2,"followUp");return}this.session.isStreaming?(this.editor.addToHistory?.(text2),this.editor.setText(""),await this.session.prompt(text2,{streamingBehavior:"followUp"}),this.updatePendingMessagesDisplay(),this.ui.requestRender()):this.editor.onSubmit&&(this.editor.setText(""),this.editor.onSubmit(text2))}}handleDequeue(){let restored=this.restoreQueuedMessagesToEditor();restored===0?this.showStatus("No queued messages to restore"):this.showStatus(`Restored ${restored} queued message${restored>1?"s":""} to editor`)}updateEditorBorderColor(){if(this.isBashMode)this.editor.borderColor=theme.getBashModeBorderColor();else{let level=this.session.thinkingLevel||"off";this.editor.borderColor=theme.getThinkingBorderColor(level)}this.activeStatusIndicator?.invalidate(),this.ui.requestRender()}cycleThinkingLevel(){let newLevel=this.session.cycleThinkingLevel();newLevel===void 0?this.showStatus("Current model does not support thinking"):(this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Thinking level: ${newLevel}`))}async cycleModel(direction){try{let result2=await this.session.cycleModel(direction);if(result2===void 0){let msg=this.session.scopedModels.length>0?"Only one model in scope":"Only one model available";this.showStatus(msg)}else{this.footer.invalidate(),this.updateEditorBorderColor();let thinkingStr=result2.model.reasoning&&result2.thinkingLevel!=="off"?` (thinking: ${result2.thinkingLevel})`:"";this.showStatus(`Switched to ${result2.model.name||result2.model.id}${thinkingStr}`),this.maybeWarnAboutAnthropicSubscriptionAuth(result2.model)}}catch(error){this.showError(error instanceof Error?error.message:String(error))}}toggleToolOutputExpansion(){this.setToolsExpanded(!this.toolOutputExpanded)}setToolsExpanded(expanded){if(expanded===this.toolOutputExpanded)return;this.toolOutputExpanded=expanded;let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(expanded);for(let container of[this.loadedResourcesContainer,this.chatContainer])for(let child of container.children)isExpandable(child)&&child.setExpanded(expanded);this.showStatus(`Tool output: ${expanded?"expanded":"collapsed"}`)}updateThinkingBlockVisibility(){for(let child of this.chatContainer.children)child instanceof AssistantMessageComponent&&child.setHideThinkingBlock(this.hideThinkingBlock);this.ui.requestRender()}toggleThinkingBlockVisibility(){this.hideThinkingBlock=!this.hideThinkingBlock,this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock),this.updateThinkingBlockVisibility(),this.showStatus(`Thinking blocks: ${this.hideThinkingBlock?"hidden":"visible"}`)}async handleOpenExternalEditor(){let editorCmd=this.settingsManager.getExternalEditorCommand(),content=this.editor.getExpandedText?.()??this.editor.getText();this.ui.stop();try{let result2=await editInExternalEditor({command:editorCmd,content});result2.status==="complete"&&this.editor.setText(result2.content)}finally{this.ui.start(),this.ui.requestRender(!0)}}clearEditor(){this.editor.setText(""),this.ui.requestRender()}showError(errorMessage9){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("error",`Error: ${errorMessage9}`),this.outputPad,0)),this.ui.requestRender()}showWarning(warningMessage){this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("warning",`Warning: ${warningMessage}`),1,0)),this.ui.requestRender()}showNewVersionNotification(release2){let updateInstruction=()=>theme.fg("muted",`New version ${release2.version} is available. Run `)+theme.fg("accent",`${APP_NAME} update`),changelogUrl="https://pi.dev/changelog",changelogLine=()=>{let changelogLink=getCapabilities().hyperlinks?hyperlink(theme.fg("accent",changelogUrl),changelogUrl):theme.fg("accent",changelogUrl);return UPDATE_CHANGELOG_HINT?theme.fg("muted",UPDATE_CHANGELOG_HINT):theme.fg("muted","Changelog: ")+changelogLink},note=release2.note?.trim();this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder(text2=>theme.fg("warning",text2))),this.chatContainer.addChild(new ThemedText(()=>`${theme.bold(theme.fg("warning","Update Available"))}
|
|
@@ -1861,7 +1835,7 @@ ${packageLines}`,1,0)),this.chatContainer.addChild(new DynamicBorder(text2=>them
|
|
|
1861
1835
|
|
|
1862
1836
|
`),currentText=options?.currentText??this.editor.getText(),combinedText=[queuedText,currentText].filter(t=>t.trim()).join(`
|
|
1863
1837
|
|
|
1864
|
-
`);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.session.abort(),allQueued.length}queueCompactionMessage(text2,mode){this.compactionQueuedMessages.push({text:text2,mode}),this.editor.addToHistory?.(text2),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text2){if(!text2.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);return!!extensionRunner.getCommand(commandName)}async flushCompactionQueue(options){if(this.compactionQueuedMessages.length===0)return;let queuedMessages=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let restoreQueue=error=>{this.session.clearQueue(),this.compactionQueuedMessages=queuedMessages,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${queuedMessages.length>1?"s":""}: ${error instanceof Error?error.message:String(error)}`)};try{if(options?.willRetry){for(let message of queuedMessages)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay();return}let firstPromptIndex=queuedMessages.findIndex(message=>!this.isExtensionCommand(message.text));if(firstPromptIndex===-1){for(let message of queuedMessages)await this.session.prompt(message.text);return}let preCommands=queuedMessages.slice(0,firstPromptIndex),firstPrompt=queuedMessages[firstPromptIndex],rest=queuedMessages.slice(firstPromptIndex+1);for(let message of preCommands)await this.session.prompt(message.text);let promptPromise=this.session.prompt(firstPrompt.text,{streamingBehavior:firstPrompt.mode}).catch(error=>{restoreQueue(error)});for(let message of rest)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay()}catch(error){restoreQueue(error)}}flushPendingBashComponents(){for(let component of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(component),this.chatContainer.addChild(component);this.pendingBashComponents=[]}disposeActiveSelector(){let dispose=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,dispose?.()}showSelector(create){let token={},dispose,created=create(()=>{dispose?.(),this.activeSelectorToken===token&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))}),release2=created.dispose,released=!1;dispose=()=>{released||(released=!0,release2?.())},this.disposeActiveSelector(),this.activeSelectorToken=token,this.activeSelectorDispose=dispose,this.editorContainer.clear(),this.editorContainer.addChild(created.component),this.ui.setFocus(created.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(done=>{let selector,defaultProvider=this.settingsManager.getDefaultProvider(),defaultModelId=this.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:"not set";return selector=new SettingsSelectorComponent({autoCompact:this.session.autoCompactionEnabled,defaultModel,currentModel:this.session.model,availableDefaultModels:this.session.modelRuntime.getAvailableSnapshot(),showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),sessionShareDestination:this.settingsManager.getSessionShareDestination(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),cacheWarmingMode:this.settingsManager.getCacheWarmingMode(),thinkingLevel:this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:this.settingsManager.getAllModelThinkingLevels(),currentTheme:this.themeController.getThemeSelection()||SYSTEM_THEME_NAME,terminalTheme:this.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:enabled=>{this.session.setAutoCompactionEnabled(enabled),this.footer.setAutoCompactEnabled(enabled)},onShowImagesChange:enabled=>{this.settingsManager.setShowImages(enabled);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{this.settingsManager.setImageWidthCells(width);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{this.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{this.settingsManager.setBlockImages(blocked)},onEnableSkillCommandsChange:enabled=>{this.settingsManager.setEnableSkillCommands(enabled),this.setupAutocompleteProvider()},onSteeringModeChange:mode=>{this.session.setSteeringMode(mode)},onFollowUpModeChange:mode=>{this.session.setFollowUpMode(mode)},onTransportChange:transport=>{this.settingsManager.setTransport(transport),this.session.agent.transport=transport},onSessionShareDestinationChange:destination=>{this.settingsManager.setSessionShareDestination(destination)},onHttpIdleTimeoutMsChange:timeoutMs=>{this.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`)},onCacheWarmingModeChange:mode=>{this.session.setCacheWarmingMode(mode),this.showStatus(`Cache warming: ${mode}`)},onModelThinkingLevelChange:(provider,modelId,level)=>{this.settingsManager.setModelThinkingLevel(provider,modelId,level);let current=this.session.model;current&¤t.provider===provider&¤t.id===modelId&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId)=>{this.settingsManager.removeModelThinkingLevel(provider,modelId);let current=this.session.model;if(current&¤t.provider===provider&¤t.id===modelId){let globalDefault=this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;this.session.setThinkingLevel(globalDefault),this.footer.invalidate(),this.updateEditorBorderColor()}},onThemeChange:themeSetting=>{this.settingsManager.setTheme(themeSetting),this.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>this.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{this.hideThinkingBlock=hidden,this.settingsManager.setHideThinkingBlock(hidden),this.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{this.settingsManager.setMermaidRenderingMode(mode),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{this.settingsManager.setShowCacheMissNotices(shown),this.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{this.settingsManager.setCollapseChangelog(collapsed)},onEnableInstallTelemetryChange:enabled=>{this.settingsManager.setEnableInstallTelemetry(enabled)},onQuietStartupChange:quiet=>{this.settingsManager.setQuietStartup(quiet)},onDefaultProjectTrustChange:defaultProjectTrust=>{this.settingsManager.setDefaultProjectTrust(defaultProjectTrust)},onDoubleEscapeActionChange:action=>{this.settingsManager.setDoubleEscapeAction(action)},onTreeFilterModeChange:mode=>{this.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{this.settingsManager.setShowHardwareCursor(enabled),this.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{this.settingsManager.setEditorPaddingX(padding),this.defaultEditor.setPaddingX(padding),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(padding)},onOutputPadChange:padding=>{this.settingsManager.setOutputPad(padding),this.outputPad=padding;for(let container of[this.chatContainer,this.pendingMessagesContainer])for(let child of container.children)"setOutputPad"in child&&typeof child.setOutputPad=="function"&&child.setOutputPad(padding);this.ui.requestRender()},onAutocompleteMaxVisibleChange:maxVisible=>{this.settingsManager.setAutocompleteMaxVisible(maxVisible),this.defaultEditor.setAutocompleteMaxVisible(maxVisible),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{this.settingsManager.setClearOnShrink(enabled),this.ui.setClearOnShrink(enabled),!enabled&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{this.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!this.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(mode),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${mode}`)},onFullscreenExitOutputChange:output=>{this.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{this.settingsManager.setFullscreenScrollbar(mode),this.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{this.settingsManager.setFullscreenCopyOnSelect(enabled),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(enabled)},onFullscreenWheelScrollLinesChange:lines=>{this.settingsManager.setFullscreenWheelScrollLines(lines),this.renderer instanceof TuiAltScreen&&this.renderer.setWheelScrollLines(lines)},onWarningsChange:warnings=>{this.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),this.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}handleThinkingCommand(searchTerm){let availableLevels=this.session.getAvailableThinkingLevels();if(!searchTerm){this.showThinkingSelector();return}let normalized=searchTerm.trim().toLowerCase(),level=availableLevels.find(candidate=>candidate.toLowerCase()===normalized);if(!level){this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);return}this.selectThinkingLevel(level,!1)}selectThinkingLevel(level,persist){try{this.session.setThinkingLevel(level,{persist}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(persist?`Default thinking level: ${level}`:`Thinking level: ${level}`)}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showThinkingSelector(){this.showSelector(done=>{let selectLevel=(level,persist)=>{this.selectThinkingLevel(level,persist),done()},selector=new ThinkingSelectorComponent(this.session.thinkingLevel??DEFAULT_THINKING_LEVEL,this.session.getAvailableThinkingLevels(),level=>selectLevel(level,!1),()=>{done(),this.ui.requestRender()},level=>selectLevel(level,!0),this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL);return{component:selector,focus:selector}})}async handleModelCommand(searchTerm){if(!searchTerm){this.showModelSelector();return}let model=await this.findExactModelMatch(searchTerm);if(model){try{await this.session.setModel(model,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model)}catch(error){this.showError(error instanceof Error?error.message:String(error))}return}this.showModelSelector(searchTerm)}async findExactModelMatch(searchTerm){let cachedModels=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):[...this.session.modelRuntime.getAvailableSnapshot()],cachedMatch=findExactModelReferenceMatch(searchTerm,cachedModels);if(cachedMatch||this.session.scopedModels.length>0)return cachedMatch;this.showStatus("Refreshing model catalogs\u2026");let controller=new AbortController,timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3);try{let result2=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result2.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result2.errors.size>0&&this.showWarning(`Could not refresh ${[...result2.errors.keys()].join(", ")}; searching cached models.`)}catch(error){this.showWarning(timedOut?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`)}finally{clearTimeout(timeout)}return findExactModelReferenceMatch(searchTerm,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let models=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):this.session.modelRuntime.getAvailableSnapshot(),uniqueProviders=new Set(models.map(model=>model.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model||model.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);return}let apiKey=(await this.session.modelRuntime.getAuth(model.provider))?.auth.apiKey;if(!isAnthropicSubscriptionAuthKey(apiKey))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let cwd=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==cwd||!this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(cwd))return!1;let trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir);try{return trustStore.get(cwd)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(trustStore.set(cwd,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(error){return this.showWarning(`Could not save project trust after reload: ${error instanceof Error?error.message:String(error)}`),!1}}showTrustSelector(){let cwd=this.sessionManager.getCwd(),trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir),savedDecision=trustStore.getEntry(cwd);this.showSelector(done=>{let selector=new TrustSelectorComponent({cwd,savedDecision,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:selection=>{trustStore.setMany(selection.updates),done(),this.showStatus(`Saved trust decision: ${selection.trusted?"trusted":"untrusted"}. Restart ${APP_NAME} for this to take effect.`)},onCancel:()=>{done(),this.ui.requestRender()}});return{component:selector,focus:selector}})}showModelSelector(initialSearchInput){this.showSelector(done=>{let selectModel=async(model,persist)=>{try{await this.session.setModel(model,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model.provider}/${model.id}`:`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model)}catch(error){done(),this.showError(error instanceof Error?error.message:String(error))}},defaultProvider=this.settingsManager.getDefaultProvider(),defaultModel=this.settingsManager.getDefaultModel(),selector=new ModelSelectorComponent(this.ui,this.session.model,this.session.modelRuntime,this.session.scopedModels,model=>selectModel(model,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model=>selectModel(model,!0),defaultProvider&&defaultModel?{provider:defaultProvider,id:defaultModel}:void 0);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showModelsSelector(){let availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),configuredPatterns=this.settingsManager.getEnabledModels(),sessionScopedModels=this.session.scopedModels,configuredEnabledIds=models=>{if(!configuredPatterns?.length)return null;let resolved=resolveModelScopeFromModels(configuredPatterns,models),ids=resolved.scopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`);for(let diagnostic of resolved.diagnostics)diagnostic.code==="no-match"&&!ids.includes(diagnostic.pattern)&&ids.push(diagnostic.pattern);return ids},currentEnabledIds=sessionScopedModels.length>0?sessionScopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`):configuredEnabledIds(availableModels),selectionChanged=!1,updateSessionModels=enabledIds=>{currentEnabledIds=enabledIds===null?null:[...enabledIds];let hasEnabledAvailableModel=enabledIds?.some(id=>availableModelIds.has(id))??!1,allAvailableModelsEnabled=enabledIds!==null&&[...availableModelIds].every(id=>enabledIds.includes(id));if(enabledIds&&hasEnabledAvailableModel&&!allAvailableModelsEnabled){let newScopedModels=resolveModelScopeFromModels(enabledIds,availableModels).scopedModels;this.session.setScopedModels(newScopedModels.map(scoped=>({model:scoped.model,thinkingLevel:scoped.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(done=>{let disposed=!1,timedOut=!1,controller=new AbortController,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3),selector=new ScopedModelsSelectorComponent({allModels:availableModels,enabledModelIds:currentEnabledIds,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:enabledIds=>{selectionChanged=!0,updateSessionModels(enabledIds)},onPersist:enabledIds=>{let allEnabled=enabledIds!==null&&enabledIds.length===availableModels.length&&enabledIds.every(id=>availableModelIds.has(id)),newPatterns=enabledIds===null||allEnabled?void 0:enabledIds;this.settingsManager.setEnabledModels(newPatterns?[...newPatterns]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{done(),this.ui.requestRender()}});return refreshModelCatalogs(this.session.modelRuntime,controller.signal).then(result2=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result2.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result2.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result2.errors.keys()].join(", ")}; showing cached models.`,"warning"):selector.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(error=>{disposed||(selector.setRefreshStatus(timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(timeout)),{component:selector,focus:selector,dispose:()=>{disposed=!0,clearTimeout(timeout),controller.abort()}}})}showUserMessageSelector(){let userMessages=this.session.getUserMessagesForForking();if(userMessages.length===0){this.showStatus("No messages to fork from");return}let initialSelectedId=userMessages[userMessages.length-1]?.entryId;this.showSelector(done=>{let selector=new UserMessageSelectorComponent(userMessages.map(m2=>({id:m2.entryId,text:m2.text})),async entryId=>{done();try{let result2=await this.runtimeHost.fork(entryId);if(result2.cancelled){this.ui.requestRender();return}this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},()=>{done(),this.ui.requestRender()},initialSelectedId);return{component:selector,focus:selector.getMessageList()}})}async handleCloneCommand(){let leafId=this.sessionManager.getLeafId();if(!leafId){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(leafId,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showTreeSelector(initialSelectedId){let tree=this.sessionManager.getTree(),realLeafId=this.sessionManager.getLeafId(),initialFilterMode=this.settingsManager.getTreeFilterMode();if(tree.length===0){this.showStatus("No entries in session");return}this.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,this.ui.terminal.rows,async entryId=>{if(entryId===this.sessionManager.getLeafId()){done(),this.showStatus("Already at this point");return}done();let stopped=this.session.tasksStoppedByTreeNavigation(entryId);if(!await confirmStopBranchTasks(stopped,(title,message)=>this.showExtensionConfirm(title,message))){this.showTreeSelector(entryId);return}let wantsSummary=!1,customInstructions;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(summaryChoice===void 0){this.showTreeSelector(entryId);return}if(wantsSummary=summaryChoice!=="No summary",!(summaryChoice==="Summarize with custom prompt"&&(customInstructions=await this.showExtensionEditor("Custom summarization instructions"),customInstructions===void 0)))break}if(this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort()),this.session.isCompacting){this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");return}let showingSummaryIndicator=!1,originalOnEscape=this.defaultEditor.onEscape;wantsSummary&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new Spacer(1)),this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)),showingSummaryIndicator=!0,this.ui.requestRender());try{let result2=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result2.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result2.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(error){this.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=originalOnEscape}},()=>{done(),this.ui.requestRender()},(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label),this.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text2=>{if(!text2){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text2),this.showStatus("Copied selected message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}showSessionSelector(){this.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress,signal),(onProgress,signal)=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress,signal):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress,signal),async sessionPath=>{done(),await this.handleResumeSession(sessionPath)},()=>{done(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:selector,focus:selector}})}async handleResumeSession(sessionPath,options){this.clearStatusIndicator();try{let result2=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session"),result2}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result2=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session in current cwd"),result2}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0,subscription=provider.auth.oauth?.isSubscription===!0;(!authType||authType==="oauth")&&provider.auth.oauth&&options.push({id:provider.id,name:provider.name,authType:"oauth",method:provider.auth.oauth,status,subscription}),(!authType||authType==="api_key")&&provider.auth.apiKey&&options.push({id:provider.id,name:provider.name,authType:"api_key",method:provider.auth.apiKey,status,subscription})}return options.sort((a,b2)=>a.name.localeCompare(b2.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId,type})=>{let provider=this.session.modelRuntime.getProvider(providerId);return{id:providerId,name:provider?.name??providerId,authType:type,status:{type,source:"stored credential"},subscription:provider?.auth.oauth?.isSubscription===!0}}).sort((a,b2)=>a.name.localeCompare(b2.name))}findLoginProviderOptions(providerRef){let normalizedProviderRef=providerRef.trim().toLowerCase();return normalizedProviderRef?this.getLoginProviderOptions().filter(provider=>provider.id.toLowerCase()===normalizedProviderRef||provider.name.toLowerCase()===normalizedProviderRef):[]}async handleLoginCommand(providerRef){if(!providerRef){this.showLoginAuthTypeSelector();return}let providerOptions=this.findLoginProviderOptions(providerRef);if(providerOptions.length===1){await this.startProviderLogin(providerOptions[0]);return}if(providerOptions.length>1&&new Set(providerOptions.map(provider=>provider.id)).size===1){this.showLoginAuthTypeSelector(providerOptions);return}this.showLoginProviderSelector(void 0,providerRef)}async startProviderLogin(providerOption,onBack){providerOption.authType==="oauth"?await this.showLoginDialog(providerOption.id,providerOption.name,onBack):providerOption.method?.login?await this.showApiKeyLoginDialog(providerOption.id,providerOption.name,onBack):this.showAmbientAuthDialog(providerOption,onBack)}showLoginAuthTypeSelector(providerOptions){let radiusOption=providerOptions?void 0:this.getLoginProviderOptions("oauth").find(provider=>provider.id===RADIUS_PROVIDER_ID),radiusText=radiusOption?`Sign in with ${radiusOption.name}`:void 0,radiusLabel=radiusOption?`${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}`:void 0,oauthProvider=providerOptions?.find(provider=>provider.authType==="oauth"),subscriptionLabel=(oauthProvider?.method&&"loginLabel"in oauthProvider.method?oauthProvider.method.loginLabel:void 0)??"Sign in with an account",apiKeyLabel="Sign in with an API key",availableAuthTypes=providerOptions?new Set(providerOptions.map(provider=>provider.authType)):new Set(["oauth","api_key"]),options=[];if(availableAuthTypes.has("oauth")&&options.push(subscriptionLabel),availableAuthTypes.has("api_key")&&options.push(apiKeyLabel),radiusLabel&&options.push(radiusLabel),options.length===0){this.showStatus("No login methods available.");return}if(providerOptions&&options.length===1){let providerOption=providerOptions[0];providerOption&&this.startProviderLogin(providerOption);return}let title=providerOptions?.[0]?`Select authentication method for ${providerOptions[0].name}:`:"Select authentication method:";this.showSelector(done=>{let onSelect=option=>{if(done(),radiusOption&&option===radiusLabel){this.startProviderLogin(radiusOption,()=>this.showLoginAuthTypeSelector());return}let authType=option===subscriptionLabel?"oauth":"api_key";if(providerOptions){let providerOption=providerOptions.find(provider=>provider.authType===authType);providerOption&&this.startProviderLogin(providerOption,()=>this.showLoginAuthTypeSelector(providerOptions));return}this.showLoginProviderSelector(authType)},onCancel=()=>{done(),this.ui.requestRender()},selector=radiusLabel&&radiusText?createLoginMenuSelector(this.ui,title,options,{label:radiusLabel,text:radiusText},onSelect,onCancel):new ExtensionSelectorComponent(title,options,onSelect,onCancel);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showLoginProviderSelector(authType,initialSearchInput){let providerOptions=this.getLoginProviderOptions(authType);if(providerOptions.length===0){let message=authType==="oauth"?"No account providers available.":authType==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(message);return}this.showSelector(done=>{let selector=new OAuthSelectorComponent("login",providerOptions,async(providerId,selectedAuthType)=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId&&provider.authType===selectedAuthType);providerOption&&await this.startProviderLogin(providerOption,()=>this.showLoginProviderSelector(authType,initialSearchInput))},()=>{done(),authType?this.showLoginAuthTypeSelector():this.ui.requestRender()},initialSearchInput);return{component:selector,focus:selector}})}async showOAuthSelector(mode){if(mode==="login"){this.showLoginAuthTypeSelector();return}let providerOptions;try{providerOptions=await this.getLogoutProviderOptions()}catch(error){this.showError(`Could not read stored credentials: ${error instanceof Error?error.message:String(error)}`);return}if(providerOptions.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(done=>{let selector=new OAuthSelectorComponent(mode,providerOptions,async providerId=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId);if(providerOption)try{await this.session.modelRuntime.logout(providerOption.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let message=providerOption.authType==="oauth"?`Logged out of ${providerOption.name}`:`Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;this.showStatus(message)}catch(error){let message=error instanceof Error?error.message:String(error);this.showError(error instanceof CredentialSynchronizationError?`Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`:`Logout failed: ${message}`)}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async completeProviderAuthentication(providerId,providerName,authType,previousModel){let actionLabel=authType==="oauth"?`Logged in to ${providerName}`:`Saved API key for ${providerName}`,session=this.session,deferSelection=isUnknownModel(previousModel)&&hasDefaultModelProvider(providerId)&&!session.modelRuntime.getAvailableSnapshot().some(model=>model.provider===providerId&&model.id===defaultModelPerProvider[providerId]),finishAuthentication=async()=>{let selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model=>model.provider===providerId);if(providerId==="llama.cpp")selectionError=llamaCppPostLoginGuidance(actionLabel,providerModels.length);else if(!hasDefaultModelProvider(providerId))selectionError=`${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;else if(providerModels.length===0)selectionError=`${actionLabel}, but no models are available for that provider. Use /model to select a model.`;else{let defaultModelId=defaultModelPerProvider[providerId];if(selectedModel=providerModels.find(model=>model.id===defaultModelId)??(providerId==="radius"?providerModels[0]:void 0),!selectedModel)selectionError=`${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;else try{await this.session.setModel(selectedModel,{persist:!0})}catch(error){selectedModel=void 0;let errorMessage9=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage9}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),selectedModel?(this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel)):(this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`),selectionError?this.showError(selectionError):this.maybeWarnAboutAnthropicSubscriptionAuth())};deferSelection?this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog\u2026`):await finishAuthentication();let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(async result2=>{result2.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result2.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),deferSelection&&this.session===session&&session.model===previousModel&&await finishAuthentication(),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(error=>{this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error?error.message:String(error)}`)}).finally(()=>clearTimeout(timeout))}showAmbientAuthDialog(providerOption,onBack){let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>{restoreEditor3(),onBack?.()},providerOption.name,`${providerOption.name} setup`);dialog.showInfo(`${providerOption.method?.name??"Authentication"} is configured outside ${APP_NAME}.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()}async showApiKeyLoginDialog(providerId,providerName,onBack){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);providerId==="amazon-bedrock"&&dialog.showDetails([theme.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),theme.fg("muted","See:"),theme.fg("accent",` ${path13.join(getDocsPath(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,providerName,"api_key"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg==="Login cancelled"?onBack?.():this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`)}}showAuthSelect(dialog,prompt,providerId){return new Promise((resolve20,reject)=>{let restoreDialog=()=>{this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()},labels=prompt.options.map(option=>option.label),selector=new ExtensionSelectorComponent(prompt.message,labels,optionLabel=>{restoreDialog();let id=prompt.options.find(option=>option.label===optionLabel)?.id;id?resolve20(id):reject(new Error("Login cancelled"))},()=>{restoreDialog(),reject(new Error("Login cancelled"))},{description:providerId===RADIUS_PROVIDER_ID?RADIUS_LOGIN_INTRO:void 0});this.editorContainer.clear(),this.editorContainer.addChild(selector),this.ui.setFocus(selector),this.ui.requestRender()})}async showAuthPrompt(dialog,prompt,providerId){let response;if(prompt.type==="select"?response=this.showAuthSelect(dialog,prompt,providerId):prompt.type==="manual_code"?response=dialog.showManualInput(prompt.message):response=dialog.showPrompt(prompt.message,prompt.placeholder),!prompt.signal)return response;if(prompt.signal.aborted)throw new Error("Login cancelled");let signal=prompt.signal,onAbort,aborted=new Promise((_resolve,reject)=>{onAbort=()=>reject(new Error("Login cancelled")),signal.addEventListener("abort",onAbort,{once:!0})});try{return await Promise.race([response,aborted])}finally{onAbort&&signal.removeEventListener("abort",onAbort)}}notifyAuthDialog(dialog,event){event.type==="auth_url"?dialog.showAuth(event.url,event.instructions):event.type==="device_code"?(dialog.showDeviceCode(event),dialog.showWaiting("Waiting for authentication...")):event.type==="info"?dialog.showInfo(event.message,event.links):dialog.showProgress(event.message)}async loginProvider(dialog,providerId,providerName,method){this.programStatus.setBlocked("login",{kind:"auth",message:`Log in to ${providerName}`});try{await this.session.modelRuntime.login(providerId,method,{signal:dialog.signal,prompt:prompt=>this.showAuthPrompt(dialog,prompt,providerId),notify:event=>this.notifyAuthDialog(dialog,event)},{getDeviceId:()=>this.settingsManager.getOrCreateDeviceId()})}finally{this.programStatus.setBlocked("login",void 0)}}async showLoginDialog(providerId,providerName,onBack){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,providerName,"oauth"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel),providerId===RADIUS_PROVIDER_ID&&this.offerRadiusMcpServer(providerId,providerName)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg==="Login cancelled"?onBack?.():this.showError(`Failed to login to ${providerName}: ${errorMsg}`)}}offerRadiusMcpServer(providerId,providerName){let mcpPath=path13.join(getAgentDir(),"mcp.json"),normalizeUrl=url=>url.replace(/\/+$/u,""),{servers}=loadMcpConfig({agentDir:getAgentDir(),cwd:this.sessionManager.getCwd(),projectTrusted:!1}),existing=servers.find(server=>"url"in server.config&&normalizeUrl(server.config.url)===normalizeUrl(RADIUS_MCP_URL));if(existing&&"url"in existing.config&&existing.config.auth?.provider===providerId)return;let name=existing?.name??"radius";!existing&&servers.some(server=>server.name===name)&&(name="radius-mcp");let config=existing&&"url"in existing.config?{...existing.config,auth:{provider:providerId}}:{url:RADIUS_MCP_URL,auth:{provider:providerId}};delete config.oauth,this.showSelector(done=>{let selector=new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`,["Yes","No"],option=>{if(done(),option==="Yes"){try{addMcpServerConfig(mcpPath,name,config)}catch(error){this.showError(`Could not update ${mcpPath}: ${error instanceof Error?error.message:String(error)}`);return}this.handleReloadCommand()}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let reloadBox=new Container,borderColor=s=>theme.fg("border",s);reloadBox.addChild(new DynamicBorder(borderColor)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new ThemedText(()=>theme.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new DynamicBorder(borderColor));let previousEditor=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(reloadBox),this.ui.setFocus(reloadBox),this.ui.requestRender(!0),await new Promise(resolve20=>process.nextTick(resolve20));let dismissReloadBox=editor=>{this.editorContainer.clear(),this.editorContainer.addChild(editor),this.ui.setFocus(editor),this.ui.requestRender()},chatRestoredBeforeSessionStart=!1,reloadBoxDismissed=!1,restoreChatBeforeSessionStart=()=>{chatRestoredBeforeSessionStart||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),chatRestoredBeforeSessionStart=!0)};try{this.tasksUI?.dispose(),await this.session.reload({beforeSessionStart:restoreChatBeforeSessionStart}),this.tasksUI=bindTasksUI({tasks:this.session.tasks,ui:this.createExtensionUIContext()}),restoreChatBeforeSessionStart(),this.keybindings.reload();let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(this.toolOutputExpanded),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.applyRuntimeSettings(),this.themeController.applyFromSettings(),this.setupAutocompleteProvider();let runner=this.session.extensionRunner;this.setupExtensionShortcuts(runner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let savedImplicitProjectTrust=this.maybeSaveImplicitProjectTrustAfterReload(),modelsJsonError=this.session.modelRuntime.getError();modelsJsonError&&this.showError(`models.json error: ${modelsJsonError}`),this.showStatus(savedImplicitProjectTrust?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),dismissReloadBox(this.editor),reloadBoxDismissed=!0}catch(error){reloadBoxDismissed||dismissReloadBox(previousEditor),this.showError(`Reload failed: ${error instanceof Error?error.message:String(error)}`)}}async handleExportCommand(text2){let outputPath=this.getPathCommandArgument(text2,"/export");try{if(outputPath?.endsWith(".jsonl")){let filePath=this.session.exportToJsonl(outputPath);this.showStatus(`Session exported to: ${filePath}`)}else{let filePath=await this.session.exportToHtml(outputPath,{themeName:theme.name});this.showStatus(`Session exported to: ${filePath}`)}}catch(error){this.showError(`Failed to export session: ${error instanceof Error?error.message:"Unknown error"}`)}}getPathCommandArgument(text2,command){if(text2===command||!text2.startsWith(`${command} `))return;let argsString=text2.slice(command.length+1).trimStart();if(!argsString)return;let firstChar=argsString[0];if(firstChar==='"'||firstChar==="'"){let closingQuoteIndex=argsString.indexOf(firstChar,1);return closingQuoteIndex<0?void 0:argsString.slice(1,closingQuoteIndex)}let firstWhitespaceIndex=argsString.search(/\s/);return firstWhitespaceIndex<0?argsString:argsString.slice(0,firstWhitespaceIndex)}async handleImportCommand(text2){let inputPath=this.getPathCommandArgument(text2,"/import");if(!inputPath){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${inputPath}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(inputPath)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`)}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(inputPath,selectedCwd)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`);return}if(error instanceof SessionImportFileNotFoundError){this.showError(`Failed to import session: ${error.message}`);return}await this.handleFatalRuntimeError("Failed to import session",error)}}async handleShareCommand(){await shareSession({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)})}async handleBugCommand(hint){await reportBug({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,keybindings:this.keybindings,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)},hint)}async handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text2=this.session.getLastAssistantText();if(!text2){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text2),options.flashConfirmation&&this.ui instanceof TuiAltScreen?this.ui.flash("Copied!"):this.showStatus("Copied last agent message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}handleNameCommand(text2){let name=text2.replace(/^\/name\s*/,"").trim();if(!name){let currentName=this.sessionManager.getSessionName();currentName?(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",`Session name: ${currentName}`),1,0))):this.showWarning("Usage: /name <name>"),this.ui.requestRender();return}this.session.setSessionName(name);let sessionName=this.sessionManager.getSessionName();sessionName!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`),this.chatContainer.addChild(new Spacer(1));let displayName=sessionName??name;this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",`Session name set: ${displayName}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),cacheWarmingStatus=this.session.cacheWarmingStatus,cacheWarmingMode=this.settingsManager.getCacheWarmingMode(),model=this.session.model,selectedModelKey=`${model?.provider}/${model?.id}`,renderInfo=()=>{let info=`${theme.bold("Session Info")}
|
|
1838
|
+
`);return this.editor.setText(combinedText),this.updatePendingMessagesDisplay(),options?.abort&&this.session.abort(),allQueued.length}queueCompactionMessage(text2,mode){this.compactionQueuedMessages.push({text:text2,mode}),this.editor.addToHistory?.(text2),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(text2){if(!text2.startsWith("/"))return!1;let extensionRunner=this.session.extensionRunner,spaceIndex=text2.indexOf(" "),commandName=spaceIndex===-1?text2.slice(1):text2.slice(1,spaceIndex);return!!extensionRunner.getCommand(commandName)}async flushCompactionQueue(options){if(this.compactionQueuedMessages.length===0)return;let queuedMessages=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let restoreQueue=error=>{this.session.clearQueue(),this.compactionQueuedMessages=queuedMessages,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${queuedMessages.length>1?"s":""}: ${error instanceof Error?error.message:String(error)}`)};try{if(options?.willRetry){for(let message of queuedMessages)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay();return}let firstPromptIndex=queuedMessages.findIndex(message=>!this.isExtensionCommand(message.text));if(firstPromptIndex===-1){for(let message of queuedMessages)await this.session.prompt(message.text);return}let preCommands=queuedMessages.slice(0,firstPromptIndex),firstPrompt=queuedMessages[firstPromptIndex],rest=queuedMessages.slice(firstPromptIndex+1);for(let message of preCommands)await this.session.prompt(message.text);let promptPromise=this.session.prompt(firstPrompt.text,{streamingBehavior:firstPrompt.mode}).catch(error=>{restoreQueue(error)});for(let message of rest)this.isExtensionCommand(message.text)?await this.session.prompt(message.text):message.mode==="followUp"?await this.session.followUp(message.text):await this.session.steer(message.text);this.updatePendingMessagesDisplay()}catch(error){restoreQueue(error)}}flushPendingBashComponents(){for(let component of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(component),this.chatContainer.addChild(component);this.pendingBashComponents=[]}disposeActiveSelector(){let dispose=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,dispose?.()}showSelector(create){let token={},dispose,created=create(()=>{dispose?.(),this.activeSelectorToken===token&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))}),release2=created.dispose,released=!1;dispose=()=>{released||(released=!0,release2?.())},this.disposeActiveSelector(),this.activeSelectorToken=token,this.activeSelectorDispose=dispose,this.editorContainer.clear(),this.editorContainer.addChild(created.component),this.ui.setFocus(created.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(done=>{let selector,defaultProvider=this.settingsManager.getDefaultProvider(),defaultModelId=this.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:"not set";return selector=new SettingsSelectorComponent({autoCompact:this.session.autoCompactionEnabled,defaultModel,currentModel:this.session.model,availableDefaultModels:this.session.modelRuntime.getAvailableSnapshot(),showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),sessionShareDestination:this.settingsManager.getSessionShareDestination(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),cacheWarmingMode:this.settingsManager.getCacheWarmingMode(),thinkingLevel:this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:this.settingsManager.getAllModelThinkingLevels(),currentTheme:this.themeController.getThemeSelection()||SYSTEM_THEME_NAME,terminalTheme:this.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:enabled=>{this.session.setAutoCompactionEnabled(enabled),this.footer.setAutoCompactEnabled(enabled)},onShowImagesChange:enabled=>{this.settingsManager.setShowImages(enabled);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{this.settingsManager.setImageWidthCells(width);for(let child of this.chatContainer.children)child instanceof ToolExecutionComponent&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{this.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{this.settingsManager.setBlockImages(blocked)},onEnableSkillCommandsChange:enabled=>{this.settingsManager.setEnableSkillCommands(enabled),this.setupAutocompleteProvider()},onSteeringModeChange:mode=>{this.session.setSteeringMode(mode)},onFollowUpModeChange:mode=>{this.session.setFollowUpMode(mode)},onTransportChange:transport=>{this.settingsManager.setTransport(transport),this.session.agent.transport=transport},onSessionShareDestinationChange:destination=>{this.settingsManager.setSessionShareDestination(destination)},onHttpIdleTimeoutMsChange:timeoutMs=>{this.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),this.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`)},onCacheWarmingModeChange:mode=>{this.session.setCacheWarmingMode(mode),this.showStatus(`Cache warming: ${mode}`)},onModelThinkingLevelChange:(provider,modelId,level)=>{this.settingsManager.setModelThinkingLevel(provider,modelId,level);let current=this.session.model;current&¤t.provider===provider&¤t.id===modelId&&(this.session.setThinkingLevel(level),this.footer.invalidate(),this.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId)=>{this.settingsManager.removeModelThinkingLevel(provider,modelId);let current=this.session.model;if(current&¤t.provider===provider&¤t.id===modelId){let globalDefault=this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;this.session.setThinkingLevel(globalDefault),this.footer.invalidate(),this.updateEditorBorderColor()}},onThemeChange:themeSetting=>{this.settingsManager.setTheme(themeSetting),this.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>this.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{this.hideThinkingBlock=hidden,this.settingsManager.setHideThinkingBlock(hidden),this.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{this.settingsManager.setMermaidRenderingMode(mode),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{this.settingsManager.setShowCacheMissNotices(shown),this.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{this.settingsManager.setCollapseChangelog(collapsed)},onEnableInstallTelemetryChange:enabled=>{this.settingsManager.setEnableInstallTelemetry(enabled)},onQuietStartupChange:quiet=>{this.settingsManager.setQuietStartup(quiet)},onDefaultProjectTrustChange:defaultProjectTrust=>{this.settingsManager.setDefaultProjectTrust(defaultProjectTrust)},onDoubleEscapeActionChange:action=>{this.settingsManager.setDoubleEscapeAction(action)},onTreeFilterModeChange:mode=>{this.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{this.settingsManager.setShowHardwareCursor(enabled),this.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{this.settingsManager.setEditorPaddingX(padding),this.defaultEditor.setPaddingX(padding),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(padding)},onOutputPadChange:padding=>{this.settingsManager.setOutputPad(padding),this.outputPad=padding;for(let container of[this.chatContainer,this.pendingMessagesContainer])for(let child of container.children)"setOutputPad"in child&&typeof child.setOutputPad=="function"&&child.setOutputPad(padding);this.ui.requestRender()},onAutocompleteMaxVisibleChange:maxVisible=>{this.settingsManager.setAutocompleteMaxVisible(maxVisible),this.defaultEditor.setAutocompleteMaxVisible(maxVisible),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{this.settingsManager.setClearOnShrink(enabled),this.ui.setClearOnShrink(enabled),!enabled&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{this.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!this.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(mode),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${mode}`)},onFullscreenExitOutputChange:output=>{this.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{this.settingsManager.setFullscreenScrollbar(mode),this.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{this.settingsManager.setFullscreenCopyOnSelect(enabled),this.renderer instanceof TuiAltScreen&&this.renderer.setCopyOnSelect(enabled)},onFullscreenWheelScrollLinesChange:lines=>{this.settingsManager.setFullscreenWheelScrollLines(lines),this.renderer instanceof TuiAltScreen&&this.renderer.setWheelScrollLines(lines)},onWarningsChange:warnings=>{this.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),this.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}handleThinkingCommand(searchTerm){let availableLevels=this.session.getAvailableThinkingLevels();if(!searchTerm){this.showThinkingSelector();return}let normalized=searchTerm.trim().toLowerCase(),level=availableLevels.find(candidate=>candidate.toLowerCase()===normalized);if(!level){this.showError(`Unknown thinking level "${searchTerm}". Available levels: ${availableLevels.join(", ")}.`);return}this.selectThinkingLevel(level,!1)}selectThinkingLevel(level,persist){try{this.session.setThinkingLevel(level,{persist}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(persist?`Default thinking level: ${level}`:`Thinking level: ${level}`)}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showThinkingSelector(){this.showSelector(done=>{let selectLevel=(level,persist)=>{this.selectThinkingLevel(level,persist),done()},selector=new ThinkingSelectorComponent(this.session.thinkingLevel??DEFAULT_THINKING_LEVEL,this.session.getAvailableThinkingLevels(),level=>selectLevel(level,!1),()=>{done(),this.ui.requestRender()},level=>selectLevel(level,!0),this.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL);return{component:selector,focus:selector}})}async handleModelCommand(searchTerm){if(!searchTerm){this.showModelSelector();return}let model=await this.findExactModelMatch(searchTerm);if(model){try{await this.session.setModel(model,{persist:!1}),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model)}catch(error){this.showError(error instanceof Error?error.message:String(error))}return}this.showModelSelector(searchTerm)}async findExactModelMatch(searchTerm){let cachedModels=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):[...this.session.modelRuntime.getAvailableSnapshot()],cachedMatch=findExactModelReferenceMatch(searchTerm,cachedModels);if(cachedMatch||this.session.scopedModels.length>0)return cachedMatch;this.showStatus("Refreshing model catalogs\u2026");let controller=new AbortController,timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3);try{let result2=await refreshModelCatalogs(this.session.modelRuntime,controller.signal);result2.aborted&&timedOut?this.showWarning("Model refresh timed out; searching cached models."):result2.errors.size>0&&this.showWarning(`Could not refresh ${[...result2.errors.keys()].join(", ")}; searching cached models.`)}catch(error){this.showWarning(timedOut?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`)}finally{clearTimeout(timeout)}return findExactModelReferenceMatch(searchTerm,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let models=this.session.scopedModels.length>0?this.session.scopedModels.map(scoped=>scoped.model):this.session.modelRuntime.getAvailableSnapshot(),uniqueProviders=new Set(models.map(model=>model.provider));this.footerDataProvider.setAvailableProviderCount(uniqueProviders.size)}async maybeWarnAboutAnthropicSubscriptionAuth(model=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!model||model.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING);return}let apiKey=(await this.session.modelRuntime.getAuth(model.provider))?.auth.apiKey;if(!isAnthropicSubscriptionAuthKey(apiKey))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(ANTHROPIC_SUBSCRIPTION_AUTH_WARNING)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let cwd=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==cwd||!this.settingsManager.isProjectTrusted()||!hasTrustRequiringProjectResources(cwd))return!1;let trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir);try{return trustStore.get(cwd)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(trustStore.set(cwd,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(error){return this.showWarning(`Could not save project trust after reload: ${error instanceof Error?error.message:String(error)}`),!1}}showTrustSelector(){let cwd=this.sessionManager.getCwd(),trustStore=new ProjectTrustStore(this.runtimeHost.services.agentDir),savedDecision=trustStore.getEntry(cwd);this.showSelector(done=>{let selector=new TrustSelectorComponent({cwd,savedDecision,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:selection=>{trustStore.setMany(selection.updates),done(),this.showStatus(`Saved trust decision: ${selection.trusted?"trusted":"untrusted"}. Restart ${APP_NAME} for this to take effect.`)},onCancel:()=>{done(),this.ui.requestRender()}});return{component:selector,focus:selector}})}showModelSelector(initialSearchInput){this.showSelector(done=>{let selectModel=async(model,persist)=>{try{await this.session.setModel(model,{persist}),this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),done(),this.showStatus(persist?`Default model: ${model.provider}/${model.id}`:`Model: ${model.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(model)}catch(error){done(),this.showError(error instanceof Error?error.message:String(error))}},defaultProvider=this.settingsManager.getDefaultProvider(),defaultModel=this.settingsManager.getDefaultModel(),selector=new ModelSelectorComponent(this.ui,this.session.model,this.session.modelRuntime,this.session.scopedModels,model=>selectModel(model,!1),()=>{done(),this.ui.requestRender()},initialSearchInput,model=>selectModel(model,!0),defaultProvider&&defaultModel?{provider:defaultProvider,id:defaultModel}:void 0);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showModelsSelector(){let availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),configuredPatterns=this.settingsManager.getEnabledModels(),sessionScopedModels=this.session.scopedModels,configuredEnabledIds=models=>{if(!configuredPatterns?.length)return null;let resolved=resolveModelScopeFromModels(configuredPatterns,models),ids=resolved.scopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`);for(let diagnostic of resolved.diagnostics)diagnostic.code==="no-match"&&!ids.includes(diagnostic.pattern)&&ids.push(diagnostic.pattern);return ids},currentEnabledIds=sessionScopedModels.length>0?sessionScopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`):configuredEnabledIds(availableModels),selectionChanged=!1,updateSessionModels=enabledIds=>{currentEnabledIds=enabledIds===null?null:[...enabledIds];let hasEnabledAvailableModel=enabledIds?.some(id=>availableModelIds.has(id))??!1,allAvailableModelsEnabled=enabledIds!==null&&[...availableModelIds].every(id=>enabledIds.includes(id));if(enabledIds&&hasEnabledAvailableModel&&!allAvailableModelsEnabled){let newScopedModels=resolveModelScopeFromModels(enabledIds,availableModels).scopedModels;this.session.setScopedModels(newScopedModels.map(scoped=>({model:scoped.model,thinkingLevel:scoped.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(done=>{let disposed=!1,timedOut=!1,controller=new AbortController,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3),selector=new ScopedModelsSelectorComponent({allModels:availableModels,enabledModelIds:currentEnabledIds,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:enabledIds=>{selectionChanged=!0,updateSessionModels(enabledIds)},onPersist:enabledIds=>{let allEnabled=enabledIds!==null&&enabledIds.length===availableModels.length&&enabledIds.every(id=>availableModelIds.has(id)),newPatterns=enabledIds===null||allEnabled?void 0:enabledIds;this.settingsManager.setEnabledModels(newPatterns?[...newPatterns]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{done(),this.ui.requestRender()}});return refreshModelCatalogs(this.session.modelRuntime,controller.signal).then(result2=>{disposed||(availableModels=[...this.session.modelRuntime.getAvailableSnapshot()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result2.aborted&&timedOut?selector.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):result2.errors.size>0?selector.setRefreshStatus(`Could not refresh ${[...result2.errors.keys()].join(", ")}; showing cached models.`,"warning"):selector.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(error=>{disposed||(selector.setRefreshStatus(timedOut?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${error instanceof Error?error.message:String(error)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(timeout)),{component:selector,focus:selector,dispose:()=>{disposed=!0,clearTimeout(timeout),controller.abort()}}})}showUserMessageSelector(){let userMessages=this.session.getUserMessagesForForking();if(userMessages.length===0){this.showStatus("No messages to fork from");return}let initialSelectedId=userMessages[userMessages.length-1]?.entryId;this.showSelector(done=>{let selector=new UserMessageSelectorComponent(userMessages.map(m2=>({id:m2.entryId,text:m2.text})),async entryId=>{done();try{let result2=await this.runtimeHost.fork(entryId);if(result2.cancelled){this.ui.requestRender();return}this.editor.setText(result2.selectedText??""),this.showStatus("Forked to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},()=>{done(),this.ui.requestRender()},initialSelectedId);return{component:selector,focus:selector.getMessageList()}})}async handleCloneCommand(){let leafId=this.sessionManager.getLeafId();if(!leafId){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(leafId,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}showTreeSelector(initialSelectedId){let tree=this.sessionManager.getTree(),realLeafId=this.sessionManager.getLeafId(),initialFilterMode=this.settingsManager.getTreeFilterMode();if(tree.length===0){this.showStatus("No entries in session");return}this.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,this.ui.terminal.rows,async entryId=>{if(entryId===this.sessionManager.getLeafId()){done(),this.showStatus("Already at this point");return}done();let wantsSummary=!1,customInstructions;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(summaryChoice===void 0){this.showTreeSelector(entryId);return}if(wantsSummary=summaryChoice!=="No summary",!(summaryChoice==="Summarize with custom prompt"&&(customInstructions=await this.showExtensionEditor("Custom summarization instructions"),customInstructions===void 0)))break}if(this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort()),this.session.isCompacting){this.showError("Wait for the current compaction or tree navigation to finish before navigating the session tree.");return}let showingSummaryIndicator=!1,originalOnEscape=this.defaultEditor.onEscape;wantsSummary&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new Spacer(1)),this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui)),showingSummaryIndicator=!0,this.ui.requestRender());try{let result2=await this.session.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result2.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(entryId);return}if(result2.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),result2.editorText&&!this.editor.getText().trim()&&this.editor.setText(result2.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(error){this.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=originalOnEscape}},()=>{done(),this.ui.requestRender()},(entryId,label)=>{this.sessionManager.appendLabelChange(entryId,label),this.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text2=>{if(!text2){this.showError("Selected entry has no text to copy");return}try{await copyToClipboard(text2),this.showStatus("Copied selected message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}showSessionSelector(){this.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>SessionManager.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),onProgress,signal),(onProgress,signal)=>this.sessionManager.usesDefaultSessionDir()?SessionManager.listAll(onProgress,signal):SessionManager.listAll(this.sessionManager.getSessionDir(),onProgress,signal),async sessionPath=>{done(),await this.handleResumeSession(sessionPath)},()=>{done(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:selector,focus:selector}})}async handleResumeSession(sessionPath,options){this.clearStatusIndicator();try{let result2=await this.runtimeHost.switchSession(sessionPath,{withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session"),result2}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd)return this.showStatus("Resume cancelled"),{cancelled:!0};let result2=await this.runtimeHost.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession,projectTrustContextFactory:cwd=>this.createProjectTrustContext(cwd)});return result2.cancelled||this.showStatus("Resumed session in current cwd"),result2}return this.handleFatalRuntimeError("Failed to resume session",error)}}getLoginProviderOptions(authType){let options=[];for(let provider of this.session.modelRuntime.getProviders()){let authStatus=this.session.modelRuntime.getProviderAuthStatus(provider.id),status=authStatus.configured?{type:this.session.modelRuntime.isUsingOAuth(provider.id)?"oauth":"api_key",source:authStatus.label??authStatus.source}:void 0,subscription=provider.auth.oauth?.isSubscription===!0;(!authType||authType==="oauth")&&provider.auth.oauth&&options.push({id:provider.id,name:provider.name,authType:"oauth",method:provider.auth.oauth,status,subscription}),(!authType||authType==="api_key")&&provider.auth.apiKey&&options.push({id:provider.id,name:provider.name,authType:"api_key",method:provider.auth.apiKey,status,subscription})}return options.sort((a,b2)=>a.name.localeCompare(b2.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId,type})=>{let provider=this.session.modelRuntime.getProvider(providerId);return{id:providerId,name:provider?.name??providerId,authType:type,status:{type,source:"stored credential"},subscription:provider?.auth.oauth?.isSubscription===!0}}).sort((a,b2)=>a.name.localeCompare(b2.name))}findLoginProviderOptions(providerRef){let normalizedProviderRef=providerRef.trim().toLowerCase();return normalizedProviderRef?this.getLoginProviderOptions().filter(provider=>provider.id.toLowerCase()===normalizedProviderRef||provider.name.toLowerCase()===normalizedProviderRef):[]}async handleLoginCommand(providerRef){if(!providerRef){this.showLoginAuthTypeSelector();return}let providerOptions=this.findLoginProviderOptions(providerRef);if(providerOptions.length===1){await this.startProviderLogin(providerOptions[0]);return}if(providerOptions.length>1&&new Set(providerOptions.map(provider=>provider.id)).size===1){this.showLoginAuthTypeSelector(providerOptions);return}this.showLoginProviderSelector(void 0,providerRef)}async startProviderLogin(providerOption,onBack){providerOption.authType==="oauth"?await this.showLoginDialog(providerOption.id,providerOption.name,onBack):providerOption.method?.login?await this.showApiKeyLoginDialog(providerOption.id,providerOption.name,onBack):this.showAmbientAuthDialog(providerOption,onBack)}showLoginAuthTypeSelector(providerOptions){let radiusOption=providerOptions?void 0:this.getLoginProviderOptions("oauth").find(provider=>provider.id===RADIUS_PROVIDER_ID),radiusText=radiusOption?`Sign in with ${radiusOption.name}`:void 0,radiusLabel=radiusOption?`${radiusText}${formatAuthSelectorProviderStatus(radiusOption)}`:void 0,oauthProvider=providerOptions?.find(provider=>provider.authType==="oauth"),subscriptionLabel=(oauthProvider?.method&&"loginLabel"in oauthProvider.method?oauthProvider.method.loginLabel:void 0)??"Sign in with an account",apiKeyLabel="Sign in with an API key",availableAuthTypes=providerOptions?new Set(providerOptions.map(provider=>provider.authType)):new Set(["oauth","api_key"]),options=[];if(availableAuthTypes.has("oauth")&&options.push(subscriptionLabel),availableAuthTypes.has("api_key")&&options.push(apiKeyLabel),radiusLabel&&options.push(radiusLabel),options.length===0){this.showStatus("No login methods available.");return}if(providerOptions&&options.length===1){let providerOption=providerOptions[0];providerOption&&this.startProviderLogin(providerOption);return}let title=providerOptions?.[0]?`Select authentication method for ${providerOptions[0].name}:`:"Select authentication method:";this.showSelector(done=>{let onSelect=option=>{if(done(),radiusOption&&option===radiusLabel){this.startProviderLogin(radiusOption,()=>this.showLoginAuthTypeSelector());return}let authType=option===subscriptionLabel?"oauth":"api_key";if(providerOptions){let providerOption=providerOptions.find(provider=>provider.authType===authType);providerOption&&this.startProviderLogin(providerOption,()=>this.showLoginAuthTypeSelector(providerOptions));return}this.showLoginProviderSelector(authType)},onCancel=()=>{done(),this.ui.requestRender()},selector=radiusLabel&&radiusText?createLoginMenuSelector(this.ui,title,options,{label:radiusLabel,text:radiusText},onSelect,onCancel):new ExtensionSelectorComponent(title,options,onSelect,onCancel);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}showLoginProviderSelector(authType,initialSearchInput){let providerOptions=this.getLoginProviderOptions(authType);if(providerOptions.length===0){let message=authType==="oauth"?"No account providers available.":authType==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(message);return}this.showSelector(done=>{let selector=new OAuthSelectorComponent("login",providerOptions,async(providerId,selectedAuthType)=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId&&provider.authType===selectedAuthType);providerOption&&await this.startProviderLogin(providerOption,()=>this.showLoginProviderSelector(authType,initialSearchInput))},()=>{done(),authType?this.showLoginAuthTypeSelector():this.ui.requestRender()},initialSearchInput);return{component:selector,focus:selector}})}async showOAuthSelector(mode){if(mode==="login"){this.showLoginAuthTypeSelector();return}let providerOptions;try{providerOptions=await this.getLogoutProviderOptions()}catch(error){this.showError(`Could not read stored credentials: ${error instanceof Error?error.message:String(error)}`);return}if(providerOptions.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(done=>{let selector=new OAuthSelectorComponent(mode,providerOptions,async providerId=>{done();let providerOption=providerOptions.find(provider=>provider.id===providerId);if(providerOption)try{await this.session.modelRuntime.logout(providerOption.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let message=providerOption.authType==="oauth"?`Logged out of ${providerOption.name}`:`Removed stored API key for ${providerOption.name}. Environment variables and models.json config are unchanged.`;this.showStatus(message)}catch(error){let message=error instanceof Error?error.message:String(error);this.showError(error instanceof CredentialSynchronizationError?`Credentials removed for ${providerOption.name}, but local model state could not be synchronized: ${message}`:`Logout failed: ${message}`)}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async completeProviderAuthentication(providerId,providerName,authType,previousModel){let actionLabel=authType==="oauth"?`Logged in to ${providerName}`:`Saved API key for ${providerName}`,session=this.session,deferSelection=isUnknownModel(previousModel)&&hasDefaultModelProvider(providerId)&&!session.modelRuntime.getAvailableSnapshot().some(model=>model.provider===providerId&&model.id===defaultModelPerProvider[providerId]),finishAuthentication=async()=>{let selectedModel,selectionError;if(isUnknownModel(previousModel)){let providerModels=this.session.modelRuntime.getAvailableSnapshot().filter(model=>model.provider===providerId);if(providerId==="llama.cpp")selectionError=llamaCppPostLoginGuidance(actionLabel,providerModels.length);else if(!hasDefaultModelProvider(providerId))selectionError=`${actionLabel}, but no default model is configured for provider "${providerId}". Use /model to select a model.`;else if(providerModels.length===0)selectionError=`${actionLabel}, but no models are available for that provider. Use /model to select a model.`;else{let defaultModelId=defaultModelPerProvider[providerId];if(selectedModel=providerModels.find(model=>model.id===defaultModelId)??(providerId==="radius"?providerModels[0]:void 0),!selectedModel)selectionError=`${actionLabel}, but its default model "${defaultModelId}" is not available. Use /model to select a model.`;else try{await this.session.setModel(selectedModel,{persist:!0})}catch(error){selectedModel=void 0;let errorMessage9=error instanceof Error?error.message:String(error);selectionError=`${actionLabel}, but selecting its default model failed: ${errorMessage9}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),selectedModel?(this.showStatus(`${actionLabel}. Selected ${selectedModel.id}. Credentials saved to ${getAuthPath()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(selectedModel)):(this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}`),selectionError?this.showError(selectionError):this.maybeWarnAboutAnthropicSubscriptionAuth())};deferSelection?this.showStatus(`${actionLabel}. Credentials saved to ${getAuthPath()}. Refreshing model catalog\u2026`):await finishAuthentication();let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);session.modelRuntime.refresh({providers:[providerId],signal:controller.signal}).then(async result2=>{result2.aborted?this.showWarning(`${actionLabel}, but its model catalog refresh timed out; using cached models.`):result2.errors.size>0&&this.showWarning(`${actionLabel}, but its model catalog could not be refreshed; using cached models.`),deferSelection&&this.session===session&&session.model===previousModel&&await finishAuthentication(),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(error=>{this.showWarning(`${actionLabel}, but its model catalog could not be refreshed: ${error instanceof Error?error.message:String(error)}`)}).finally(()=>clearTimeout(timeout))}showAmbientAuthDialog(providerOption,onBack){let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},dialog=new LoginDialogComponent(this.ui,providerOption.id,()=>{restoreEditor3(),onBack?.()},providerOption.name,`${providerOption.name} setup`);dialog.showInfo(`${providerOption.method?.name??"Authentication"} is configured outside ${APP_NAME}.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()}async showApiKeyLoginDialog(providerId,providerName,onBack){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);providerId==="amazon-bedrock"&&dialog.showDetails([theme.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),theme.fg("muted","See:"),theme.fg("accent",` ${path13.join(getDocsPath(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,providerName,"api_key"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"api_key",previousModel)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Saved API key for ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg==="Login cancelled"?onBack?.():this.showError(`Failed to save API key for ${providerName}: ${errorMsg}`)}}showAuthSelect(dialog,prompt,providerId){return new Promise((resolve20,reject)=>{let restoreDialog=()=>{this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender()},labels=prompt.options.map(option=>option.label),selector=new ExtensionSelectorComponent(prompt.message,labels,optionLabel=>{restoreDialog();let id=prompt.options.find(option=>option.label===optionLabel)?.id;id?resolve20(id):reject(new Error("Login cancelled"))},()=>{restoreDialog(),reject(new Error("Login cancelled"))},{description:providerId===RADIUS_PROVIDER_ID?RADIUS_LOGIN_INTRO:void 0});this.editorContainer.clear(),this.editorContainer.addChild(selector),this.ui.setFocus(selector),this.ui.requestRender()})}async showAuthPrompt(dialog,prompt,providerId){let response;if(prompt.type==="select"?response=this.showAuthSelect(dialog,prompt,providerId):prompt.type==="manual_code"?response=dialog.showManualInput(prompt.message):response=dialog.showPrompt(prompt.message,prompt.placeholder),!prompt.signal)return response;if(prompt.signal.aborted)throw new Error("Login cancelled");let signal=prompt.signal,onAbort,aborted=new Promise((_resolve,reject)=>{onAbort=()=>reject(new Error("Login cancelled")),signal.addEventListener("abort",onAbort,{once:!0})});try{return await Promise.race([response,aborted])}finally{onAbort&&signal.removeEventListener("abort",onAbort)}}notifyAuthDialog(dialog,event){event.type==="auth_url"?dialog.showAuth(event.url,event.instructions):event.type==="device_code"?(dialog.showDeviceCode(event),dialog.showWaiting("Waiting for authentication...")):event.type==="info"?dialog.showInfo(event.message,event.links):dialog.showProgress(event.message)}async loginProvider(dialog,providerId,providerName,method){this.programStatus.setBlocked("login",{kind:"auth",message:`Log in to ${providerName}`});try{await this.session.modelRuntime.login(providerId,method,{signal:dialog.signal,prompt:prompt=>this.showAuthPrompt(dialog,prompt,providerId),notify:event=>this.notifyAuthDialog(dialog,event)},{getDeviceId:()=>this.settingsManager.getOrCreateDeviceId()})}finally{this.programStatus.setBlocked("login",void 0)}}async showLoginDialog(providerId,providerName,onBack){let previousModel=this.session.model,dialog=new LoginDialogComponent(this.ui,providerId,(_success,_message)=>{},providerName);this.editorContainer.clear(),this.editorContainer.addChild(dialog),this.ui.setFocus(dialog),this.ui.requestRender();let restoreEditor3=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(dialog,providerId,providerName,"oauth"),restoreEditor3(),await this.completeProviderAuthentication(providerId,providerName,"oauth",previousModel),providerId===RADIUS_PROVIDER_ID&&this.offerRadiusMcpServer(providerId,providerName)}catch(error){restoreEditor3();let errorMsg=error instanceof Error?error.message:String(error);error instanceof CredentialSynchronizationError?this.showError(`Logged in to ${providerName}, but local model state could not be synchronized: ${errorMsg}`):errorMsg==="Login cancelled"?onBack?.():this.showError(`Failed to login to ${providerName}: ${errorMsg}`)}}offerRadiusMcpServer(providerId,providerName){let mcpPath=path13.join(getAgentDir(),"mcp.json"),normalizeUrl=url=>url.replace(/\/+$/u,""),{servers}=loadMcpConfig({agentDir:getAgentDir(),cwd:this.sessionManager.getCwd(),projectTrusted:!1}),existing=servers.find(server=>"url"in server.config&&normalizeUrl(server.config.url)===normalizeUrl(RADIUS_MCP_URL));if(existing&&"url"in existing.config&&existing.config.auth?.provider===providerId)return;let name=existing?.name??"radius";!existing&&servers.some(server=>server.name===name)&&(name="radius-mcp");let config=existing&&"url"in existing.config?{...existing.config,auth:{provider:providerId}}:{url:RADIUS_MCP_URL,auth:{provider:providerId}};delete config.oauth,this.showSelector(done=>{let selector=new ExtensionSelectorComponent(`Configure ${providerName} MCP in ${mcpPath}?`,["Yes","No"],option=>{if(done(),option==="Yes"){try{addMcpServerConfig(mcpPath,name,config)}catch(error){this.showError(`Could not update ${mcpPath}: ${error instanceof Error?error.message:String(error)}`);return}this.handleReloadCommand()}},()=>{done(),this.ui.requestRender()});return{component:selector,focus:selector}})}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let reloadBox=new Container,borderColor=s=>theme.fg("border",s);reloadBox.addChild(new DynamicBorder(borderColor)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new ThemedText(()=>theme.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),reloadBox.addChild(new Spacer(1)),reloadBox.addChild(new DynamicBorder(borderColor));let previousEditor=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(reloadBox),this.ui.setFocus(reloadBox),this.ui.requestRender(!0),await new Promise(resolve20=>process.nextTick(resolve20));let dismissReloadBox=editor=>{this.editorContainer.clear(),this.editorContainer.addChild(editor),this.ui.setFocus(editor),this.ui.requestRender()},chatRestoredBeforeSessionStart=!1,reloadBoxDismissed=!1,restoreChatBeforeSessionStart=()=>{chatRestoredBeforeSessionStart||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),chatRestoredBeforeSessionStart=!0)};try{await this.session.reload({beforeSessionStart:restoreChatBeforeSessionStart}),restoreChatBeforeSessionStart(),this.keybindings.reload();let activeHeader=this.customHeader??this.builtInHeader;isExpandable(activeHeader)&&activeHeader.setExpanded(this.toolOutputExpanded),setRegisteredThemes(this.session.resourceLoader.getThemes().themes),this.applyRuntimeSettings(),this.themeController.applyFromSettings(),this.setupAutocompleteProvider();let runner=this.session.extensionRunner;this.setupExtensionShortcuts(runner),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let savedImplicitProjectTrust=this.maybeSaveImplicitProjectTrustAfterReload(),modelsJsonError=this.session.modelRuntime.getError();modelsJsonError&&this.showError(`models.json error: ${modelsJsonError}`),this.showStatus(savedImplicitProjectTrust?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),dismissReloadBox(this.editor),reloadBoxDismissed=!0}catch(error){reloadBoxDismissed||dismissReloadBox(previousEditor),this.showError(`Reload failed: ${error instanceof Error?error.message:String(error)}`)}}async handleExportCommand(text2){let outputPath=this.getPathCommandArgument(text2,"/export");try{if(outputPath?.endsWith(".jsonl")){let filePath=this.session.exportToJsonl(outputPath);this.showStatus(`Session exported to: ${filePath}`)}else{let filePath=await this.session.exportToHtml(outputPath,{themeName:theme.name});this.showStatus(`Session exported to: ${filePath}`)}}catch(error){this.showError(`Failed to export session: ${error instanceof Error?error.message:"Unknown error"}`)}}getPathCommandArgument(text2,command){if(text2===command||!text2.startsWith(`${command} `))return;let argsString=text2.slice(command.length+1).trimStart();if(!argsString)return;let firstChar=argsString[0];if(firstChar==='"'||firstChar==="'"){let closingQuoteIndex=argsString.indexOf(firstChar,1);return closingQuoteIndex<0?void 0:argsString.slice(1,closingQuoteIndex)}let firstWhitespaceIndex=argsString.search(/\s/);return firstWhitespaceIndex<0?argsString:argsString.slice(0,firstWhitespaceIndex)}async handleImportCommand(text2){let inputPath=this.getPathCommandArgument(text2,"/import");if(!inputPath){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${inputPath}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(inputPath)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`)}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await this.promptForMissingSessionCwd(error);if(!selectedCwd){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(inputPath,selectedCwd)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${inputPath}`);return}if(error instanceof SessionImportFileNotFoundError){this.showError(`Failed to import session: ${error.message}`);return}await this.handleFatalRuntimeError("Failed to import session",error)}}async handleShareCommand(){await shareSession({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)})}async handleBugCommand(hint){await reportBug({session:this.session,ui:this.ui,editorContainer:this.editorContainer,editor:this.editor,keybindings:this.keybindings,showStatus:message=>this.showStatus(message),showError:message=>this.showError(message)},hint)}async handleCopyCommand(options={}){if(options.preferSelection&&this.ui instanceof TuiAltScreen&&!this.ui.getCopyOnSelect()&&this.ui.hasActiveSelection()){await this.ui.copyActiveSelectionToClipboard();return}let text2=this.session.getLastAssistantText();if(!text2){this.showError("No agent messages to copy yet.");return}try{await copyToClipboard(text2),options.flashConfirmation&&this.ui instanceof TuiAltScreen?this.ui.flash("Copied!"):this.showStatus("Copied last agent message to clipboard")}catch(error){this.showError(error instanceof Error?error.message:String(error))}}handleNameCommand(text2){let name=text2.replace(/^\/name\s*/,"").trim();if(!name){let currentName=this.sessionManager.getSessionName();currentName?(this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",`Session name: ${currentName}`),1,0))):this.showWarning("Usage: /name <name>"),this.ui.requestRender();return}this.session.setSessionName(name);let sessionName=this.sessionManager.getSessionName();sessionName!==name&&this.showWarning(`Session name was normalized from ${JSON.stringify(name)} to ${JSON.stringify(sessionName)}`),this.chatContainer.addChild(new Spacer(1));let displayName=sessionName??name;this.chatContainer.addChild(new ThemedText(()=>theme.fg("dim",`Session name set: ${displayName}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let stats=this.session.getSessionStats(),sessionName=this.sessionManager.getSessionName(),entries=this.sessionManager.getEntries(),cacheWaste=computeCacheWaste(entries,this.session.modelRuntime),usageBreakdown=getUsageCostBreakdown(entries),cacheWarmingStatus=this.session.cacheWarmingStatus,cacheWarmingMode=this.settingsManager.getCacheWarmingMode(),model=this.session.model,selectedModelKey=`${model?.provider}/${model?.id}`,renderInfo=()=>{let info=`${theme.bold("Session Info")}
|
|
1865
1839
|
|
|
1866
1840
|
`;sessionName&&(info+=`${theme.fg("dim","Name:")} ${sessionName}
|
|
1867
1841
|
`),info+=`${theme.fg("dim","File:")} ${stats.sessionFile??"In-memory"}
|
|
@@ -1938,7 +1912,12 @@ ${theme.fg("dim","Cache Re-billed:")} ${detail}`}}return info};this.chatContaine
|
|
|
1938
1912
|
| \`/\` | Slash commands |
|
|
1939
1913
|
| \`!\` | Run bash command |
|
|
1940
1914
|
| \`!!\` | Run bash command (excluded from context) |
|
|
1941
|
-
`;
|
|
1915
|
+
`;for(let section of getRegisteredKeybindingHelpSections()){hotkeys+=`
|
|
1916
|
+
**${section.title}**
|
|
1917
|
+
| Key | Action |
|
|
1918
|
+
|-----|--------|
|
|
1919
|
+
`;for(let row of section.rows)hotkeys+=`| \`${this.getEditorKeyDisplay(row.action)}\` | ${row.description} |
|
|
1920
|
+
`}let shortcuts=this.session.extensionRunner.getShortcuts(this.keybindings.getEffectiveConfig());if(shortcuts.size>0){hotkeys+=`
|
|
1942
1921
|
**Extensions**
|
|
1943
1922
|
| Key | Action |
|
|
1944
1923
|
|-----|--------|
|
|
@@ -1967,7 +1946,7 @@ changes anytime in settings.json.`),1,0)),this.addChild(new Spacer(1)),this.addO
|
|
|
1967
1946
|
${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(resolve20=>{let keybindings=KeybindingsManager2.create();setKeybindings(keybindings);let resolved=!1,selector=new SessionSelectorComponent(currentSessionsLoader,allSessionsLoader,path14=>{resolved||(resolved=!0,ui.stop(),resolve20(path14))},()=>{resolved||(resolved=!0,ui.stop(),resolve20(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?
|
|
1968
1947
|
${cwd}
|
|
1969
1948
|
|
|
1970
|
-
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??SETTINGS_DEFAULTS.defaultProjectTrust){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.btw.close":{defaultKeys:"escape",description:"Close the BTW conversation"},"app.btw.cancel":{defaultKeys:"ctrl+c",description:"Stop the BTW answer, or close when idle"},"app.btw.scrollUp":{defaultKeys:"up",description:"Scroll BTW up when the editor is empty"},"app.btw.scrollDown":{defaultKeys:"down",description:"Scroll BTW down when the editor is empty"}});var TOOL_DENIAL="Tools are unavailable in this BTW conversation. Answer using the inherited context only.",UNKNOWN_TOOL_RESULT="This tool had not returned a result when the BTW context snapshot was captured. Its outcome is unknown here; the original task may still be running.",BTW_REMINDER=`<btw-reminder>
|
|
1949
|
+
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??SETTINGS_DEFAULTS.defaultProjectTrust){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.btw.close":{defaultKeys:"escape",description:"Close the BTW conversation"},"app.btw.cancel":{defaultKeys:"ctrl+c",description:"Stop the BTW answer, or close when idle"},"app.btw.scrollUp":{defaultKeys:"up",description:"Scroll BTW up when the editor is empty"},"app.btw.scrollDown":{defaultKeys:"down",description:"Scroll BTW down when the editor is empty"}});function registerListKeybindings(){registerKeybindings({"app.list.toggle":{defaultKeys:"space",description:"Toggle selected list item"}})}registerListKeybindings();registerKeybindings({"app.provider.switchPaneLeft":{defaultKeys:"left",description:"/provider: focus the left pane"},"app.provider.switchPaneRight":{defaultKeys:"right",description:"/provider: focus the right pane"},"app.provider.removeEntry":{defaultKeys:"ctrl+x",description:"/provider: remove the selected compat or dictionary entry"}});registerListKeybindings();var TASK_KEYBINDINGS={"app.tasks.detach":{defaultKeys:"ctrl+b",description:"Move foreground tasks to the background"},"app.tasks.previousTab":{defaultKeys:"left",description:"Show Output in the focused task inspector"},"app.tasks.nextTab":{defaultKeys:"right",description:"Show Details in the focused task inspector"},"app.tasks.kill":{defaultKeys:"k",description:"Stop the selected task"},"app.tasks.confirmStop":{defaultKeys:"enter",description:"Confirm stopping the selected task"},"app.tasks.detachSelected":{defaultKeys:"b",description:"Move the selected task to the background"},"app.tasks.search":{defaultKeys:"/",description:"Search retained task identities and labels"},"app.tasks.follow":{defaultKeys:"f",description:"Follow the selected task's output"},"app.tasks.top":{defaultKeys:"home",description:"Go to the top of the task list or preview"},"app.tasks.bottom":{defaultKeys:"end",description:"Go to the bottom of the task list or preview"},"app.tasks.nextFocus":{defaultKeys:"tab",description:"Switch between task list and inspector"},"app.tasks.previousFocus":{defaultKeys:"shift+tab",description:"Switch between task inspector and list"},"app.tasks.help":{defaultKeys:"?",description:"Show task controls"}};registerKeybindings(TASK_KEYBINDINGS);registerReservedKeybindings("app.tasks.detach");registerKeybindingHelpSection({id:"tasks",title:"Tasks",rows:[{action:"app.tasks.detach",description:TASK_KEYBINDINGS["app.tasks.detach"].description},{action:"app.tasks.detachSelected",description:`${TASK_KEYBINDINGS["app.tasks.detachSelected"].description} (while /tasks is open)`}]});var TOOL_DENIAL="Tools are unavailable in this BTW conversation. Answer using the inherited context only.",UNKNOWN_TOOL_RESULT="This tool had not returned a result when the BTW context snapshot was captured. Its outcome is unknown here; the original task may still be running.",BTW_REMINDER=`<btw-reminder>
|
|
1971
1950
|
This is a separate side conversation about the preceding context. Answer the user's side questions without continuing or changing the original task. The original task may still be running; later activity is not part of this snapshot.
|
|
1972
1951
|
Tool definitions are retained for prompt-cache reuse, but tools cannot be executed here. Use only the available context, and say when it does not contain the answer.
|
|
1973
1952
|
This conversation is temporary: it is not added to the original conversation and is discarded when the user closes the BTW panel.
|
|
@@ -2064,10 +2043,10 @@ The llama.cpp server needs HF_TOKEN with access.`,["Continue","Back"])!=="Contin
|
|
|
2064
2043
|
${details.id}`,options);if(!choice||(quantization=details.quantizations[options.indexOf(choice)]?.name,!quantization))return}let model=quantization?`${details.id}:${quantization}`:details.id,result2=await runWithProgress(ui,{title:"Downloading model",model,initialMessage:"Starting\u2026",cancelTitle:"Stop download?",cancelMessage:model,run:(signal,update)=>client.downloadAndWait(model,update,signal),cancel:()=>client.unload(model)});result2.cancelled||(await syncCatalog(ctx,client,result2.value),ctx.ui.notify(`Downloaded ${model}`))};pi.registerCommand("llama",{description:"Manage llama.cpp router models",handler:async(_args,ctx)=>{if(ctx.mode!=="tui"){ctx.ui.notify("/llama is available in interactive mode","warning");return}let client=await configuredClient(ctx);client&&await showLlamaUi(ctx,async ui=>{let readCatalog2=async()=>{for(;;)try{return await syncCatalog(ctx,client)}catch(error){if(await ui.connectionError(client.serverUrl,connectionErrorMessage(error))==="close")return}},catalog=await readCatalog2();if(catalog)for(;;){let action=await ui.showModels(client.serverUrl,catalog);if(action.type==="close")return;let actionError;try{action.type==="download"?await downloadModel(ctx,ui,client):modelIsLoaded(action.model)?await unloadModel(ctx,ui,client,action.model):action.model.status.value==="unloaded"?await loadModel(ctx,ui,client,catalog,action.model):ctx.ui.notify(`${action.model.id} is ${action.model.status.value}`,"warning")}catch(error){actionError=error}let refreshed=await readCatalog2();if(!refreshed)return;catalog=refreshed,actionError&&!isConnectionError(actionError)&&ctx.ui.notify(actionError instanceof Error?actionError.message:String(actionError),"error")}})}})}var COMMAND_NAME="provider",COMMAND_DESCRIPTION="Manage models.json providers: connection, API type, and models",NO_UI_WARNING="/provider requires interactive TUI mode.",NO_MODELS_FILE_WARNING="models.json is disabled for this runtime (custom SDK configuration), so /provider is unavailable.",API_TYPES=["openai-responses","openai-completions","anthropic-messages","google-generative-ai","azure-openai-responses","openai-codex-responses","mistral-conversations","google-vertex","bedrock-converse-stream","pi-messages"],INPUT_TYPES=["text","image"],THINKING_LEVELS4=["off","minimal","low","medium","high","xhigh","max"],PROBE_LIMITS={timeoutMs:1e4,maxBodyBytes:4194304,maxErrorBytes:4096,maxErrorChars:400,maxModels:2e3,maxPages:5},MAX_CANDIDATES=8,REFRESH_TIMEOUT_MS=15e3;function formatError2(error){return error instanceof Error?error.message:String(error)}function plural(count,word){return count===1?word:word.endsWith("y")?`${word.slice(0,-1)}ies`:`${word}s`}function truncate3(value,max){return value.length<=max?value:`${value.slice(0,Math.max(0,max-1))}\u2026`}function maskApiKey(value){return!value||value.startsWith("$")||value.startsWith("!")?value:value.length<=8?"\u2022\u2022\u2022\u2022\u2022\u2022":`\u2022\u2022\u2022\u2022\u2022\u2022${value.slice(-4)}`}var import_proper_lockfile5=__toESM(require_proper_lockfile(),1);import{randomUUID as randomUUID9}from"node:crypto";import{mkdir,readFile as readFile6,realpath as realpath2,rename,rm,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname25,join as join45}from"node:path";var indexCache;function builtinCatalogIndex(){if(indexCache)return indexCache;let entries=[];for(let providerId of getBuiltinProviders())for(let model of getBuiltinModels(providerId))entries.push({providerId,model});return indexCache=entries,entries}function isBuiltinProviderId(providerId){return getBuiltinProviders().includes(providerId)}function builtinDefaults(providerId,modelId,api){if(!isBuiltinProviderId(providerId))return{};let models=getBuiltinModels(providerId);if(models.length===0)return{};let found=(modelId?models.find(model=>model.id===modelId):void 0)??(api?models.find(model=>model.api===api):void 0)??models.find(model=>model.api==="openai-completions")??models[0];return{api:found.api,baseUrl:found.baseUrl}}function normalizeId(id){return(id.includes("/")?id.slice(id.lastIndexOf("/")+1):id).toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")}function sortTier(matches,preferredApi){return matches.sort((a,b2)=>{if(preferredApi){let aPreferred=a.entry.model.api===preferredApi?0:1,bPreferred=b2.entry.model.api===preferredApi?0:1;if(aPreferred!==bPreferred)return aPreferred-bPreferred}return a.entry.model.id.localeCompare(b2.entry.model.id)})}function matchBuiltinModels(query,preferredApi,max=MAX_CANDIDATES){let trimmed=query.trim();if(!trimmed)return[];let index3=builtinCatalogIndex(),normalizedQuery=normalizeId(trimmed),exact=[],normalized=[],consumed=new Set;for(let entry of index3)entry.model.id===trimmed?(exact.push({entry,tier:"exact"}),consumed.add(entry)):normalizeId(entry.model.id)===normalizedQuery&&(normalized.push({entry,tier:"normalized"}),consumed.add(entry));let remaining=sortTier(index3.filter(entry=>!consumed.has(entry)).map(entry=>({entry,tier:"fuzzy"})),preferredApi),fuzzy=fuzzyFilter(remaining,trimmed,({entry})=>`${entry.model.id} ${entry.model.name} ${entry.providerId}`);return[...sortTier(exact,preferredApi),...sortTier(normalized,preferredApi),...fuzzy].slice(0,max)}var DEFAULT_CONTEXT_WINDOW=128e3,DEFAULT_MAX_TOKENS=16384;function formatCostRates(cost){return`$${cost.input} / $${cost.output} in/out (cache $${cost.cacheRead} / $${cost.cacheWrite})`}function computeFieldChanges(current,reference,effectiveApi){let changes=[],unset=key=>current[key]===void 0;changes.push({field:"name",patches:[{path:["name"],value:reference.name}],checked:unset("name")&&reference.name!==reference.id,applicable:!0,currentText:current.name??`not set (falls back to id${current.id?` "${current.id}"`:""})`,referenceText:reference.name}),changes.push({field:"reasoning",patches:[{path:["reasoning"],value:reference.reasoning}],checked:unset("reasoning")&&reference.reasoning===!0,applicable:!0,currentText:current.reasoning===void 0?"false (default)":String(current.reasoning),referenceText:String(reference.reasoning)}),changes.push({field:"input",patches:[{path:["input"],value:reference.input}],checked:unset("input"),applicable:!0,currentText:current.input?current.input.join(", "):"text (default)",referenceText:reference.input.join(", ")}),changes.push({field:"contextWindow",patches:[{path:["contextWindow"],value:reference.contextWindow}],checked:unset("contextWindow"),applicable:!0,currentText:current.contextWindow===void 0?`${DEFAULT_CONTEXT_WINDOW} (default)`:String(current.contextWindow),referenceText:String(reference.contextWindow)}),changes.push({field:"maxTokens",patches:[{path:["maxTokens"],value:reference.maxTokens}],checked:unset("maxTokens"),applicable:!0,currentText:current.maxTokens===void 0?`${DEFAULT_MAX_TOKENS} (default)`:String(current.maxTokens),referenceText:String(reference.maxTokens)});let sameApi=effectiveApi!==void 0&&reference.api===effectiveApi;if(reference.thinkingLevelMap&&Object.keys(reference.thinkingLevelMap).length>0){let details=Object.entries(reference.thinkingLevelMap).map(([level,target])=>`${level}: ${target===null?"null (hidden)":target}`);changes.push({field:"thinkingLevelMap",patches:sameApi?Object.entries(reference.thinkingLevelMap).map(([level,value])=>({path:["thinkingLevelMap",level],value})):[],checked:!1,applicable:sameApi,currentText:current.thinkingLevelMap?`${Object.keys(current.thinkingLevelMap).length} ${plural(Object.keys(current.thinkingLevelMap).length,"mapping")}`:"not set",referenceText:`${details.length} ${plural(details.length,"mapping")}`,referenceDetails:details})}if(reference.compat&&Object.keys(reference.compat).length>0){let patches=[];if(sameApi)for(let[key,value]of Object.entries(reference.compat))if(["chatTemplateKwargs","chatTemplateArgs","openRouterRouting","vercelGatewayRouting"].includes(key)&&value!==null&&typeof value=="object"&&!Array.isArray(value))for(let[entry,item]of Object.entries(value))patches.push({path:["compat",key,entry],value:item});else patches.push({path:["compat",key],value});let details=Object.entries(reference.compat).map(([key,value])=>`${key}: ${JSON.stringify(value)}`);changes.push({field:"compat",patches,checked:!1,applicable:sameApi,currentText:current.compat?`${Object.keys(current.compat).length} ${plural(Object.keys(current.compat).length,"entry")}`:"not set",referenceText:`${details.length} ${plural(details.length,"entry")}`,referenceDetails:details})}if(reference.cost){let{input:input2,output,cacheRead,cacheWrite}=reference.cost,rates={input:input2,output,cacheRead,cacheWrite};changes.push({field:"cost",patches:current.cost?Object.entries(rates).map(([rate,value])=>({path:["cost",rate],value})):[{path:["cost"],value:rates}],checked:!1,applicable:!0,currentText:current.cost?formatCostRates(current.cost):"all 0 (default)",referenceText:formatCostRates(reference.cost),referenceDetails:[`input: $${reference.cost.input} / M tokens`,`output: $${reference.cost.output} / M tokens`,`cacheRead: $${reference.cost.cacheRead} / M tokens`,`cacheWrite: $${reference.cost.cacheWrite} / M tokens`],referenceHasTiers:Array.isArray(reference.cost.tiers)&&reference.cost.tiers.length>0})}return changes}function hasProviderSettings(provider){return!!(provider&&(provider.baseUrl||provider.apiKey||provider.headers||provider.compat||provider.oauth||provider.authHeader!==void 0||provider.models?.length||Object.keys(provider.modelOverrides??{}).length))}function effectiveModelSettings(providerId,provider,model={}){let fallback=builtinDefaults(providerId,model.id,model.api??provider?.api);return{api:model.api??provider?.api??fallback.api,baseUrl:model.baseUrl??provider?.baseUrl??fallback.baseUrl}}var DELETE=Symbol("provider-store-delete");function setPath(root,path14,value){let current=root;for(let segment2 of path14.slice(0,-1)){let next=Object.hasOwn(current,segment2)?current[segment2]:void 0;if(typeof next=="object"&&next!==null&&!Array.isArray(next))current=next;else{let created={};Object.defineProperty(current,segment2,{value:created,writable:!0,enumerable:!0,configurable:!0}),current=created}}let leaf=path14[path14.length-1];value===DELETE?delete current[leaf]:Object.defineProperty(current,leaf,{value:structuredClone(value),writable:!0,enumerable:!0,configurable:!0})}function isPlainObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function jsonEquals(a,b2){if(a===b2)return!0;if(Array.isArray(a)&&Array.isArray(b2))return a.length===b2.length&&a.every((entry,index3)=>jsonEquals(entry,b2[index3]));if(isPlainObject2(a)&&isPlainObject2(b2)){let aKeys=Object.keys(a).sort(),bKeys=Object.keys(b2).sort();return aKeys.length===bKeys.length&&aKeys.every((key,index3)=>key===bKeys[index3]&&jsonEquals(a[key],b2[key]))}return!1}function cloneValue(value){return value===DELETE?value:structuredClone(value)}async function readDocument(path14){let rawText;try{rawText=await readFile6(path14,"utf8")}catch(error){if(error.code==="ENOENT")return{exists:!1,doc:{providers:{}}};throw error}let parsed=JSON.parse(stripJsonComments(stripBom(rawText)));if(!isPlainObject2(parsed))throw new Error("models.json root must be a JSON object.");let doc=parsed;if(!isPlainObject2(doc.providers))throw new Error('models.json "providers" must be an object.');return{exists:!0,doc,rawText}}var ModelsJsonStore=class _ModelsJsonStore{constructor(path14,baseline){this.ops=[],this.seq=0,this.backedUp=!1,this.batching=!1,this.saveChain=Promise.resolve(),this.drafts=new Set,this.lastSaveResult={kind:"clean"},this.path=path14,this.baseline=baseline,this.view=structuredClone(baseline)}static async load(path14){let normalized=normalizePath(path14),disk;try{normalized=await realpath2(normalized).catch(error=>{if(error.code==="ENOENT")return normalized;throw error}),disk=await readDocument(normalized)}catch(error){return{ok:!1,error:`Failed to parse models.json: ${formatError2(error)}
|
|
2065
2044
|
|
|
2066
2045
|
File: ${normalized}`}}if(disk.exists){let validationError=(await ModelConfig.load(normalized)).getError();if(validationError)return{ok:!1,error:validationError}}return{ok:!0,store:new _ModelsJsonStore(normalized,disk.doc)}}getDoc(){return this.view}getProviderIds(){return[...new Set([...Object.keys(this.view.providers),...this.ops.map(op=>op.providerId)])]}getProvider(providerId){return Object.hasOwn(this.view.providers,providerId)?this.view.providers[providerId]:void 0}ensureProviderView(providerId){Object.hasOwn(this.view.providers,providerId)||(this.drafts.add(providerId),this.recomputeView())}isDraftProvider(providerId){return!Object.hasOwn(this.baseline.providers,providerId)&&Object.hasOwn(this.view.providers,providerId)}getModels(providerId){let provider=this.getProvider(providerId);return Array.isArray(provider?.models)?provider.models:[]}getModel(providerId,modelId){return this.getModels(providerId).find(model=>model.id===modelId)}get pendingCount(){return this.ops.length}getPendingError(providerId){let pending=this.ops.filter(op=>providerId===void 0||op.providerId===providerId);if(pending.length!==0)return this.lastSaveResult.kind==="error"||this.lastSaveResult.kind==="invalid"?this.lastSaveResult.error:`${pending.length} change(s) are not saved; retry or discard before continuing.`}retrySave(){this.ops.length>0&&this.scheduleSave()}discardPending(){this.ops=[],this.drafts.clear(),this.recomputeView()}enqueue(op){this.ops.push(op),this.recomputeView(),this.scheduleSave()}nextSeq(){return++this.seq}setProviderField(providerId,path14,value){this.enqueue({kind:"set",seq:this.nextSeq(),providerId,path:path14,value:cloneValue(value),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}setModelField(providerId,modelId,path14,value){this.enqueue({kind:"set",seq:this.nextSeq(),providerId,modelId,path:path14,value:cloneValue(value),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}addModel(providerId,model){this.enqueue({kind:"addModel",seq:this.nextSeq(),providerId,model:structuredClone(model),createProvider:!Object.hasOwn(this.baseline.providers,providerId)})}removeModel(providerId,modelId){this.enqueue({kind:"removeModel",seq:this.nextSeq(),providerId,modelId})}async renameModel(providerId,oldId,newId){await this.flush();let pendingError=this.getPendingError(providerId);if(pendingError)return pendingError;let before=this.getModel(providerId,oldId);if(!before)return"The model no longer exists.";let seq=this.nextSeq();if(this.enqueue({kind:"renameModel",seq,providerId,oldId,newId}),await this.flush(),this.ops.some(op=>op.seq===seq))return this.ops=this.ops.filter(op=>op.seq!==seq),this.recomputeView(),this.getPendingError(providerId)??"Failed to save models.json.";let renamed=this.getModel(providerId,newId);return renamed&&jsonEquals(renamed,{...before,id:newId})?void 0:"The model changed on disk; reopen it before renaming."}removeProvider(providerId){this.enqueue({kind:"removeProvider",seq:this.nextSeq(),providerId})}batch(mutate){this.batching=!0;try{mutate()}finally{this.batching=!1}this.ops.length>0&&this.scheduleSave()}discardProviderDraft(providerId){this.drafts.delete(providerId),!Object.hasOwn(this.baseline.providers,providerId)&&(this.ops=this.ops.filter(op=>op.providerId!==providerId),this.recomputeView())}recomputeView(){let view=structuredClone(this.baseline);for(let id of this.drafts)ensureProvider(view,id);for(let op of this.ops)applyOp(view,op);this.view=view}scheduleSave(){this.batching||(this.saveChain=this.saveChain.catch(()=>{}).then(async()=>{let result2=await this.save();this.lastSaveResult=result2,result2.kind!=="clean"&&this.onSaveResult?.(result2)}))}async flush(){let pending;do pending=this.saveChain,await pending;while(pending!==this.saveChain)}async save(){if(this.ops.length===0)return{kind:"clean"};try{return await withFileMutationQueue(this.path,async()=>{await mkdir(dirname25(this.path),{recursive:!0});let compromised,release2=await import_proper_lockfile5.default.lock(this.path,{realpath:!1,stale:3e4,retries:{retries:20,factor:1.2,minTimeout:50,maxTimeout:250},onCompromised:error=>{compromised=error}}),result2;try{result2=await this.saveLocked(()=>{if(compromised)throw compromised})}catch(error){result2={kind:"error",error:`Failed to save models.json: ${formatError2(error)}`}}try{await release2()}catch(error){!compromised&&result2.kind!=="error"&&result2.kind!=="invalid"&&(result2={kind:"error",error:`Could not release the models.json lock: ${formatError2(error)}`})}return result2})}catch(error){return{kind:"error",error:`Failed to access models.json for saving: ${formatError2(error)}`}}}async saveLocked(assertLock){let tempPath=join45(dirname25(this.path),`.models.${randomUUID9()}.tmp`);try{assertLock();let disk;try{disk=await readDocument(this.path)}catch(error){return{kind:"error",error:`models.json changed on disk and is unreadable: ${formatError2(error)}`}}let working=structuredClone(disk.doc),batch=this.ops.filter(op=>{let provider=this.getProvider(op.providerId);return Object.hasOwn(disk.doc.providers,op.providerId)||!provider||Object.keys(provider).length===0||hasProviderSettings(provider)});for(let op of batch)applyOp(working,op);pruneEmptyNewProviders(working,disk.doc);let settle=()=>{let settled=new Set(batch.map(op=>op.seq));this.ops=this.ops.filter(op=>!settled.has(op.seq)),this.recomputeView()};if(jsonEquals(working,disk.doc))return this.baseline=disk.doc,settle(),{kind:"saved",applied:batch.length};let candidate=`${JSON.stringify(working,null,2)}
|
|
2067
|
-
`;await writeFile3(tempPath,candidate,{encoding:"utf8",mode:384});let validationError=(await ModelConfig.load(tempPath)).getError();if(validationError)return{kind:"invalid",error:validationError};let latest=await readDocument(this.path);if(latest.exists!==disk.exists||latest.rawText!==disk.rawText)throw new Error("models.json changed while saving; the edits were kept for retry.");return!this.backedUp&&disk.exists&&disk.rawText!==void 0&&(await writeFile3(`${this.path}.bak`,disk.rawText,{encoding:"utf8",mode:384}),this.backedUp=!0),assertLock(),await rename(tempPath,this.path),this.baseline=working,settle(),{kind:"saved",applied:batch.length}}finally{await rm(tempPath,{force:!0}).catch(()=>{})}}};function ensureProvider(doc,providerId){let existing=Object.hasOwn(doc.providers,providerId)?doc.providers[providerId]:void 0;if(existing)return existing;let created={};return Object.defineProperty(doc.providers,providerId,{value:created,writable:!0,enumerable:!0,configurable:!0}),created}function applyOp(doc,op){switch(op.kind){case"set":{let provider=ensureProvider(doc,op.providerId);if(op.modelId===void 0){setPath(provider,op.path,op.value);return}let model=(Array.isArray(provider.models)?provider.models:[]).find(entry=>entry.id===op.modelId);model&&setPath(model,op.path,op.value);return}case"addModel":{let provider=ensureProvider(doc,op.providerId),models=Array.isArray(provider.models)?provider.models:[],index3=models.findIndex(entry=>entry.id===op.model.id),clone=structuredClone(op.model);index3>=0?models[index3]=clone:models.push(clone),provider.models=models;return}case"removeModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!provider||!models)return;provider.models=models.filter(entry=>entry.id!==op.modelId);return}case"renameModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!models)return;let model=models.find(entry=>entry.id===op.oldId);model&&!models.some(entry=>entry.id===op.newId)&&(model.id=op.newId);return}case"removeProvider":{delete doc.providers[op.providerId];return}}}function pruneEmptyNewProviders(working,disk){for(let[providerId,provider]of Object.entries(working.providers))Object.hasOwn(disk.providers,providerId)||isPlainObject2(provider)&&Object.keys(provider).length===0&&delete working.providers[providerId]}var RefreshCoordinator=class{constructor(runtime){this.pending=new Map,this.changed=new Set,this.revision=0,this.runtime=runtime}touch(providerId){this.pending.set(providerId,++this.revision),this.changed.add(providerId)}get touchedProviders(){return[...this.changed]}async refreshNow(providerId,signal){return this.run([providerId],signal)}async flush(signal){let providers=[...this.pending.keys()];return providers.length===0?{ok:!0,aborted:!1,errors:[]}:this.run(providers,signal)}async run(providers,signal){let revisions=new Map(providers.map(id=>[id,this.pending.get(id)])),combined=AbortSignal.any([...signal?[signal]:[],AbortSignal.timeout(REFRESH_TIMEOUT_MS)]),errors=[];try{let result2=await this.runtime.refresh({allowNetwork:!1,providers,signal:combined});for(let[providerId,error]of result2.errors)errors.push(`${providerId}: ${formatError2(error)}`);let configError=this.runtime.getError();configError&&errors.push(configError);let aborted=result2.aborted||combined.aborted;aborted&&errors.length===0&&errors.push("Refresh was cancelled or timed out.");let ok=errors.length===0&&!aborted;if(ok)for(let id of providers)this.pending.get(id)===revisions.get(id)&&this.pending.delete(id);return{ok,aborted,errors}}catch(error){return errors.push(formatError2(error)),{ok:!1,aborted:combined.aborted,errors}}}};function registerListKeybindings(){registerKeybindings({"app.list.toggle":{defaultKeys:"space",description:"Toggle selected list item"}})}registerListKeybindings();registerKeybindings({"app.provider.switchPaneLeft":{defaultKeys:"left",description:"/provider: focus the left pane"},"app.provider.switchPaneRight":{defaultKeys:"right",description:"/provider: focus the right pane"},"app.provider.removeEntry":{defaultKeys:"ctrl+x",description:"/provider: remove the selected compat or dictionary entry"}});async function probeProviderModels(opts){let baseUrl;try{baseUrl=new URL(opts.baseUrl)}catch{return{ok:!1,error:"Base URL is not a valid URL."}}if(baseUrl.protocol!=="http:"&&baseUrl.protocol!=="https:")return{ok:!1,error:`Unsupported protocol: ${baseUrl.protocol}`};if(baseUrl.username||baseUrl.password||baseUrl.hash)return{ok:!1,error:"Base URL must not contain credentials or a fragment."};if(opts.signal?.aborted)return{ok:!1,error:"Cancelled."};let controller=new AbortController,timeoutMs=opts.timeoutMs??PROBE_LIMITS.timeoutMs,timer=setTimeout(()=>controller.abort(),timeoutMs),onOuterAbort=()=>controller.abort();opts.signal?.addEventListener("abort",onOuterAbort,{once:!0});let doFetch=opts.fetch??globalThis.fetch,getPage=async(url,headers)=>{let response=await doFetch(url,{method:"GET",headers,signal:controller.signal});if(!response.ok){let body2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxErrorBytes,signal:controller.signal});return{ok:!1,status:response.status,error:`HTTP ${response.status}${body2?`: ${safeErrorText(body2,opts.auth).slice(0,PROBE_LIMITS.maxErrorChars)}`:""}`}}let text2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxBodyBytes,overflowMessage:`Response exceeds ${PROBE_LIMITS.maxBodyBytes} bytes.`,signal:controller.signal});try{return{ok:!0,json:JSON.parse(text2)}}catch{return{ok:!1,error:"Model catalog response is not JSON."}}};try{let url=modelCatalogUrl(baseUrl,opts.api),headers=buildHeaders(opts.auth,opts.api),page=await getPage(url,headers),retry=page.ok?void 0:openAIStyleRetry(baseUrl,opts.auth,opts.api,{url,headers,status:page.status});if(!page.ok&&retry){let retried=await getPage(retry.url,retry.headers);if(!retried.ok)return{ok:!1,error:safeErrorText(`${url.href} \u2192 HTTP ${page.status}; OpenAI-style retry ${retry.url.href} \u2192 ${retried.error}`,opts.auth)};({url,headers}=retry),page=retried}if(!page.ok)return{ok:!1,error:page.error};let models=parseCatalogModels(page.json);if(models===null)return{ok:!1,error:"JSON has no supported OpenAI-style data[] or models[] catalog with model ids. Add models manually if this endpoint uses another catalog format."};let json=page.json;for(let pages=1;opts.api==="anthropic-messages"&&pages<PROBE_LIMITS.maxPages&&models.length<PROBE_LIMITS.maxModels;pages++){let cursor=nextPageCursor(json);if(!cursor)break;let nextUrl=new URL(url.href);nextUrl.searchParams.set("after_id",cursor),nextUrl.searchParams.set("limit","1000");let next=await getPage(nextUrl,headers),more=next.ok?parseCatalogModels(next.json):null;if(!next.ok||!more||(models.push(...more),nextPageCursor(next.json)===cursor))break;json=next.json}let sorted=dedupeSort(models),truncated=sorted.length>PROBE_LIMITS.maxModels||declaresMorePages(json);return{ok:!0,models:sorted.slice(0,PROBE_LIMITS.maxModels),truncated}}catch(error){return controller.signal.aborted?{ok:!1,error:opts.signal?.aborted?"Cancelled.":`Timed out after ${timeoutMs}ms.`}:{ok:!1,error:safeErrorText(formatError2(error),opts.auth)}}finally{clearTimeout(timer),opts.signal?.removeEventListener("abort",onOuterAbort)}}function modelCatalogUrl(base,api){let url=new URL(base.href),path14=url.pathname.replace(/\/+$/,"");return url.pathname=api==="anthropic-messages"&&!path14.endsWith("/v1")?`${path14}/v1/models`:`${path14}/models`,url}function openAIStyleRetry(base,auth,api,first){if(api!=="anthropic-messages"||![401,403,404].includes(first.status??0)||Object.keys(auth?.headers??{}).some(key=>key.toLowerCase()==="authorization"))return;let root=new URL(base.href);root.pathname=root.pathname.replace(/\/+$/,"").replace(/\/anthropic$/i,"");let url=modelCatalogUrl(root,api),headers=buildHeaders(auth,void 0);return url.href===first.url.href&&headers.get("authorization")===first.headers.get("authorization")?void 0:{url,headers}}function safeErrorText(text2,auth){for(let value of[auth?.apiKey,...Object.values(auth?.headers??{})]){if(typeof value!="string"||!value)continue;text2=text2.replaceAll(value,"[redacted]");let token=value.replace(/^Bearer\s+/i,"");token!==value&&token&&(text2=text2.replaceAll(token,"[redacted]"))}return stripTerminalSequences(text2)}function buildHeaders(auth,api){let headers=new Headers;headers.set("accept","application/json");let configured=auth?.headers??{};api==="anthropic-messages"&&headers.set("anthropic-version","2023-06-01");let hasAuthorization=!1;for(let[key,value]of Object.entries(configured))key.toLowerCase()==="authorization"&&(hasAuthorization=!0),typeof value=="string"?headers.set(key,value):value===null&&headers.delete(key);if(!auth?.apiKey||hasAuthorization)return headers;let lower=name=>Object.keys(configured).some(key=>key.toLowerCase()===name);return api==="anthropic-messages"?(auth.apiKey.includes("sk-ant-oat")?headers.set("authorization",`Bearer ${auth.apiKey}`):(lower("x-api-key")||headers.set("x-api-key",auth.apiKey),lower("anthropic-version")||headers.set("anthropic-version","2023-06-01")),headers):api==="google-generative-ai"||api==="google-vertex"?(lower("x-goog-api-key")||headers.set("x-goog-api-key",auth.apiKey),headers):(headers.set("authorization",`Bearer ${auth.apiKey}`),headers)}function declaresMorePages(json){return typeof json=="object"&&json!==null&&"has_more"in json&&json.has_more===!0}function nextPageCursor(json){if(!declaresMorePages(json))return;let lastId=json.last_id;return typeof lastId=="string"&&lastId?lastId:void 0}var CONTEXT_WINDOW_FIELDS=["context_window","context_window.tokens","context_length","top_provider.context_length","max_input_tokens","max_context_length","max_model_len","context_size","metadata.context_length"],MAX_TOKENS_FIELDS=["max_output_tokens","max_completion_tokens","top_provider.max_completion_tokens","max_tokens","max_output_length"],INPUT_MODALITY_FIELDS=["input_modalities","architecture.input_modalities","modalities.input"],IMAGE_FLAG_FIELDS=["supports_vision","enable_vision_input","capabilities.vision","capabilities.image_input.supported"],REASONING_FLAG_FIELDS=["reasoning","supports_reasoning","enable_reason","capabilities.reasoning","capabilities.thinking.supported"],REASONING_LEVEL_FIELDS=["effort.supported_levels","reasoning_effort_support_list"],CAPABILITY_LIST_FIELDS=["supported_parameters","tags","features","supported_features","metadata.tags"];function fieldAt(record,path14){let value=record;for(let key of path14.split(".")){if(!value||typeof value!="object"||Array.isArray(value))return;value=value[key]}return value}function listAt(record,path14){let value=fieldAt(record,path14);return Array.isArray(value)?value.filter(entry=>typeof entry=="string").map(entry=>entry.toLowerCase()):[]}function declaredLimit(record,paths){let limit;for(let path14 of paths){let value=fieldAt(record,path14);typeof value=="number"&&Number.isSafeInteger(value)&&value>0&&(limit=Math.min(limit??value,value))}return limit}function declaresImageInput(record){return INPUT_MODALITY_FIELDS.some(path14=>listAt(record,path14).includes("image"))||IMAGE_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("vision"))}function declaresReasoning(record){return REASONING_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||REASONING_LEVEL_FIELDS.some(path14=>listAt(record,path14).length>0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("reasoning"))}function parseCatalogModels(json){if(!json||typeof json!="object")return null;let payload=json,data=Array.isArray(json)?json:Array.isArray(payload.models)?payload.models:payload.data;if(!Array.isArray(data))return null;let models=[];for(let item of data){if(!item||typeof item!="object")continue;let record=item,id=(typeof record.id=="string"?record.id.trim():"")||(typeof record.slug=="string"?record.slug.trim():"");if(!id)continue;let displayName=typeof record.name=="string"&&record.name.trim()?record.name.trim():void 0,anthropicName=typeof record.display_name=="string"&&record.display_name.trim()?record.display_name.trim():typeof record.displayName=="string"?record.displayName.trim():void 0,name=(displayName??anthropicName)!==id?displayName??anthropicName:void 0,model=name?{id,name}:{id},contextWindow=declaredLimit(record,CONTEXT_WINDOW_FIELDS);contextWindow&&(model.contextWindow=contextWindow);let maxTokens=declaredLimit(record,MAX_TOKENS_FIELDS);maxTokens&&(model.maxTokens=maxTokens),declaresImageInput(record)&&(model.input=["text","image"]),declaresReasoning(record)&&(model.reasoning=!0),models.push(model)}return data.length>0&&models.length===0?null:models}function dedupeSort(models){let map=new Map;for(let model of models)map.has(model.id)||map.set(model.id,model);return[...map.values()].sort((a,b2)=>a.id.localeCompare(b2.id))}async function fetchProviderModels(options,signal){let{store,refresher,runtime,providerId}=options,deadline=AbortSignal.any([signal,AbortSignal.timeout(PROBE_LIMITS.timeoutMs)]);try{await raceWithAbortSignal(store.flush(),deadline);let unsaved=store.getPendingError(providerId);if(unsaved)return{ok:!1,error:`Save the provider changes before fetching: ${unsaved}`};let provider=store.getProvider(providerId),settings2=effectiveModelSettings(providerId,provider);if(!settings2.baseUrl)return{ok:!1,error:"Set a baseUrl under API Auth first."};let sync=await refresher.refreshNow(providerId,deadline);if(deadline.throwIfAborted(),!sync.ok)return{ok:!1,error:`The provider did not reload: ${sync.errors.join("; ")}`};let resolved=await raceWithAbortSignal(runtime.getAuth(providerId,{signal:deadline}),deadline),configured=provider?.apiKey!==void 0||provider?.authHeader===!0||Object.keys(provider?.headers??{}).length>0||runtime.getProviderAuthStatus(providerId).configured;if(!resolved&&configured)return{ok:!1,error:"Configured credentials or headers did not resolve; check the provider authentication."};let result2=await probeProviderModels({baseUrl:resolved?.auth.baseUrl??settings2.baseUrl,auth:resolved?.auth,api:settings2.api,signal:deadline});return deadline.throwIfAborted(),result2}catch(error){return deadline.aborted?{ok:!1,error:signal.aborted?"Cancelled.":"Timed out while preparing or fetching the model catalog."}:{ok:!1,error:formatError2(error)}}}async function importProviderModels(options,models,signal){let{store,refresher,providerId}=options;await raceWithAbortSignal(store.flush(),signal);let unsaved=store.getPendingError(providerId);if(unsaved)return unsaved;let settings2=effectiveModelSettings(providerId,store.getProvider(providerId));if(!settings2.api||!settings2.baseUrl)return"Set baseUrl and API Type under API Auth before importing models.";let existing=new Set(store.getModels(providerId).map(model=>model.id)),fresh=models.filter(model=>existing.has(model.id)?!1:(existing.add(model.id),!0));if(fresh.length===0)return;signal.throwIfAborted(),options.edits.addModels(fresh),await store.flush();let saveError=store.getPendingError(providerId);if(saveError)return saveError;let outcome=await refresher.refreshNow(providerId,signal);if(!outcome.ok)return`Models were saved, but refresh failed: ${outcome.errors.join("; ")}`}var ProviderEdits=class{constructor(store,providerId,refresher,refresh){this.renaming=!1,this.store=store,this.providerId=providerId,this.refresher=refresher,this.refresh=refresh}changed(){(!this.store.isDraftProvider(this.providerId)||hasProviderSettings(this.store.getProvider(this.providerId)))&&this.refresher.touch(this.providerId),this.refresh()}setProviderField(path14,value){this.store.setProviderField(this.providerId,path14,value),this.changed()}removeProvider(){this.store.removeProvider(this.providerId),this.changed()}removeModel(modelId){this.store.removeModel(this.providerId,modelId),this.changed()}batch(apply){this.store.batch(apply)}addModels(models){this.store.batch(()=>{for(let model of models)this.store.addModel(this.providerId,model)}),models.length>0&&this.changed()}draft(){let fields={};return{isDraft:!0,read:()=>fields,setField:(path14,value)=>{setPath(fields,path14,value),this.refresh()}}}commitDraft(draft){let fields=draft.read(),id=(fields.id??"").trim();if(!id)return"Model id is required.";if(this.store.getModel(this.providerId,id))return`Model "${id}" already exists.`;let settings2=effectiveModelSettings(this.providerId,this.store.getProvider(this.providerId),fields);if(!settings2.api)return"Cannot resolve an api \u2014 set one under Model-Specific API or the provider's API Auth.";if(!settings2.baseUrl)return"Cannot resolve a baseUrl \u2014 set one under Model-Specific API or the provider's API Auth.";this.store.addModel(this.providerId,{...fields,id}),this.changed()}model(modelId,onRename){let id=modelId,snapshot;return{isDraft:!1,read:()=>snapshot??this.store.getModel(this.providerId,id)??{id},setField:(path14,value)=>{this.store.setModelField(this.providerId,id,path14,value),this.changed()},rename:async newId=>{let oldId=id;snapshot=this.store.getModel(this.providerId,id),this.renaming=!0;try{let error=await this.store.renameModel(this.providerId,id,newId);if(error)return error;id=newId,this.changed();return}finally{snapshot=void 0,this.renaming=!1,onRename(oldId,id)}}}}};var CURSOR2="\u203A",PASTE_START="\x1B[200~",PASTE_END="\x1B[201~",ValueEditor=class{constructor(callbacks){this.input=new Input({prompt:""}),this.input.onSubmit=callbacks.onCommit,this.input.onEscape=callbacks.onCancel}beginOverwrite(firstData){this.input.setValue(""),firstData&&this.input.handleInput(firstData)}reset(value){this.beginTweak(value)}beginTweak(current){this.input.setValue(""),this.input.handleInput(PASTE_START+current+PASTE_END),this.input.setValue(current)}get value(){return this.input.getValue()}handleInput(data){this.input.handleInput(data)}renderLine(width){return this.input.render(Math.max(1,width))[0]??""}get focused(){return this.input.focused}set focused(value){this.input.focused=value}};function renderKeyValueLine(theme2,opts){let lit=opts.active&&opts.paneFocused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",keyPrefix=opts.keyLabel===void 0?"":`${opts.keyLabel}: `,keyColor=lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"";if(opts.editing){let body2=opts.editing.renderLine(Math.max(1,opts.width-visibleWidth(marker)-visibleWidth(keyPrefix)));return truncateToWidth(marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(keyColor,body2)+note,opts.width)}let valueColor=opts.unset?"dim":keyColor,line=marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(valueColor,opts.valueText??"")+note;return truncateToWidth(line,opts.width)}function renderPlainLine(theme2,text2,opts){let lit=(opts.active??!1)&&(opts.paneFocused??!1),marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",check=opts.checked===void 0?"":opts.checked?"[x] ":"[ ] ",color2=opts.dim?"dim":lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"",line=marker+theme2.fg(color2,check+text2)+note;return truncateToWidth(line,opts.width)}function renderInfoLine(theme2,text2,width){return truncateToWidth(theme2.fg("dim",text2),width)}function windowLines(theme2,lines,height,scroll,indicator){let top=Math.max(0,Math.min(scroll?.top??0,lines.length)),bottom=Math.max(0,Math.min(scroll?.bottom??0,lines.length-top)),head=lines.slice(0,top),tail2=bottom>0?lines.slice(lines.length-bottom):[],middle=lines.slice(top,lines.length-bottom),cursor=Math.max(0,Math.min((scroll?.cursor??0)-top,Math.max(0,middle.length-1))),padToHeight=rows=>{let out=rows.slice(0,height);for(;out.length<height;)out.push("");return out},avail=height-head.length-tail2.length;if(middle.length<=avail)return padToHeight([...head,...middle,...tail2]);let slots=Math.max(1,avail-1),start=Math.max(0,Math.min(cursor-Math.floor(slots/2),middle.length-slots)),note=indicator?.(cursor+1,middle.length)??theme2.fg("dim",` (${cursor+1}/${middle.length})`);return padToHeight([...head,...middle.slice(start,start+slots),note,...tail2])}function isPrintableInput(data){if(!data)return!1;if(data.startsWith(PASTE_START)||decodeKittyPrintable(data)!==void 0)return!0;if(data.includes("\x1B")||data.includes("\r")||data.includes(`
|
|
2046
|
+
`;await writeFile3(tempPath,candidate,{encoding:"utf8",mode:384});let validationError=(await ModelConfig.load(tempPath)).getError();if(validationError)return{kind:"invalid",error:validationError};let latest=await readDocument(this.path);if(latest.exists!==disk.exists||latest.rawText!==disk.rawText)throw new Error("models.json changed while saving; the edits were kept for retry.");return!this.backedUp&&disk.exists&&disk.rawText!==void 0&&(await writeFile3(`${this.path}.bak`,disk.rawText,{encoding:"utf8",mode:384}),this.backedUp=!0),assertLock(),await rename(tempPath,this.path),this.baseline=working,settle(),{kind:"saved",applied:batch.length}}finally{await rm(tempPath,{force:!0}).catch(()=>{})}}};function ensureProvider(doc,providerId){let existing=Object.hasOwn(doc.providers,providerId)?doc.providers[providerId]:void 0;if(existing)return existing;let created={};return Object.defineProperty(doc.providers,providerId,{value:created,writable:!0,enumerable:!0,configurable:!0}),created}function applyOp(doc,op){switch(op.kind){case"set":{let provider=ensureProvider(doc,op.providerId);if(op.modelId===void 0){setPath(provider,op.path,op.value);return}let model=(Array.isArray(provider.models)?provider.models:[]).find(entry=>entry.id===op.modelId);model&&setPath(model,op.path,op.value);return}case"addModel":{let provider=ensureProvider(doc,op.providerId),models=Array.isArray(provider.models)?provider.models:[],index3=models.findIndex(entry=>entry.id===op.model.id),clone=structuredClone(op.model);index3>=0?models[index3]=clone:models.push(clone),provider.models=models;return}case"removeModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!provider||!models)return;provider.models=models.filter(entry=>entry.id!==op.modelId);return}case"renameModel":{let provider=doc.providers[op.providerId],models=Array.isArray(provider?.models)?provider.models:void 0;if(!models)return;let model=models.find(entry=>entry.id===op.oldId);model&&!models.some(entry=>entry.id===op.newId)&&(model.id=op.newId);return}case"removeProvider":{delete doc.providers[op.providerId];return}}}function pruneEmptyNewProviders(working,disk){for(let[providerId,provider]of Object.entries(working.providers))Object.hasOwn(disk.providers,providerId)||isPlainObject2(provider)&&Object.keys(provider).length===0&&delete working.providers[providerId]}var RefreshCoordinator=class{constructor(runtime){this.pending=new Map,this.changed=new Set,this.revision=0,this.runtime=runtime}touch(providerId){this.pending.set(providerId,++this.revision),this.changed.add(providerId)}get touchedProviders(){return[...this.changed]}async refreshNow(providerId,signal){return this.run([providerId],signal)}async flush(signal){let providers=[...this.pending.keys()];return providers.length===0?{ok:!0,aborted:!1,errors:[]}:this.run(providers,signal)}async run(providers,signal){let revisions=new Map(providers.map(id=>[id,this.pending.get(id)])),combined=AbortSignal.any([...signal?[signal]:[],AbortSignal.timeout(REFRESH_TIMEOUT_MS)]),errors=[];try{let result2=await this.runtime.refresh({allowNetwork:!1,providers,signal:combined});for(let[providerId,error]of result2.errors)errors.push(`${providerId}: ${formatError2(error)}`);let configError=this.runtime.getError();configError&&errors.push(configError);let aborted=result2.aborted||combined.aborted;aborted&&errors.length===0&&errors.push("Refresh was cancelled or timed out.");let ok=errors.length===0&&!aborted;if(ok)for(let id of providers)this.pending.get(id)===revisions.get(id)&&this.pending.delete(id);return{ok,aborted,errors}}catch(error){return errors.push(formatError2(error)),{ok:!1,aborted:combined.aborted,errors}}}};async function probeProviderModels(opts){let baseUrl;try{baseUrl=new URL(opts.baseUrl)}catch{return{ok:!1,error:"Base URL is not a valid URL."}}if(baseUrl.protocol!=="http:"&&baseUrl.protocol!=="https:")return{ok:!1,error:`Unsupported protocol: ${baseUrl.protocol}`};if(baseUrl.username||baseUrl.password||baseUrl.hash)return{ok:!1,error:"Base URL must not contain credentials or a fragment."};if(opts.signal?.aborted)return{ok:!1,error:"Cancelled."};let controller=new AbortController,timeoutMs=opts.timeoutMs??PROBE_LIMITS.timeoutMs,timer=setTimeout(()=>controller.abort(),timeoutMs),onOuterAbort=()=>controller.abort();opts.signal?.addEventListener("abort",onOuterAbort,{once:!0});let doFetch=opts.fetch??globalThis.fetch,getPage=async(url,headers)=>{let response=await doFetch(url,{method:"GET",headers,signal:controller.signal});if(!response.ok){let body2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxErrorBytes,signal:controller.signal});return{ok:!1,status:response.status,error:`HTTP ${response.status}${body2?`: ${safeErrorText(body2,opts.auth).slice(0,PROBE_LIMITS.maxErrorChars)}`:""}`}}let text2=await readResponseTextBounded(response,{maxBytes:PROBE_LIMITS.maxBodyBytes,overflowMessage:`Response exceeds ${PROBE_LIMITS.maxBodyBytes} bytes.`,signal:controller.signal});try{return{ok:!0,json:JSON.parse(text2)}}catch{return{ok:!1,error:"Model catalog response is not JSON."}}};try{let url=modelCatalogUrl(baseUrl,opts.api),headers=buildHeaders(opts.auth,opts.api),page=await getPage(url,headers),retry=page.ok?void 0:openAIStyleRetry(baseUrl,opts.auth,opts.api,{url,headers,status:page.status});if(!page.ok&&retry){let retried=await getPage(retry.url,retry.headers);if(!retried.ok)return{ok:!1,error:safeErrorText(`${url.href} \u2192 HTTP ${page.status}; OpenAI-style retry ${retry.url.href} \u2192 ${retried.error}`,opts.auth)};({url,headers}=retry),page=retried}if(!page.ok)return{ok:!1,error:page.error};let models=parseCatalogModels(page.json);if(models===null)return{ok:!1,error:"JSON has no supported OpenAI-style data[] or models[] catalog with model ids. Add models manually if this endpoint uses another catalog format."};let json=page.json;for(let pages=1;opts.api==="anthropic-messages"&&pages<PROBE_LIMITS.maxPages&&models.length<PROBE_LIMITS.maxModels;pages++){let cursor=nextPageCursor(json);if(!cursor)break;let nextUrl=new URL(url.href);nextUrl.searchParams.set("after_id",cursor),nextUrl.searchParams.set("limit","1000");let next=await getPage(nextUrl,headers),more=next.ok?parseCatalogModels(next.json):null;if(!next.ok||!more||(models.push(...more),nextPageCursor(next.json)===cursor))break;json=next.json}let sorted=dedupeSort(models),truncated=sorted.length>PROBE_LIMITS.maxModels||declaresMorePages(json);return{ok:!0,models:sorted.slice(0,PROBE_LIMITS.maxModels),truncated}}catch(error){return controller.signal.aborted?{ok:!1,error:opts.signal?.aborted?"Cancelled.":`Timed out after ${timeoutMs}ms.`}:{ok:!1,error:safeErrorText(formatError2(error),opts.auth)}}finally{clearTimeout(timer),opts.signal?.removeEventListener("abort",onOuterAbort)}}function modelCatalogUrl(base,api){let url=new URL(base.href),path14=url.pathname.replace(/\/+$/,"");return url.pathname=api==="anthropic-messages"&&!path14.endsWith("/v1")?`${path14}/v1/models`:`${path14}/models`,url}function openAIStyleRetry(base,auth,api,first){if(api!=="anthropic-messages"||![401,403,404].includes(first.status??0)||Object.keys(auth?.headers??{}).some(key=>key.toLowerCase()==="authorization"))return;let root=new URL(base.href);root.pathname=root.pathname.replace(/\/+$/,"").replace(/\/anthropic$/i,"");let url=modelCatalogUrl(root,api),headers=buildHeaders(auth,void 0);return url.href===first.url.href&&headers.get("authorization")===first.headers.get("authorization")?void 0:{url,headers}}function safeErrorText(text2,auth){for(let value of[auth?.apiKey,...Object.values(auth?.headers??{})]){if(typeof value!="string"||!value)continue;text2=text2.replaceAll(value,"[redacted]");let token=value.replace(/^Bearer\s+/i,"");token!==value&&token&&(text2=text2.replaceAll(token,"[redacted]"))}return stripTerminalSequences(text2)}function buildHeaders(auth,api){let headers=new Headers;headers.set("accept","application/json");let configured=auth?.headers??{};api==="anthropic-messages"&&headers.set("anthropic-version","2023-06-01");let hasAuthorization=!1;for(let[key,value]of Object.entries(configured))key.toLowerCase()==="authorization"&&(hasAuthorization=!0),typeof value=="string"?headers.set(key,value):value===null&&headers.delete(key);if(!auth?.apiKey||hasAuthorization)return headers;let lower=name=>Object.keys(configured).some(key=>key.toLowerCase()===name);return api==="anthropic-messages"?(auth.apiKey.includes("sk-ant-oat")?headers.set("authorization",`Bearer ${auth.apiKey}`):(lower("x-api-key")||headers.set("x-api-key",auth.apiKey),lower("anthropic-version")||headers.set("anthropic-version","2023-06-01")),headers):api==="google-generative-ai"||api==="google-vertex"?(lower("x-goog-api-key")||headers.set("x-goog-api-key",auth.apiKey),headers):(headers.set("authorization",`Bearer ${auth.apiKey}`),headers)}function declaresMorePages(json){return typeof json=="object"&&json!==null&&"has_more"in json&&json.has_more===!0}function nextPageCursor(json){if(!declaresMorePages(json))return;let lastId=json.last_id;return typeof lastId=="string"&&lastId?lastId:void 0}var CONTEXT_WINDOW_FIELDS=["context_window","context_window.tokens","context_length","top_provider.context_length","max_input_tokens","max_context_length","max_model_len","context_size","metadata.context_length"],MAX_TOKENS_FIELDS=["max_output_tokens","max_completion_tokens","top_provider.max_completion_tokens","max_tokens","max_output_length"],INPUT_MODALITY_FIELDS=["input_modalities","architecture.input_modalities","modalities.input"],IMAGE_FLAG_FIELDS=["supports_vision","enable_vision_input","capabilities.vision","capabilities.image_input.supported"],REASONING_FLAG_FIELDS=["reasoning","supports_reasoning","enable_reason","capabilities.reasoning","capabilities.thinking.supported"],REASONING_LEVEL_FIELDS=["effort.supported_levels","reasoning_effort_support_list"],CAPABILITY_LIST_FIELDS=["supported_parameters","tags","features","supported_features","metadata.tags"];function fieldAt(record,path14){let value=record;for(let key of path14.split(".")){if(!value||typeof value!="object"||Array.isArray(value))return;value=value[key]}return value}function listAt(record,path14){let value=fieldAt(record,path14);return Array.isArray(value)?value.filter(entry=>typeof entry=="string").map(entry=>entry.toLowerCase()):[]}function declaredLimit(record,paths){let limit;for(let path14 of paths){let value=fieldAt(record,path14);typeof value=="number"&&Number.isSafeInteger(value)&&value>0&&(limit=Math.min(limit??value,value))}return limit}function declaresImageInput(record){return INPUT_MODALITY_FIELDS.some(path14=>listAt(record,path14).includes("image"))||IMAGE_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("vision"))}function declaresReasoning(record){return REASONING_FLAG_FIELDS.some(path14=>fieldAt(record,path14)===!0)||REASONING_LEVEL_FIELDS.some(path14=>listAt(record,path14).length>0)||CAPABILITY_LIST_FIELDS.some(path14=>listAt(record,path14).includes("reasoning"))}function parseCatalogModels(json){if(!json||typeof json!="object")return null;let payload=json,data=Array.isArray(json)?json:Array.isArray(payload.models)?payload.models:payload.data;if(!Array.isArray(data))return null;let models=[];for(let item of data){if(!item||typeof item!="object")continue;let record=item,id=(typeof record.id=="string"?record.id.trim():"")||(typeof record.slug=="string"?record.slug.trim():"");if(!id)continue;let displayName=typeof record.name=="string"&&record.name.trim()?record.name.trim():void 0,anthropicName=typeof record.display_name=="string"&&record.display_name.trim()?record.display_name.trim():typeof record.displayName=="string"?record.displayName.trim():void 0,name=(displayName??anthropicName)!==id?displayName??anthropicName:void 0,model=name?{id,name}:{id},contextWindow=declaredLimit(record,CONTEXT_WINDOW_FIELDS);contextWindow&&(model.contextWindow=contextWindow);let maxTokens=declaredLimit(record,MAX_TOKENS_FIELDS);maxTokens&&(model.maxTokens=maxTokens),declaresImageInput(record)&&(model.input=["text","image"]),declaresReasoning(record)&&(model.reasoning=!0),models.push(model)}return data.length>0&&models.length===0?null:models}function dedupeSort(models){let map=new Map;for(let model of models)map.has(model.id)||map.set(model.id,model);return[...map.values()].sort((a,b2)=>a.id.localeCompare(b2.id))}async function fetchProviderModels(options,signal){let{store,refresher,runtime,providerId}=options,deadline=AbortSignal.any([signal,AbortSignal.timeout(PROBE_LIMITS.timeoutMs)]);try{await raceWithAbortSignal(store.flush(),deadline);let unsaved=store.getPendingError(providerId);if(unsaved)return{ok:!1,error:`Save the provider changes before fetching: ${unsaved}`};let provider=store.getProvider(providerId),settings2=effectiveModelSettings(providerId,provider);if(!settings2.baseUrl)return{ok:!1,error:"Set a baseUrl under API Auth first."};let sync=await refresher.refreshNow(providerId,deadline);if(deadline.throwIfAborted(),!sync.ok)return{ok:!1,error:`The provider did not reload: ${sync.errors.join("; ")}`};let resolved=await raceWithAbortSignal(runtime.getAuth(providerId,{signal:deadline}),deadline),configured=provider?.apiKey!==void 0||provider?.authHeader===!0||Object.keys(provider?.headers??{}).length>0||runtime.getProviderAuthStatus(providerId).configured;if(!resolved&&configured)return{ok:!1,error:"Configured credentials or headers did not resolve; check the provider authentication."};let result2=await probeProviderModels({baseUrl:resolved?.auth.baseUrl??settings2.baseUrl,auth:resolved?.auth,api:settings2.api,signal:deadline});return deadline.throwIfAborted(),result2}catch(error){return deadline.aborted?{ok:!1,error:signal.aborted?"Cancelled.":"Timed out while preparing or fetching the model catalog."}:{ok:!1,error:formatError2(error)}}}async function importProviderModels(options,models,signal){let{store,refresher,providerId}=options;await raceWithAbortSignal(store.flush(),signal);let unsaved=store.getPendingError(providerId);if(unsaved)return unsaved;let settings2=effectiveModelSettings(providerId,store.getProvider(providerId));if(!settings2.api||!settings2.baseUrl)return"Set baseUrl and API Type under API Auth before importing models.";let existing=new Set(store.getModels(providerId).map(model=>model.id)),fresh=models.filter(model=>existing.has(model.id)?!1:(existing.add(model.id),!0));if(fresh.length===0)return;signal.throwIfAborted(),options.edits.addModels(fresh),await store.flush();let saveError=store.getPendingError(providerId);if(saveError)return saveError;let outcome=await refresher.refreshNow(providerId,signal);if(!outcome.ok)return`Models were saved, but refresh failed: ${outcome.errors.join("; ")}`}var ProviderEdits=class{constructor(store,providerId,refresher,refresh){this.renaming=!1,this.store=store,this.providerId=providerId,this.refresher=refresher,this.refresh=refresh}changed(){(!this.store.isDraftProvider(this.providerId)||hasProviderSettings(this.store.getProvider(this.providerId)))&&this.refresher.touch(this.providerId),this.refresh()}setProviderField(path14,value){this.store.setProviderField(this.providerId,path14,value),this.changed()}removeProvider(){this.store.removeProvider(this.providerId),this.changed()}removeModel(modelId){this.store.removeModel(this.providerId,modelId),this.changed()}batch(apply){this.store.batch(apply)}addModels(models){this.store.batch(()=>{for(let model of models)this.store.addModel(this.providerId,model)}),models.length>0&&this.changed()}draft(){let fields={};return{isDraft:!0,read:()=>fields,setField:(path14,value)=>{setPath(fields,path14,value),this.refresh()}}}commitDraft(draft){let fields=draft.read(),id=(fields.id??"").trim();if(!id)return"Model id is required.";if(this.store.getModel(this.providerId,id))return`Model "${id}" already exists.`;let settings2=effectiveModelSettings(this.providerId,this.store.getProvider(this.providerId),fields);if(!settings2.api)return"Cannot resolve an api \u2014 set one under Model-Specific API or the provider's API Auth.";if(!settings2.baseUrl)return"Cannot resolve a baseUrl \u2014 set one under Model-Specific API or the provider's API Auth.";this.store.addModel(this.providerId,{...fields,id}),this.changed()}model(modelId,onRename){let id=modelId,snapshot;return{isDraft:!1,read:()=>snapshot??this.store.getModel(this.providerId,id)??{id},setField:(path14,value)=>{this.store.setModelField(this.providerId,id,path14,value),this.changed()},rename:async newId=>{let oldId=id;snapshot=this.store.getModel(this.providerId,id),this.renaming=!0;try{let error=await this.store.renameModel(this.providerId,id,newId);if(error)return error;id=newId,this.changed();return}finally{snapshot=void 0,this.renaming=!1,onRename(oldId,id)}}}}};var CURSOR2="\u203A",PASTE_START="\x1B[200~",PASTE_END="\x1B[201~",ValueEditor=class{constructor(callbacks){this.input=new Input({prompt:""}),this.input.onSubmit=callbacks.onCommit,this.input.onEscape=callbacks.onCancel}beginOverwrite(firstData){this.input.setValue(""),firstData&&this.input.handleInput(firstData)}reset(value){this.beginTweak(value)}beginTweak(current){this.input.setValue(""),this.input.handleInput(PASTE_START+current+PASTE_END),this.input.setValue(current)}get value(){return this.input.getValue()}handleInput(data){this.input.handleInput(data)}renderLine(width){return this.input.render(Math.max(1,width))[0]??""}get focused(){return this.input.focused}set focused(value){this.input.focused=value}};function renderKeyValueLine(theme2,opts){let lit=opts.active&&opts.paneFocused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",keyPrefix=opts.keyLabel===void 0?"":`${opts.keyLabel}: `,keyColor=lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"";if(opts.editing){let body2=opts.editing.renderLine(Math.max(1,opts.width-visibleWidth(marker)-visibleWidth(keyPrefix)));return truncateToWidth(marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(keyColor,body2)+note,opts.width)}let valueColor=opts.unset?"dim":keyColor,line=marker+theme2.fg(keyColor,keyPrefix)+theme2.fg(valueColor,opts.valueText??"")+note;return truncateToWidth(line,opts.width)}function renderPlainLine(theme2,text2,opts){let lit=(opts.active??!1)&&(opts.paneFocused??!1),marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",check=opts.checked===void 0?"":opts.checked?"[x] ":"[ ] ",color2=opts.dim?"dim":lit?"accent":"text",note=opts.note?theme2.fg("dim",` ${opts.note}`):"",line=marker+theme2.fg(color2,check+text2)+note;return truncateToWidth(line,opts.width)}function renderInfoLine(theme2,text2,width){return truncateToWidth(theme2.fg("dim",text2),width)}function windowLines(theme2,lines,height,scroll,indicator){let top=Math.max(0,Math.min(scroll?.top??0,lines.length)),bottom=Math.max(0,Math.min(scroll?.bottom??0,lines.length-top)),head=lines.slice(0,top),tail2=bottom>0?lines.slice(lines.length-bottom):[],middle=lines.slice(top,lines.length-bottom),cursor=Math.max(0,Math.min((scroll?.cursor??0)-top,Math.max(0,middle.length-1))),padToHeight=rows=>{let out=rows.slice(0,height);for(;out.length<height;)out.push("");return out},avail=height-head.length-tail2.length;if(middle.length<=avail)return padToHeight([...head,...middle,...tail2]);let slots=Math.max(1,avail-1),start=Math.max(0,Math.min(cursor-Math.floor(slots/2),middle.length-slots)),note=indicator?.(cursor+1,middle.length)??theme2.fg("dim",` (${cursor+1}/${middle.length})`);return padToHeight([...head,...middle.slice(start,start+slots),note,...tail2])}function isPrintableInput(data){if(!data)return!1;if(data.startsWith(PASTE_START)||decodeKittyPrintable(data)!==void 0)return!0;if(data.includes("\x1B")||data.includes("\r")||data.includes(`
|
|
2068
2047
|
`))return!1;for(let char of data){let code=char.codePointAt(0);if(code<32||code===127)return!1}return!0}function truncateMiddle2(text2,maxWidth){if(visibleWidth(text2)<=maxWidth)return text2;if(maxWidth<=4)return truncateToWidth(text2,maxWidth);let headWidth=Math.ceil((maxWidth-1)/2),tailWidth=maxWidth-1-headWidth,head="",headUsed=0;for(let char of text2){let charWidth=visibleWidth(char);if(headUsed+charWidth>headWidth)break;head+=char,headUsed+=charWidth}let tail2="",tailUsed=0;for(let char of[...text2].reverse()){let charWidth=visibleWidth(char);if(tailUsed+charWidth>tailWidth)break;tail2=char+tail2,tailUsed+=charWidth}return`${head}\u2026${tail2}`}var InfoPane=class{constructor(host,lines,onConfirm){this.focused=!1,this.host=host,this.lines=lines,this.onConfirm=onConfirm}render(width){return this.focused&&this.onConfirm?this.lines.map((line,index3)=>index3>0?renderInfoLine(this.host.theme,line,width):truncateToWidth(this.host.theme.fg("accent",`${CURSOR2} `)+this.host.theme.fg("text",line),width)):this.lines.map(line=>renderInfoLine(this.host.theme,line,width))}handleInput(data){if(this.host.keybindings.matches(data,"tui.select.cancel")){this.host.popPane();return}this.onConfirm&&this.host.keybindings.matches(data,"tui.select.confirm")&&this.onConfirm()}setFocused(focused){this.focused=focused}hints(){let hints=[];return this.onConfirm&&hints.push(keyHint("tui.select.confirm","proceed")),hints.push(keyHint("tui.select.cancel","back")),hints.join(" ")}},ConfirmPane=class{constructor(host,message,actionLabel,action){this.crumb="Confirm",this.index=1,this.focused=!1,this.host=host,this.message=message,this.actionLabel=actionLabel,this.action=action}render(width){let theme2=this.host.theme;return[truncateToWidth(theme2.fg("warning",this.message),width),renderPlainLine(theme2,this.actionLabel,{active:this.index===0,paneFocused:this.focused,width}),renderPlainLine(theme2,"Cancel",{active:this.index===1,paneFocused:this.focused,width})]}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down")){this.index=this.index===0?1:0,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}kb.matches(data,"tui.select.confirm")&&(this.index===0?this.action():this.host.popPane())}setFocused(focused){this.focused=focused}hints(){return[keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}};function moveSelection(keys,data,index3,count){let delta=keys.matches(data,"tui.select.up")?-1:keys.matches(data,"tui.select.down")?1:void 0;return delta===void 0?void 0:count===0?0:(index3+delta+count)%count}var ChoicePane=class{constructor(host,crumb,options){this.focused=!1,this.host=host,this.crumb=crumb,this.options=options,this.index=Math.max(0,options.choices().findIndex(choice=>choice.value===options.current()))}render(width){let lines=this.options.choices().map((choice,index3)=>renderPlainLine(this.host.theme,`${choice.value===this.options.current()?"\u25CF":"\u25CB"} ${choice.label}`,{active:index3===this.index,paneFocused:this.focused,dim:choice.dim,width}));return this.error&&lines.push(renderInfoLine(this.host.theme,this.error,width)),lines}scrollWindow(){return{cursor:this.index,bottom:this.error?1:0}}handleInput(data){let choices=this.options.choices(),next=moveSelection(this.host.keybindings,data,this.index,choices.length);if(next!==void 0)this.index=next,this.host.refresh();else if(this.host.keybindings.matches(data,"tui.select.cancel"))this.host.popPane();else if(this.host.keybindings.matches(data,"tui.select.confirm")||this.host.keybindings.matches(data,"app.list.toggle")){let choice=choices[this.index];if(!choice)return;this.error=this.options.choose(choice.value),this.error?this.host.refresh():this.host.popPane()}}setFocused(focused){this.focused=focused}hints(){return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","select"),keyHint("tui.select.cancel","back")].join(" ")}},InlineEdit=class{constructor(refresh){this.refresh=refresh}get editing(){return this.active!==void 0}editor(key){return this.active?.key===key?this.active.editor:void 0}setFocused(focused){this.active&&(this.active.editor.focused=focused)}begin(key,current,mode,focused,commit,firstData){let editor=new ValueEditor({onCommit:value=>{this.error=commit(value),this.error||(this.active=void 0),this.refresh()},onCancel:()=>{this.active=void 0,this.error=void 0,this.refresh()}});this.active={key,editor},editor.focused=focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current),this.refresh()}handleInput(data,keys){return this.active?(!keys.matches(data,"tui.select.up")&&!keys.matches(data,"tui.select.down")&&this.active.editor.handleInput(data),this.refresh(),!0):!1}};function formatTokens3(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function metadataNote(model){let parts=[model.contextWindow?`${formatTokens3(model.contextWindow)} ctx`:"",model.maxTokens?`${formatTokens3(model.maxTokens)} out`:"",model.input?.includes("image")?"img":"",model.reasoning?"think":""].filter(Boolean);return parts.length>0?`\xB7 ${parts.join(" \xB7 ")}`:void 0}var FetchModelsPane=class{constructor(host){this.state={type:"idle"},this.query="",this.index=0,this.checked=new Set,this.focused=!1,this.disposed=!1,this.host=host,this.search=new ValueEditor({onCommit:()=>this.importChecked(),onCancel:()=>this.exitResults()})}start(){if(this.disposed||this.state.type==="loading"||this.state.type==="importing"||!this.catalogUrl())return;let controller=new AbortController;this.state={type:"loading",controller},this.host.refresh(),this.host.runFetch(controller.signal).then(result2=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller)){if(result2.ok)this.state={type:"results",catalog:result2},this.checked=new Set,this.query="",this.search.reset(""),this.index=0,this.search.focused=this.focused,this.host.setFetchStatus(`\xB7 ${result2.models.length} models`);else{if(result2.error==="Cancelled.")return;this.state={type:"error",message:result2.error},this.host.setFetchStatus("\xB7 failed")}this.host.refresh()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="loading"||this.state.controller!==controller||(this.state={type:"error",message:error instanceof Error?error.message:String(error)},this.host.setFetchStatus("\xB7 failed"),this.host.refresh())})}existingIds(){return new Set(this.host.store.getModels(this.host.providerId).map(model=>model.id))}catalogUrl(){let baseUrl=this.host.store.getProvider(this.host.providerId)?.baseUrl;try{return baseUrl?modelCatalogUrl(new URL(baseUrl),this.host.effectiveApi()).href:void 0}catch{return}}rows(){if(this.state.type!=="results"&&this.state.type!=="importing")return[];let existing=this.existingIds(),rows=this.state.catalog.models.map(model=>({model,added:existing.has(model.id)})),query=this.query.trim().toLowerCase();return query?rows.filter(row=>row.model.id.toLowerCase().includes(query)||row.model.name?.toLowerCase().includes(query)):rows}render(width){let theme2=this.host.theme,catalogUrl=this.catalogUrl();switch(this.state.type){case"idle":return catalogUrl?[renderPlainLine(theme2,"Fetch Models",{active:!0,paneFocused:this.focused,note:`\xB7 from ${truncateMiddle2(catalogUrl,Math.max(10,width-22))}`,width})]:[renderInfoLine(theme2,"Set a baseUrl under API Auth first.",width)];case"loading":return[renderInfoLine(theme2,`Fetching ${catalogUrl??""} \u2026`,width),renderInfoLine(theme2,"Esc cancels the request.",width)];case"error":return[theme2.fg("error",truncate3(this.state.message,Math.max(10,width-2))),renderInfoLine(theme2,"Enter retries; Esc goes back.",width)];case"importing":case"results":{let lines=[];this.state.catalog.truncated&&lines.push(renderInfoLine(theme2,"The catalog was truncated; refine manually if a model is missing.",width)),lines.push(this.search.renderLine(width));let rows=this.rows();for(let[rowIndex,row]of rows.entries()){if(row.added){lines.push(renderPlainLine(theme2,row.model.id,{active:rowIndex===this.index,paneFocused:this.focused,dim:!0,note:"\xB7 Added",width}));continue}lines.push(renderPlainLine(theme2,row.model.name?`${row.model.id} \xB7 ${row.model.name}`:row.model.id,{checked:this.checked.has(row.model.id),active:rowIndex===this.index,paneFocused:this.focused,note:metadataNote(row.model),width}))}rows.length===0&&lines.push(renderInfoLine(theme2,"No matching models.",width));let addedCount=rows.filter(row=>row.added).length;return lines.push(renderInfoLine(theme2,`${this.checked.size} selected \xB7 ${rows.length} shown${addedCount?` \xB7 ${addedCount} already added`:""}`,width)),this.state.type==="importing"&&lines.push(renderInfoLine(theme2,"Importing\u2026",width)),this.state.type==="results"&&this.state.error&&lines.push(theme2.fg("error",truncate3(this.state.error,Math.max(10,width-2)))),lines}}}scrollWindow(){if(this.state.type!=="results"&&this.state.type!=="importing")return{};let top=(this.state.catalog.truncated?1:0)+1,bottom=1+(this.state.type==="importing"||this.state.error?1:0);return{top,bottom,cursor:top+this.index}}handleInput(data){let kb=this.host.keybindings;switch(this.state.type){case"idle":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"loading":if(kb.matches(data,"tui.select.cancel")){this.state.controller.abort(),this.state={type:"idle"},this.host.refresh();return}return;case"error":if(kb.matches(data,"tui.select.confirm")){this.start();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}return;case"importing":case"results":this.handleResultsInput(data);return}}handleResultsInput(data){let kb=this.host.keybindings,rows=this.rows(),next=moveSelection(kb,data,this.index,rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let row=rows[this.index];if(!row||row.added||this.state.type==="importing")return;this.checked.has(row.model.id)?this.checked.delete(row.model.id):this.checked.add(row.model.id),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.exitResults();return}if(kb.matches(data,"tui.select.confirm")){this.importChecked();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}importChecked(){if(this.state.type!=="results")return;let chosen;if(this.checked.size===0){let row=this.rows()[this.index];if(!row||row.added)return;chosen=[row.model]}else chosen=this.state.catalog.models.filter(model=>this.checked.has(model.id));let controller=new AbortController,catalog=this.state.catalog;this.state={type:"importing",catalog,controller},this.host.refresh(),this.host.importModels(chosen,controller.signal).then(error=>{if(!(this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller)){if(error)return this.state={type:"results",catalog,error},this.host.setFetchStatus("\xB7 import failed"),this.host.refresh();this.host.setFetchStatus(`\xB7 ${this.host.store.getModels(this.host.providerId).length} models`),this.state={type:"idle"},this.host.popPane()}}).catch(error=>{this.disposed||controller.signal.aborted||this.state.type!=="importing"||this.state.controller!==controller||(this.state={type:"results",catalog,error:error instanceof Error?error.message:String(error)},this.host.refresh())})}exitResults(){(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort(),this.state={type:"idle"},this.checked=new Set,this.host.popPane()}setFocused(focused){this.focused=focused,this.search.focused=focused&&(this.state.type==="results"||this.state.type==="importing")}isEditing(){return this.state.type==="results"||this.state.type==="importing"}dispose(){this.disposed=!0,(this.state.type==="loading"||this.state.type==="importing")&&this.state.controller.abort()}hints(){switch(this.state.type){case"loading":return keyHint("tui.select.cancel","cancel request");case"importing":case"results":return[rawKeyHint("type","filter"),keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","import"),keyHint("tui.select.cancel","discard")].join(" ");case"error":return[keyHint("tui.select.confirm","retry"),keyHint("tui.select.cancel","back")].join(" ");default:return this.catalogUrl()?[keyHint("tui.select.confirm","fetch"),keyHint("tui.select.cancel","back")].join(" "):keyHint("tui.select.cancel","back")}}};function formatContext(model){let ctx=model.contextWindow>=1e3?`${Math.round(model.contextWindow/1024)}k`:String(model.contextWindow);return`${model.api} \xB7 ${ctx} ctx${model.reasoning?" \xB7 reasoning":""}`}var BuiltinCandidatesPane=class{constructor(host,model){this.crumb="Use Built-in Data",this.index=0,this.focused=!1,this.host=host,this.model=model,this.query=this.model.read().id??"",this.search=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()}),this.search.reset(this.query)}candidates(){return matchBuiltinModels(this.query,this.host.effectiveApi(this.model.read()))}render(width){let theme2=this.host.theme,lines=[this.search.renderLine(width)],matches=this.candidates();matches.length===0&&lines.push(renderInfoLine(theme2,"No builtin candidates \u2014 keep configuring manually.",width));for(let[rowIndex,match2]of matches.entries()){let{providerId,model}=match2.entry,label=`${providerId} / ${model.id}`,note=(match2.tier==="exact"?"exact \xB7 ":"")+`${model.name!==model.id?`${model.name} \xB7 `:""}${formatContext(model)}`;lines.push(renderPlainLine(theme2,label,{active:rowIndex===this.index,paneFocused:this.focused,note,width}))}return lines.push(renderInfoLine(theme2,"Candidates are a reference only; the configured id is never rewritten.",width)),lines}scrollWindow(){return{top:1,bottom:1,cursor:1+this.index}}pickCurrent(){let entry=this.candidates()[this.index]?.entry;entry&&this.host.pushPane(new BuiltinPreviewPane(this.host,this.model,entry))}handleInput(data){let kb=this.host.keybindings,count=this.candidates().length,next=moveSelection(kb,data,this.index,count);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.search.handleInput(data),this.query=this.search.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.search.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","preview"),keyHint("tui.select.cancel","back")].join(" ")}},BuiltinPreviewPane=class{constructor(host,model,reference){this.crumb="Use Built-in Data \xB7 preview",this.index=0,this.focused=!1,this.host=host,this.model=model,this.reference=reference;let current=model.read();this.snapshot=structuredClone(current),this.snapshotApi=host.effectiveApi(current),this.changes=computeFieldChanges(current,reference.model,host.effectiveApi(current)),this.checked=this.changes.map(change=>change.checked&&change.applicable)}rowCount(){return this.changes.length+1}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,`reference: ${this.reference.providerId} / ${this.reference.model.id}`,width)];for(let[rowIndex,change]of this.changes.entries()){let active=rowIndex===this.index,expandable=change.referenceDetails!==void 0,note=change.applicable?void 0:"\xB7 view only";if(lines.push(renderPlainLine(theme2,`${change.field}: ${change.currentText} \u2192 ${change.referenceText}`,{checked:change.applicable?this.checked[rowIndex]:void 0,active,paneFocused:this.focused,note,width})),this.expanded===rowIndex&&expandable){for(let detail of change.referenceDetails)lines.push(renderInfoLine(theme2,` ${detail}`,width));change.referenceHasTiers&&lines.push(renderInfoLine(theme2," reference has cost tiers \u2014 tiers are never imported.",width))}}return lines.push(renderPlainLine(theme2,"Apply Selected Fields",{active:this.index===this.changes.length,paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){let cursor=1+this.index;if(this.expanded!==void 0&&this.expanded<this.index){let change=this.changes[this.expanded];change.referenceDetails&&(cursor+=change.referenceDetails.length+(change.referenceHasTiers?1:0))}return{top:1,bottom:this.error?1:0,cursor}}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.list.toggle")){let change=this.changes[this.index];if(!change)return;if(!change.applicable){this.expanded=this.expanded===this.index?void 0:this.index,this.host.refresh();return}this.checked[this.index]=!this.checked[this.index],this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){if(this.index===this.changes.length){this.apply();return}let change=this.changes[this.index];change.referenceDetails?this.expanded=this.expanded===this.index?void 0:this.index:change.applicable&&(this.checked[this.index]=!this.checked[this.index]),this.host.refresh();return}}apply(){let current=this.model.read();if(this.host.effectiveApi(current)!==this.snapshotApi){this.error="The API changed since this preview opened; reopen to continue.",this.host.refresh();return}if(!current.id||!jsonEquals(current,this.snapshot)){this.error="The model changed since this preview opened; reopen to continue.",this.host.refresh();return}let chosen=this.changes.filter((_2,rowIndex)=>this.checked[rowIndex]&&this.changes[rowIndex].applicable);if(chosen.length===0){this.host.popPane();return}this.host.edits.batch(()=>{for(let change of chosen)for(let patch of change.patches)this.model.setField(patch.path,patch.value)}),this.host.notify(`Applied ${chosen.length} field${chosen.length===1?"":"s"} from ${this.reference.providerId} / ${this.reference.model.id}.`,"info"),this.host.popPane(),this.host.popPane()}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","check"),keyHint("tui.select.confirm","details / apply"),keyHint("tui.select.cancel","back")].join(" ")}};var THINKING_VARIABLES=["thinking.enabled","thinking.effort","thinking.budget"],SESSION_AFFINITY=["openai","openai-nosession","openrouter"],OPENAI_COMPLETIONS_FIELDS=[{key:"supportsStore",kind:"boolean",note:"Accepts the `store` parameter"},{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"supportsReasoningEffort",kind:"boolean",note:"Accepts `reasoning_effort`"},{key:"supportsUsageInStreaming",kind:"boolean",note:"Streams usage chunks"},{key:"supportsFinishReason",kind:"boolean",note:"Reports finish reasons"},{key:"maxTokensField",kind:"enum",options:["max_completion_tokens","max_tokens"],note:"Token limit field name"},{key:"requiresToolResultName",kind:"boolean",note:"Tool results need a `name`"},{key:"requiresAssistantAfterToolResult",kind:"boolean",note:"Needs assistant message after tool results"},{key:"requiresThinkingAsText",kind:"boolean",note:"Thinking must be plain text"},{key:"requiresReasoningContentOnAssistantMessages",kind:"boolean",note:"Assistant messages must carry reasoning content"},{key:"thinkingFormat",kind:"enum",options:["openai","openrouter","together","baseten","deepseek","zai","qwen","chat-template","qwen-chat-template","string-thinking","ant-ling"],note:"Reasoning payload format"},{key:"chatTemplateKwargs",kind:"stringMap",note:"Extra chat-template kwargs (open dictionary)"},{key:"chatTemplateArgs",kind:"stringMap",note:"Extra chat-template args (open dictionary)"},{key:"cacheControlFormat",kind:"enum",options:["anthropic"],note:"Cache-control payload format"},{key:"openRouterRouting",kind:"json",note:"OpenRouter routing preferences object"},{key:"vercelGatewayRouting",kind:"json",note:"Vercel AI Gateway routing object"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolAdditions",kind:"boolean",note:"System messages can add tools mid-conversation"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"vllmPriority",kind:"number",note:"vLLM scheduling priority"},{key:"zaiToolStream",kind:"boolean",note:"Z.AI streaming tool calls"},{key:"supportsThinkingTokenBudget",kind:"boolean",note:"Enable the thinking-token budget alias"},{key:"thinkingTokenBudgetField",kind:"enum",options:["thinking_token_budget","thinking_budget","thinking_budget_tokens"],note:"Thinking budget field"}],OPENAI_RESPONSES_FIELDS=[{key:"supportsDeveloperRole",kind:"boolean",note:"Accepts `developer` role messages"},{key:"sessionAffinityFormat",kind:"enum",options:SESSION_AFFINITY,note:"Affinity header format"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"},{key:"supportsOpenAIGrammarTools",kind:"boolean",note:"Grammar-constrained tool calls"},{key:"supportsAdditionalTools",kind:"boolean",note:"Accepts additional hosted tools"},{key:"supportsToolSearch",kind:"boolean",note:"Tool search support"},{key:"supportsMaxOutputTokens",kind:"boolean",note:"Accepts `max_output_tokens`"},{key:"supportsExplicitPromptCacheMode",kind:"boolean",note:"Explicit prompt caching"}],ANTHROPIC_MESSAGES_FIELDS=[{key:"supportsEagerToolInputStreaming",kind:"boolean",note:"Streams tool input eagerly"},{key:"supportsLongCacheRetention",kind:"boolean",note:"Long-lived prompt cache retention"},{key:"sendSessionAffinityHeaders",kind:"boolean",note:"Send session affinity headers"},{key:"supportsCacheControlOnTools",kind:"boolean",note:"Cache control on tool definitions"},{key:"supportsTemperature",kind:"boolean",note:"Accepts `temperature`"},{key:"forceAdaptiveThinking",kind:"boolean",note:"Force adaptive thinking mode"},{key:"allowEmptySignature",kind:"boolean",note:"Tolerate empty thinking signatures"},{key:"supportsStrictTools",kind:"boolean",note:"Strict tool schemas"},{key:"supportsMidConvoEffort",kind:"boolean",note:"Effort changes mid-conversation"},{key:"supportsMidConvoSystemMessages",kind:"boolean",note:"Accepts mid-conversation system messages"},{key:"supportsMidConvoToolChanges",kind:"boolean",note:"Accepts mid-conversation tool changes"},{key:"allowedFallbackModels",kind:"json",note:"Server-side refusal fallback models"}],BEDROCK_FIELDS=[{key:"supportsStrictMode",kind:"boolean",note:"Strict tool schemas"}];function compatFieldsForApi(api){switch(api){case"openai-completions":return OPENAI_COMPLETIONS_FIELDS;case"openai-responses":return OPENAI_RESPONSES_FIELDS;case"azure-openai-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsDeveloperRole","supportsStrictMode","supportsOpenAIGrammarTools"].includes(field5.key));case"openai-codex-responses":return OPENAI_RESPONSES_FIELDS.filter(field5=>["supportsStrictMode","supportsOpenAIGrammarTools","supportsAdditionalTools","supportsToolSearch"].includes(field5.key));case"anthropic-messages":return ANTHROPIC_MESSAGES_FIELDS;case"bedrock-converse-stream":return BEDROCK_FIELDS;default:return[]}}function compatFieldFor(api,key){return compatFieldsForApi(api).find(field5=>field5.key===key)}var completionsCompatValidator=Compile(OpenAICompletionsCompatSchema);function validateCompletionsCompat(value){if(!completionsCompatValidator.Check(value))return completionsCompatValidator.Errors(value).slice(0,5).map(error=>{let path14=error.instancePath.replace(/^\//,"").replace(/\//g,"."),required=error.keyword==="required"?error.params.requiredProperties?.[0]:void 0;return`${required?path14?`${path14}.${required}`:required:path14||"root"}: ${error.message}`}).join("; ")}function validateJsonCompatValue(key,text2){let value;try{value=JSON.parse(text2)}catch{return"Value is not valid JSON."}return validateCompletionsCompat({[key]:value})}function validateChatTemplateKwarg(value){if(value!==null&&typeof value=="object"&&!Array.isArray(value)&&!Object.keys(value).every(key=>key==="$var"||key==="omitWhenOff"))return'Only "$var" and "omitWhenOff" are allowed.';let error=validateCompletionsCompat({chatTemplateKwargs:{value}});return error?`Value must be a scalar or valid $var reference: ${error}`:void 0}function compatObject(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var DICT_VALUE_KINDS=["string","number","boolean","null","$var"],VAR_OPTIONS=THINKING_VARIABLES,DictPane=class{constructor(host,model,dictKey){this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model,this.dictKey=dictKey,this.crumb=`compat \xB7 ${dictKey}`}dict(){let value=compatObject(this.model)[this.dictKey];return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:{}}entries(){return Object.entries(this.dict())}render(width){let theme2=this.host.theme,lines=[renderInfoLine(theme2,"free-form keys; values: string \xB7 number \xB7 boolean \xB7 null \xB7 $var",width)];if(this.mode.type!=="list")return lines.push(...this.renderMode(width)),this.error&&lines.push(renderInfoLine(theme2,this.error,width)),lines;let entries=this.entries();for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:scalarText(value),active,paneFocused:this.focused,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type!=="list"?{top:1,bottom:this.error?1:0}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}renderMode(width){let theme2=this.host.theme,mode=this.mode;switch(mode.type){case"keyEdit":return[renderInfoLine(theme2,"new key:",width),mode.editor.renderLine(width)];case"kindPick":return[renderInfoLine(theme2,`${mode.key} \xB7 value kind`,width),...DICT_VALUE_KINDS.map((kind,kindIndex)=>renderPlainLine(theme2,kind,{active:kindIndex===mode.index,paneFocused:this.focused,width}))];case"valueEdit":return[renderInfoLine(theme2,`${mode.key} \xB7 ${mode.kind}`,width),renderKeyValueLine(theme2,{keyLabel:mode.key,active:!0,paneFocused:this.focused,editing:mode.editor,width})];case"boolPick":return[renderInfoLine(theme2,`${mode.key} \xB7 boolean`,width),...["true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"varPick":return[renderInfoLine(theme2,`${mode.key} \xB7 $var`,width),...VAR_OPTIONS.map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];case"omitPick":return[renderInfoLine(theme2,`${mode.key} \xB7 omitWhenOff`,width),...["default","true","false"].map((option,optionIndex)=>renderPlainLine(theme2,option,{active:optionIndex===mode.index,paneFocused:this.focused,width}))];default:return[]}}handleInput(data){let kb=this.host.keybindings,mode=this.mode;switch(mode.type){case"keyEdit":case"valueEdit":if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;mode.editor.handleInput(data),this.host.refresh();return;case"kindPick":this.handlePick(data,mode,DICT_VALUE_KINDS.length,index3=>{let key=mode.key,kind=DICT_VALUE_KINDS[index3];this.startValueForKind(key,kind)});return;case"boolPick":this.handlePick(data,mode,2,index3=>{let key=mode.key;this.mode={type:"list"},this.writeEntry(key,index3===0)});return;case"varPick":this.handlePick(data,mode,VAR_OPTIONS.length,index3=>{let key=mode.key;this.mode={type:"omitPick",key,$var:VAR_OPTIONS[index3],index:0},this.host.refresh()});return;case"omitPick":this.handlePick(data,mode,3,index3=>{this.mode={type:"list"},this.writeEntry(mode.key,index3===0?{$var:mode.$var}:{$var:mode.$var,omitWhenOff:index3===1})});return;case"list":this.handleList(data);return}}handlePick(data,mode,count,choose2){let kb=this.host.keybindings,index3=mode.index;if(kb.matches(data,"tui.select.up")){mode.index=index3===0?count-1:index3-1,this.host.refresh();return}if(kb.matches(data,"tui.select.down")){mode.index=(index3+1)%count,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}kb.matches(data,"tui.select.confirm")&&choose2(index3)}handleList(data){let kb=this.host.keybindings,rowCount=this.entries().length+1,next=moveSelection(kb,data,this.index,rowCount);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;this.model.setField(["compat",this.dictKey,entry[0]],DELETE),this.index=Math.max(0,Math.min(this.index,this.entries().length-1));return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"app.list.toggle")){let entry=this.entries()[this.index];if(!entry){let editor2=new ValueEditor({onCommit:raw=>{let key2=raw.trim();if(!key2)return this.error="Key must be non-empty.",this.host.refresh();if(Object.hasOwn(this.dict(),key2))return this.error=`"${key2}" already exists.`,this.host.refresh();this.error=void 0,this.mode={type:"kindPick",key:key2,index:0},this.host.refresh()},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor2.focused=this.focused,this.mode={type:"keyEdit",editor:editor2},this.host.refresh();return}let[key,value]=entry;if(typeof value=="boolean"){this.writeEntry(key,!value);return}if(value===null)return;if(typeof value=="object"){let record=value;if(record.$var==="thinking.enabled"||record.$var==="thinking.effort"||record.$var==="thinking.budget"){this.mode={type:"omitPick",key,$var:record.$var,index:record.omitWhenOff===void 0?0:record.omitWhenOff?1:2},this.host.refresh();return}return}let kind=typeof value=="number"?"number":"string",editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.beginTweak(String(value)),editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}}startValueForKind(key,kind){switch(kind){case"string":case"number":{let editor=new ValueEditor({onCommit:raw=>this.commitScalar(key,kind,raw),onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});editor.focused=this.focused,this.mode={type:"valueEdit",key,kind,editor},this.host.refresh();return}case"boolean":this.mode={type:"boolPick",key,index:0},this.host.refresh();return;case"null":this.mode={type:"list"},this.writeEntry(key,null);return;case"$var":this.mode={type:"varPick",key,index:0},this.host.refresh();return}}commitScalar(key,kind,raw){let value=raw;if(kind==="number"){let parsed=Number(raw.trim());if(!Number.isFinite(parsed)){this.error=`${key} must be a number.`,this.host.refresh();return}value=parsed}let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.error=void 0,this.mode={type:"list"},this.writeEntry(key,value)}writeEntry(key,value){let invalid2=validateChatTemplateKwarg(value);if(invalid2){this.error=invalid2,this.host.refresh();return}this.model.setField(["compat",this.dictKey,key],value)}setFocused(focused){this.focused=focused,(this.mode.type==="keyEdit"||this.mode.type==="valueEdit")&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="keyEdit"||this.mode.type==="valueEdit"}hints(){switch(this.mode.type){case"keyEdit":case"valueEdit":return[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" ");case"list":return[keyHint("tui.select.confirm","edit / add"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ");default:return[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","cancel")].join(" ")}}};function compatObject2(handle){let compat=handle.read().compat;return typeof compat=="object"&&compat!==null&&!Array.isArray(compat)?compat:{}}function scalarText2(value){return value===null?"null":typeof value=="string"||typeof value=="number"||typeof value=="boolean"?String(value):JSON.stringify(value)??String(value)}var CompatPane=class{constructor(host,model){this.crumb="compat",this.index=0,this.mode={type:"list"},this.focused=!1,this.host=host,this.model=model}entries(){return Object.entries(compatObject2(this.model))}effectiveApi(){return this.host.effectiveApi(this.model.read())}rowCount(){return this.entries().length+1}render(width){let theme2=this.host.theme,api=this.effectiveApi(),lines=[renderInfoLine(theme2,api?`effective api: ${api}`:"effective api: unresolved \u2014 set API Type",width)];if(this.mode.type==="chooseValue"){let mode=this.mode;lines.push(renderKeyValueLine(theme2,{keyLabel:mode.key,valueText:"choose a value",active:!0,paneFocused:this.focused,width}));for(let[index3,option]of mode.options.entries())lines.push(renderPlainLine(theme2,option,{active:index3===mode.index,paneFocused:this.focused,width}));return lines}let known=api?compatFieldsForApi(api):[],entries=this.entries(),editingKey=this.mode.type==="list"?void 0:this.mode.key;editingKey!==void 0&&!entries.some(([key])=>key===editingKey)&&entries.push([editingKey,void 0]),known.length===0&&entries.length===0&&lines.push(renderInfoLine(theme2,`No compat fields are known for ${api??"this api"}.`,width));for(let[rowIndex,[key,value]]of entries.entries()){let active=rowIndex===this.index,field5=api?compatFieldFor(api,key):void 0,editing=this.mode.type==="editValue"&&this.mode.key===key?this.mode.editor:void 0,note=field5?void 0:`\xB7 not used by ${api??"this api"}`;lines.push(renderKeyValueLine(theme2,{keyLabel:key,valueText:value===void 0?"not set":scalarText2(value),active,paneFocused:this.focused,editing,note,width}))}return lines.push(renderPlainLine(theme2,"+ Add Entry",{active:this.index===entries.length&&this.mode.type==="list",paneFocused:this.focused,width})),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}scrollWindow(){return this.mode.type==="chooseValue"?{top:1,cursor:2+this.mode.index}:{top:1,bottom:this.error?1:0,cursor:1+this.index}}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="editValue"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.mode.editor.handleInput(data),this.host.refresh();return}if(this.mode.type==="chooseValue"){let mode=this.mode;if(kb.matches(data,"tui.select.up")){this.mode={...mode,index:mode.index===0?mode.options.length-1:mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...mode,index:(mode.index+1)%mode.options.length},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"list"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let option=mode.options[mode.index];this.mode={type:"list"},this.writeValue(mode.key,this.parseChosen(option))}return}let next=moveSelection(kb,data,this.index,this.rowCount());if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"app.provider.removeEntry")){let entry=this.entries()[this.index];if(!entry)return;let[key]=entry;this.model.setField(["compat",key],DELETE),this.index=Math.min(this.index,this.rowCount()-2<0?0:this.rowCount()-2);return}if(kb.matches(data,"app.list.toggle")||kb.matches(data,"tui.select.confirm")){this.activateRow();return}}activateRow(){let entries=this.entries();if(this.index===entries.length){let api=this.effectiveApi();if(!api){this.fail("Set API Type first \u2014 compat fields depend on the effective api.");return}if(compatFieldsForApi(api).length===0){this.fail(`No compat fields are known for ${api}.`);return}let taken=new Set(entries.map(([key2])=>key2));this.host.pushPane(new CompatKeyPickerPane(this.host,api,taken,key2=>this.beginValueEntry(key2)));return}let[key,value]=entries[this.index],field5=this.effectiveApi()?compatFieldFor(this.effectiveApi(),key):void 0;if(!field5){this.beginJsonEdit(key,value);return}switch(field5.kind){case"boolean":this.writeValue(key,value!==!0);return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,value);return;case"json":this.beginJsonEdit(key,value);return;case"stringMap":this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginValueEntry(key){let api=this.effectiveApi(),field5=compatFieldFor(api,key);switch(field5.kind){case"boolean":this.mode={type:"chooseValue",key,options:["true","false"],index:0},this.host.refresh();return;case"enum":this.mode={type:"chooseValue",key,options:field5.options,index:0},this.host.refresh();return;case"number":this.beginTextEdit(key,void 0);return;case"json":this.beginJsonEdit(key,void 0);return;case"stringMap":this.writeValue(key,{}),this.host.pushPane(new DictPane(this.host,this.model,key));return}}beginTextEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let parsed=Number(raw.trim());if(!Number.isFinite(parsed))return this.error=`${key} must be a number.`,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,parsed)},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(String(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}beginJsonEdit(key,current){let editor=new ValueEditor({onCommit:raw=>{let text2=raw.trim();if(!text2){this.mode={type:"list"},this.writeValue(key,DELETE);return}let shapeError=validateJsonCompatValue(key,text2);if(shapeError)return this.error=shapeError,this.host.refresh();this.error=void 0,this.mode={type:"list"},this.writeValue(key,JSON.parse(text2))},onCancel:()=>{this.mode={type:"list"},this.error=void 0,this.host.refresh()}});current!==void 0&&editor.beginTweak(JSON.stringify(current)),editor.focused=this.focused,this.mode={type:"editValue",key,editor},this.host.refresh()}parseChosen(option){return option==="true"?!0:option==="false"?!1:option}writeValue(key,value){this.model.setField(["compat",key],value)}fail(message){this.error=message,this.host.refresh()}setFocused(focused){this.focused=focused,this.mode.type==="editValue"&&(this.mode.editor.focused=focused)}isEditing(){return this.mode.type==="editValue"}hints(){return this.mode.type==="editValue"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):this.mode.type==="chooseValue"?[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","set"),keyHint("tui.select.cancel","cancel")].join(" "):[keyHint("tui.select.confirm","edit"),keyHint("app.list.toggle","toggle"),keyHint("app.provider.removeEntry","remove"),keyHint("tui.select.cancel","back")].join(" ")}},CompatKeyPickerPane=class{constructor(host,api,taken,onPick){this.crumb="compat \xB7 new entry",this.query="",this.index=0,this.focused=!1,this.host=host,this.api=api,this.taken=taken,this.onPick=onPick,this.editor=new ValueEditor({onCommit:()=>this.pickCurrent(),onCancel:()=>this.host.popPane()})}candidates(){let available=compatFieldsForApi(this.api).filter(field5=>!this.taken.has(field5.key)),query=this.query.trim();return query?fuzzyFilter(available,query,field5=>`${field5.key} ${field5.note??""}`):available}render(width){let theme2=this.host.theme,lines=[this.editor.renderLine(width)],candidates=this.candidates();candidates.length===0&&lines.push(renderInfoLine(theme2,"No remaining known fields.",width));for(let[rowIndex,field5]of candidates.entries())lines.push(renderPlainLine(theme2,field5.key,{active:rowIndex===this.index,paneFocused:this.focused,note:field5.note?`\xB7 ${field5.kind} \u2014 ${truncate3(field5.note,30)}`:`\xB7 ${field5.kind}`,width}));return lines}scrollWindow(){return{top:1,cursor:1+this.index}}pickCurrent(){let field5=this.candidates()[this.index];field5&&(this.host.popPane(),this.onPick(field5.key))}handleInput(data){let kb=this.host.keybindings;if(kb.matches(data,"tui.select.up")){let count=this.candidates().length;count>0&&(this.index=this.index===0?count-1:this.index-1),this.host.refresh();return}if(kb.matches(data,"tui.select.down")){let count=this.candidates().length;count>0&&(this.index=(this.index+1)%count),this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.pickCurrent();return}let before=this.query;this.editor.handleInput(data),this.query=this.editor.value,this.query!==before&&(this.index=0),this.host.refresh()}setFocused(focused){this.focused=focused,this.editor.focused=focused}isEditing(){return!0}hints(){return[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","choose"),keyHint("tui.select.cancel","back")].join(" ")}};function baseUrlHint(api){switch(api){case"openai-responses":case"openai-completions":case"openai-codex-responses":return"baseUrl includes the version path, e.g. https://api.openai.com/v1";case"anthropic-messages":return"baseUrl is the bare origin \u2014 /v1/messages is added automatically";case"mistral-conversations":return"baseUrl is the bare origin \u2014 /v1 is added automatically";case"google-generative-ai":return"baseUrl includes the version path, e.g. https://generativelanguage.googleapis.com/v1beta";default:return}}function validateBaseUrlValue(value){let url;try{url=new URL(value)}catch{return"baseUrl must be a valid URL."}if(url.protocol!=="http:"&&url.protocol!=="https:")return`Unsupported protocol: ${url.protocol}`;if(url.username||url.password||url.hash)return"baseUrl must not contain credentials or a fragment."}var ApiAuthPane=class{constructor(host,registry){this.rows=["baseUrl","apiKey","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.registry=registry}provider(){return this.host.store.getProvider(this.host.providerId)}scrollWindow(){return{cursor:this.index,bottom:this.bottomNoteCount()}}bottomNoteCount(){let status=this.registry.getProviderAuthStatus(this.host.providerId),hint=baseUrlHint(this.provider()?.api);return(this.edit.error?1:0)+(status.configured?1:0)+1+(hint?1:0)}render(width){let theme2=this.host.theme,provider=this.provider(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,value=provider?.[row==="apiType"?"api":row];lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:value?row==="apiKey"?maskApiKey(value):value:"not set",unset:!value,active,paneFocused:this.focused,editing:row==="apiType"?void 0:this.edit.editor(row),width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let status=this.registry.getProviderAuthStatus(this.host.providerId);status.configured&&status.source==="stored"?lines.push(renderInfoLine(theme2,"A stored credential (auth.json) takes precedence over the apiKey here.",width)):status.configured&&status.source==="environment"&&lines.push(renderInfoLine(theme2,`An environment variable (${status.label??"env"}) currently provides the key.`,width)),lines.push(renderInfoLine(theme2,"Values are stored raw; $VAR / !command references resolve at request time.",width));let hint=baseUrlHint(provider?.api);return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createProviderApiPane(this.host)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];row!=="apiType"&&this.edit.begin(row,this.provider()?.[row]??"",mode,this.focused,value=>this.commit(row,value),firstData)}commit(row,raw){let value=raw.trim();if(row==="baseUrl"&&value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}if(row==="baseUrl"&&!value){let builtin=builtinDefaults(this.host.providerId).baseUrl!==void 0,modelsCovered=this.host.store.getModels(this.host.providerId).every(model=>model.baseUrl!==void 0);if(!builtin&&!modelsCovered&&this.host.store.getModels(this.host.providerId).length>0)return"baseUrl cannot be removed while models rely on it."}this.host.edits.setProviderField([row],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createProviderApiPane(host){let current=()=>host.store.getProvider(host.providerId)?.api;return new ChoicePane(host,"API Type",{current,choices:()=>{let fallback=builtinDefaults(host.providerId).api,label=fallback?`not set (built-in default: ${fallback})`:"not set (models define their own)",values=[void 0,...API_TYPES],value=current();return value&&!values.includes(value)&&values.push(value),values.map(value2=>({value:value2,label:value2??label,dim:value2===void 0}))},choose:api=>{if(api===void 0){let uncovered=host.store.getModels(host.providerId).filter(model=>!model.api&&!builtinDefaults(host.providerId,model.id).api);if(uncovered.length)return uncovered.length===1?`Model "${uncovered[0].id}" resolves its API from here \u2014 give it a model-level API first.`:`${uncovered.length} ${plural(uncovered.length,"model")} resolve their API from here \u2014 give them model-level APIs first.`}host.edits.setProviderField(["api"],api??DELETE)}})}var REASONING_OPTIONS=[{label:"true",value:!0},{label:"false",value:!1},{label:"default (false)",value:void 0}];function createReasoningPane(host,model){return new ChoicePane(host,"reasoning",{current:()=>model.read().reasoning,choices:()=>REASONING_OPTIONS.map(option=>({...option,dim:option.value===void 0})),choose:value=>{model.setField(["reasoning"],value===void 0?DELETE:value)}})}var InputTypesPane=class{constructor(host,model){this.crumb="input",this.index=0,this.focused=!1,this.host=host,this.model=model}selected(){return new Set(this.model.read().input??["text"])}render(width){let theme2=this.host.theme,selected=this.selected(),lines=INPUT_TYPES.map((type,rowIndex)=>renderPlainLine(theme2,type,{checked:selected.has(type),active:rowIndex===this.index,paneFocused:this.focused,width}));return this.model.read().input===void 0&&lines.push(renderInfoLine(theme2,"Not set \u2014 the runtime default is [text].",width)),this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings,next=moveSelection(kb,data,this.index,INPUT_TYPES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"app.list.toggle")){let type=INPUT_TYPES[this.index],selected=this.selected();if(selected.has(type)){if(selected.size===1){this.error="At least one input type must stay selected.",this.host.refresh();return}selected.delete(type)}else selected.add(type);this.error=void 0;let next2=INPUT_TYPES.filter(entry=>selected.has(entry));this.model.setField(["input"],[...next2]);return}if(kb.matches(data,"tui.select.confirm")||kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused}hints(){return[keyHint("app.list.toggle","toggle"),keyHint("tui.select.confirm","done"),keyHint("tui.select.cancel","back")].join(" ")}},COST_RATES=["input","output","cacheRead","cacheWrite"],CostPane=class{constructor(host,model){this.crumb="cost",this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}cost(){let cost=this.model.read().cost;if(cost)return{input:cost.input,output:cost.output,cacheRead:cost.cacheRead,cacheWrite:cost.cacheWrite}}render(width){let theme2=this.host.theme,cost=this.cost(),lines=[];for(let[rowIndex,rate]of COST_RATES.entries()){let value=cost?.[rate];lines.push(renderKeyValueLine(theme2,{keyLabel:rate,valueText:value===void 0?"0 (default)":`$${value} / M tokens`,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,editing:this.edit.editor(rate),width}))}let tiers=this.model.read().cost?.tiers;return tiers&&tiers.length>0&&lines.push(renderInfoLine(theme2,`tiers: ${tiers.length} (read-only; kept as-is)`,width)),this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,COST_RATES.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.beginEdit("tweak");return}if(isPrintableInput(data)){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let rate=COST_RATES[this.index],current=this.cost()?.[rate];this.edit.begin(rate,current===void 0?"":String(current),mode,this.focused,value=>this.commit(rate,value),firstData)}commit(rate,raw){let value=raw.trim(),parsed=value===""?0:Number(value);if(!Number.isFinite(parsed)||parsed<0)return"cost rates must be finite non-negative numbers.";this.model.read().cost?this.model.setField(["cost",rate],parsed):this.model.setField(["cost"],{input:0,output:0,cacheRead:0,cacheWrite:0,[rate]:parsed})}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit"),keyHint("tui.select.cancel","back")].join(" ")}},ModelSpecificApiPane=class{constructor(host,model){this.crumb="Model-Specific API",this.rows=["baseUrl","apiType"],this.index=0,this.focused=!1,this.host=host,this.edit=new InlineEdit(()=>host.refresh()),this.model=model}inherited(key){let provider=this.host.store.getProvider(this.host.providerId),providerValue=key==="api"?provider?.api:provider?.baseUrl;if(providerValue)return{value:providerValue,via:"provider"};let current=this.model.read(),effective=key==="api"?this.host.effectiveApi(current):this.host.effectiveBaseUrl(current);return effective?{value:effective,via:"built-in"}:void 0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[];for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index,key=row==="apiType"?"api":row,override=current[key],inherited=override?void 0:this.inherited(key);lines.push(renderKeyValueLine(theme2,{keyLabel:row==="apiType"?"API Type":row,valueText:override??inherited?.value??"not set",unset:!override,note:inherited?`\xB7 ${inherited.via}`:void 0,active,paneFocused:this.focused,editing:row==="baseUrl"?this.edit.editor(row):void 0,width}))}this.edit.error&&lines.push(theme2.fg("error",truncate3(this.edit.error,Math.max(10,width-2))));let hint=baseUrlHint(this.host.effectiveApi(current));return hint&&lines.push(renderInfoLine(theme2,hint,width)),lines}handleInput(data){let kb=this.host.keybindings;if(this.edit.handleInput(data,kb))return;let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}if(kb.matches(data,"tui.select.confirm")){this.rows[this.index]==="apiType"?this.host.pushPane(createModelApiPane(this.host,this.model)):this.beginEdit("tweak");return}if(isPrintableInput(data)){if(this.rows[this.index]==="apiType")return;this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let base=this.model.read().baseUrl??this.inherited("baseUrl")?.value??"";this.edit.begin("baseUrl",base,mode,this.focused,value=>this.commit(value),firstData)}commit(raw){let value=raw.trim();if(value){let invalid2=validateBaseUrlValue(value);if(invalid2)return invalid2}this.model.setField(["baseUrl"],value===""?DELETE:value)}setFocused(focused){this.focused=focused,this.edit.setFocused(focused)}isEditing(){return this.edit.editing}hints(){return this.edit.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("tui.select.cancel","back")].join(" ")}};function createModelApiPane(host,model){let fallback=()=>{let provider=host.store.getProvider(host.providerId);return provider?.api??builtinDefaults(host.providerId,model.read().id,provider?.api).api};return new ChoicePane(host,"API Type",{current:()=>model.read().api,choices:()=>{let providerApi=host.store.getProvider(host.providerId)?.api,inherited=fallback(),label=providerApi?`provider: ${providerApi}`:inherited?`built-in: ${inherited}`:"no provider or built-in API",values=[void 0,...API_TYPES],current=model.read().api;return current&&!values.includes(current)&&values.push(current),values.map(value=>({value,label:value??label,dim:value===void 0}))},choose:value=>{if(value===void 0&&!fallback())return"Nothing to inherit \u2014 pick an API.";model.setField(["api"],value??DELETE)}})}var ThinkingMapPane=class{constructor(host,model){this.crumb="thinkingLevelMap",this.mode={type:"levels"},this.index=0,this.focused=!1,this.host=host,this.model=model}map(){return this.model.read().thinkingLevelMap??{}}render(width){let theme2=this.host.theme,lines=[];if(this.model.read().reasoning!==!0&&lines.push(renderInfoLine(theme2,"reasoning is not true \u2014 the map is stored but currently has no effect.",width)),this.mode.type==="levels")for(let[rowIndex,level]of THINKING_LEVELS4.entries()){let value=this.map()[level],status=value===void 0?"default":value===null?"null (hidden)":value;lines.push(renderKeyValueLine(theme2,{keyLabel:level,valueText:status,unset:value===void 0,active:rowIndex===this.index,paneFocused:this.focused,width}))}else if(this.mode.type==="choice"){lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 mapping`,width));for(let[choiceIndex,label]of["String target (provider effort)","Hidden (null)","Default (remove key)"].entries())lines.push(renderPlainLine(theme2,label,{active:choiceIndex===this.mode.index,paneFocused:this.focused,width}))}else lines.push(renderInfoLine(theme2,`${this.mode.level} \xB7 non-empty provider effort`,width)),lines.push(renderKeyValueLine(theme2,{keyLabel:this.mode.level,active:!0,paneFocused:this.focused,editing:this.editor,width}));return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),lines}handleInput(data){let kb=this.host.keybindings;if(this.mode.type==="target"){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editor?.handleInput(data),this.host.refresh();return}if(this.mode.type==="choice"){if(kb.matches(data,"tui.select.up")){this.mode={...this.mode,index:this.mode.index===0?2:this.mode.index-1},this.host.refresh();return}if(kb.matches(data,"tui.select.down")){this.mode={...this.mode,index:(this.mode.index+1)%3},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.mode={type:"levels"},this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){let{level,index:index3}=this.mode;if(index3===0){let editor=new ValueEditor({onCommit:value=>{let target=value.trim();if(!target)return this.error="A string target must be non-empty; use Hidden for null.",this.host.refresh();this.error=void 0,this.mode={type:"levels"},this.editor=void 0,this.model.setField(["thinkingLevelMap",level],target)},onCancel:()=>{this.editor=void 0,this.mode={type:"levels"},this.host.refresh()}});this.editor=editor,editor.focused=this.focused;let existing=this.map()[level];typeof existing=="string"&&editor.beginTweak(existing),this.mode={type:"target",level},this.host.refresh();return}this.mode={type:"levels"},this.model.setField(["thinkingLevelMap",level],index3===1?null:DELETE);return}return}let next=moveSelection(kb,data,this.index,THINKING_LEVELS4.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.confirm")){this.mode={type:"choice",level:THINKING_LEVELS4[this.index],index:0},this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){this.host.popPane();return}}setFocused(focused){this.focused=focused,this.editor&&(this.editor.focused=focused&&this.mode.type==="target")}isEditing(){return this.mode.type==="target"}hints(){return this.mode.type==="target"?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","back")].join(" "):[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.mode.type==="choice"?"set":"edit"),keyHint("tui.select.cancel","back")].join(" ")}};var DEFAULT_CONTEXT_WINDOW2=128e3,DEFAULT_MAX_TOKENS2=16384,ModelFieldsPane=class{constructor(host,model){this.index=0,this.focused=!1,this.renaming=!1,this.disposed=!1,this.host=host,this.model=model;let rows=[{kind:"text",key:"id"},{kind:"text",key:"name"},{kind:"reasoning"},{kind:"subpage",key:"thinkingLevelMap"},{kind:"subpage",key:"input"},{kind:"subpage",key:"cost"},{kind:"number",key:"contextWindow"},{kind:"number",key:"maxTokens"},{kind:"subpage",key:"compat"}];model.isDraft?rows.push({kind:"modelApi"}):rows.push({kind:"builtin"},{kind:"modelApi"},{kind:"deleteModel"}),this.rows=rows}startEditingId(){this.index=0,this.beginEdit("overwrite")}draftEmpty(){return this.model.isDraft&&Object.keys(this.model.read()).length===0}render(width){let theme2=this.host.theme,current=this.model.read(),lines=[],api=this.host.effectiveApi(current);lines.push(renderInfoLine(theme2,api?`api: ${api}${current.api?" (model)":""}`:"api: none resolved \u2014 see Model-Specific API below",width));for(let[rowIndex,row]of this.rows.entries()){let active=rowIndex===this.index;lines.push(this.renderRow(row,current,active,width))}return this.error&&lines.push(theme2.fg("error",truncate3(this.error,Math.max(10,width-2)))),this.renaming&&lines.push(renderInfoLine(theme2,"Saving model id\u2026",width)),lines}scrollWindow(){return{top:1,bottom:(this.error?1:0)+(this.renaming?1:0),cursor:1+this.index}}renderRow(row,current,active,width){let theme2=this.host.theme,editing=this.editingRow===row?this.editing:void 0;switch(row.kind){case"text":{let value=current[row.key],unsetText=row.key==="id"?"required":"falls back to id";return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value??`not set (${unsetText})`,unset:!value,active,paneFocused:this.focused,editing,width})}case"reasoning":{let value=current.reasoning;return renderKeyValueLine(theme2,{keyLabel:"reasoning",valueText:value===void 0?"false (default)":String(value),unset:value===void 0,active,paneFocused:this.focused,width})}case"subpage":{let summary=this.subpageSummary(row.key,current);return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:summary.text,unset:summary.unset,active,paneFocused:this.focused,width})}case"number":{let value=current[row.key],fallback=row.key==="contextWindow"?DEFAULT_CONTEXT_WINDOW2:DEFAULT_MAX_TOKENS2;return renderKeyValueLine(theme2,{keyLabel:row.key,valueText:value===void 0?`${fallback} (default)`:String(value),unset:value===void 0,active,paneFocused:this.focused,editing,width})}case"builtin":{let id=current.id,count=id?matchBuiltinModels(id,this.host.effectiveApi(current)).length:0;return renderKeyValueLine(theme2,{valueText:"Use Built-in Data",active,paneFocused:this.focused,note:id?`\xB7 ${count} ${plural(count,"candidate")}`:"\xB7 set id first",width})}case"modelApi":return renderKeyValueLine(theme2,{valueText:"Model-Specific API",active,paneFocused:this.focused,note:`\xB7 ${this.modelApiSummary(current)}`,width});case"deleteModel":return renderKeyValueLine(theme2,{valueText:"Delete Model",active,paneFocused:this.focused,width})}}modelApiSummary(current){let overrides=[current.baseUrl?"baseUrl":"",current.api?"API Type":""].filter(Boolean);if(overrides.length>0)return overrides.join(" + ");let provider=this.host.store.getProvider(this.host.providerId);return provider?.api||provider?.baseUrl?"provider defaults":this.host.effectiveApi(current)||this.host.effectiveBaseUrl(current)?"built-in defaults":"not set"}subpageSummary(key,current){switch(key){case"thinkingLevelMap":{let map=current.thinkingLevelMap,count=map?Object.keys(map).length:0;return count>0?{text:`${count} ${plural(count,"mapping")}`,unset:!1}:{text:"default",unset:!0}}case"input":return current.input?{text:`[${current.input.join(", ")}]`,unset:!1}:{text:"[text] (default)",unset:!0};case"cost":{let cost=current.cost;return cost?{text:`$${cost.input} / $${cost.output} in/out`,unset:!1}:{text:"all 0 (default)",unset:!0}}case"compat":{let compat=current.compat,count=compat?Object.keys(compat).length:0;if(count>0)return{text:`${count} ${count===1?"entry":"entries"}`,unset:!1};let inherited=this.host.store.getProvider(this.host.providerId)?.compat,inheritedCount=inherited?Object.keys(inherited).length:0;return inheritedCount>0?{text:`${inheritedCount} from provider`,unset:!0}:{text:"none",unset:!0}}}}handleInput(data){if(this.renaming||this.disposed)return;let kb=this.host.keybindings;if(this.editing){if(kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.down"))return;this.editing.handleInput(data),this.host.refresh();return}let next=moveSelection(kb,data,this.index,this.rows.length);if(next!==void 0){this.index=next,this.host.refresh();return}if(kb.matches(data,"tui.select.cancel")){if(!this.model.isDraft){this.host.popPane();return}if(this.draftEmpty()){this.host.discardModelDraft();return}let label=this.model.read().name??this.model.read().id??"New Model";this.host.confirm(`Discard the new model "${label}"? Its fields are not saved.`,"Discard Model",()=>this.host.discardModelDraft());return}if(kb.matches(data,"app.list.toggle")){this.toggleRow();return}if(kb.matches(data,"tui.select.confirm")){this.enterRow();return}if(isPrintableInput(data)){this.overwriteRow(data);return}}toggleRow(){if(this.rows[this.index].kind!=="reasoning")return;let current=this.model.read().reasoning;this.model.setField(["reasoning"],current!==!0)}enterRow(){let row=this.rows[this.index];switch(row.kind){case"text":case"number":this.beginEdit("tweak");return;case"reasoning":this.host.pushPane(createReasoningPane(this.host,this.model));return;case"subpage":this.pushSubpage(row.key);return;case"modelApi":this.host.pushPane(new ModelSpecificApiPane(this.host,this.model));return;case"builtin":{if(!this.model.read().id){this.host.notify("Set the model id first.","warning");return}this.host.pushPane(new BuiltinCandidatesPane(this.host,this.model));return}case"deleteModel":{let id=this.model.read().id;if(!id)return;if(this.host.isCurrentModel(id)){this.host.notify("The current model cannot be deleted; switch models with /model first.","error");return}this.host.confirm(`Delete model "${id}" from ${this.host.providerId}?`,"Delete Model",()=>{this.host.edits.removeModel(id),this.host.onModelRemoved(id)});return}}}overwriteRow(data){let row=this.rows[this.index];if(row.kind==="text"||row.kind==="number"){this.beginEdit("overwrite",data);return}}beginEdit(mode,firstData){let row=this.rows[this.index];if(row.kind!=="text"&&row.kind!=="number")return;let current=this.model.read()[row.key],editor=new ValueEditor({onCommit:value=>this.commitText(row,value),onCancel:()=>{if(this.editing=void 0,this.editingRow=void 0,this.error=void 0,this.draftEmpty()){this.host.discardModelDraft();return}this.host.refresh()}});this.editing=editor,this.editingRow=row,editor.focused=this.focused,mode==="overwrite"?editor.beginOverwrite(firstData):editor.beginTweak(current===void 0?"":String(current)),this.host.refresh()}commitText(row,raw){let value=raw.trim(),finish=error=>{if(this.error=error,error){this.host.refresh();return}this.editing=void 0,this.editingRow=void 0,this.host.refresh()};if(row.key==="id"){if(!value){finish("id is required and cannot be empty.");return}if(this.model.isDraft){this.model.setField(["id"],value),finish(this.host.commitModelDraft());return}let current=this.model.read().id;if(!current){finish("Missing current id.");return}if(value===current){finish();return}if(this.host.isCurrentModel(current)){finish("The current model's id cannot be renamed; switch models with /model first.");return}if(this.host.store.getModel(this.host.providerId,value)){finish(`Model "${value}" already exists.`);return}this.renaming=!0,this.host.refresh(),this.model.rename(value).then(error=>{this.renaming=!1,this.disposed||finish(error)},error=>{this.renaming=!1,this.disposed||finish(error instanceof Error?error.message:String(error))});return}if(row.key==="name"){this.model.setField(["name"],value===""?DELETE:value),finish();return}if(value===""){this.model.setField([row.key],DELETE),finish();return}let parsed=Number(value);if(!Number.isSafeInteger(parsed)||parsed<=0){finish(`${row.key} must be a positive integer.`);return}this.model.setField([row.key],parsed),finish()}pushSubpage(key){switch(key){case"thinkingLevelMap":this.host.pushPane(new ThinkingMapPane(this.host,this.model));return;case"input":this.host.pushPane(new InputTypesPane(this.host,this.model));return;case"cost":this.host.pushPane(new CostPane(this.host,this.model));return;case"compat":this.host.pushPane(new CompatPane(this.host,this.model));return}}setFocused(focused){this.focused=focused,this.editing&&(this.editing.focused=focused)}isEditing(){return this.editing!==void 0||this.renaming}dispose(){this.disposed=!0}hints(){return this.editing?[keyHint("tui.input.submit","save"),keyHint("tui.select.cancel","cancel")].join(" "):[rawKeyHint("type","overwrite"),keyHint("tui.select.confirm","edit / open"),keyHint("app.list.toggle","toggle"),keyHint("tui.select.cancel",this.model.isDraft?"discard":"back")].join(" ")}};var LEFT_WIDTH_MIN=16,LEFT_WIDTH_MAX=40,BODY_ROWS=14,MIN_WIDTH=56;function padTo(line,width){let missing=width-visibleWidth(line);return missing>0?line+" ".repeat(missing):line}function leftItemKey(item){return item?item.kind==="model"?`model:${item.modelId}`:item.kind:""}var ProviderEditorScreen=class{constructor(tui,theme2,keybindings,done,options){this.leftItems=[],this.leftIndex=0,this.focusPane="left",this.stack=[],this.disposed=!1,this._focused=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.options=options,this.edits=new ProviderEdits(options.store,options.providerId,options.refresher,()=>this.refresh()),this.host=this.createHost(),this.rebuildLeftItems(),this.resetRightStack()}get focused(){return this._focused}set focused(value){this._focused=value,this.topPane()?.setFocused(value&&this.focusPane==="right")}invalidate(){this.cache=void 0}dispose(){if(!this.disposed){this.disposed=!0;for(let pane of this.stack)pane.dispose?.();this.stack=[],hasProviderSettings(this.options.store.getProvider(this.options.providerId))||this.options.store.discardProviderDraft(this.options.providerId)}}render(width){if(this.cache&&this.cache.width===width)return this.cache.lines;let lines=this.renderFrame(width);return this.cache={width,lines},lines}handleInput(data){if(this.focusPane==="right"){let pane=this.topPane();if(pane&&!pane.isEditing?.()&&this.keybindings.matches(data,"app.provider.switchPaneLeft")){pane.setFocused(!1),this.focusPane="left",this.refresh();return}pane?.handleInput(data);return}let kb=this.keybindings;if(kb.matches(data,"tui.select.up")){this.moveLeft(-1);return}if(kb.matches(data,"tui.select.down")){this.moveLeft(1);return}if(kb.matches(data,"app.provider.switchPaneRight")){this.activateLeftItem("inspect");return}if(kb.matches(data,"tui.select.confirm")){this.activateLeftItem("activate");return}kb.matches(data,"tui.select.cancel")&&this.done("back")}syncFromStore(){if(this.disposed||this.edits.renaming)return;let selected=this.leftItems[this.leftIndex],selectedKey=leftItemKey(selected);this.rebuildLeftItems();let nextIndex=this.leftItems.findIndex(item=>leftItemKey(item)===selectedKey);this.leftIndex=nextIndex>=0?nextIndex:Math.min(this.leftIndex,this.selectableIndex(0)),nextIndex<0&&selected?.kind==="model"&&this.resetRightStack(),this.refresh()}rebuildLeftItems(){let items=[{kind:"apiAuth"},{kind:"fetch"},{kind:"separator"}];for(let model of this.options.store.getModels(this.options.providerId))items.push({kind:"model",modelId:model.id});this.draft&&items.push({kind:"draft"}),items.push({kind:"separator"},{kind:"addModel"},{kind:"deleteProvider"}),this.leftItems=items}selectableIndex(start){let index3=this.leftItems.findIndex((item,i)=>i>=start&&item.kind!=="separator");return index3>=0?index3:0}moveLeft(delta){let selectable=this.leftItems.map((item,index3)=>({item,index:index3})).filter(entry=>entry.item.kind!=="separator");if(selectable.length===0)return;let position=selectable.findIndex(entry=>entry.index===this.leftIndex),next=selectable[(position+delta+selectable.length)%selectable.length];next.index!==this.leftIndex&&(this.leftIndex=next.index,this.resetRightStack(),this.refresh())}activateLeftItem(via){let item=this.leftItems[this.leftIndex];if(item)switch(item.kind){case"apiAuth":case"model":case"draft":this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return;case"fetch":if(this.focusPane="right",via==="activate"){let pane=this.topPane();pane instanceof FetchModelsPane&&pane.start()}this.topPane()?.setFocused(this._focused),this.refresh();return;case"addModel":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}this.draft||(this.draft=this.edits.draft(),this.rebuildLeftItems());let draftIndex=this.leftItems.findIndex(entry=>entry.kind==="draft");draftIndex>=0&&(this.leftIndex=draftIndex),this.resetRightStack(),this.focusPane="right";let pane=this.topPane();pane?.setFocused(this._focused),pane instanceof ModelFieldsPane&&!this.draft.read().id&&pane.startEditingId(),this.refresh();return}case"deleteProvider":{if(via==="inspect"){this.focusPane="right",this.topPane()?.setFocused(this._focused),this.refresh();return}if(this.host.isCurrentProvider()){this.host.notify("The current model's provider cannot be deleted; switch models with /model first.","error");return}let builtin=isBuiltinProviderId(this.options.providerId);this.host.confirm(`Delete provider "${this.options.providerId}" from models.json?`+(builtin?" The built-in catalog remains and its models may reappear.":"")+" Stored credentials in auth.json are kept.","Delete Provider",()=>{this.edits.removeProvider(),this.done("deleted")});return}default:return}}renderLeft(width){let theme2=this.theme,focused=this.focusPane==="left",rows=[],renderRow=index3=>{let item=this.leftItems[index3];return item.kind==="separator"?theme2.fg("borderMuted",` ${"\u2500".repeat(Math.max(1,width-4))}`):this.renderLeftItem(item,index3===this.leftIndex,focused,width)};if(this.leftItems.length<=BODY_ROWS)for(let index3=0;index3<this.leftItems.length;index3++)rows.push(renderRow(index3));else{let slots=BODY_ROWS-1,start=Math.max(0,Math.min(this.leftIndex-Math.floor(slots/2),this.leftItems.length-slots));for(let index3=start;index3<start+slots;index3++)rows.push(renderRow(index3));let selectable=this.leftItems.filter(item=>item.kind!=="separator"),position=selectable.indexOf(this.leftItems[this.leftIndex]);rows.push(theme2.fg("dim",` (${position+1}/${selectable.length})`))}for(;rows.length<BODY_ROWS;)rows.push("");return rows}leftItemContent(item){let store=this.options.store,text2,note;switch(item.kind){case"apiAuth":text2="API Auth";break;case"fetch":text2="Fetch Models",note=this.fetchStatus;break;case"model":{let model=store.getModel(this.options.providerId,item.modelId);text2=model?modelDisplayName(model):item.modelId;break}case"draft":{text2=this.draft?.read().name??this.draft?.read().id??"New Model",note="\xB7 draft";break}case"addModel":text2="+ Add Model";break;case"deleteProvider":text2="Delete Provider";break;default:text2=""}let dim=item.kind==="draft"&&!this.draft?.read().name&&!this.draft?.read().id;return{text:text2,note,dim}}renderLeftItem(item,active,focused,width){let theme2=this.theme,lit=active&&focused,marker=lit?theme2.fg("accent",`${CURSOR2} `):" ",style=(text3,dim2=!1)=>theme2.fg(lit?"accent":dim2?"dim":"text",text3),{text:label,note,dim}=this.leftItemContent(item),text2=label;if(item.kind==="model"||item.kind==="draft"){let budget=Math.max(8,width-2-(note?visibleWidth(note)+1:0));text2=truncateMiddle2(text2,budget)}let noteText=note?theme2.fg("dim",` ${note}`):"";return truncateToWidth(marker+style(text2,dim)+noteText,width)}topPane(){return this.stack[this.stack.length-1]}pushPane(pane){this.topPane()?.setFocused(!1),this.focusPane="right",this.stack.push(pane),pane.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}popPane(){if(this.stack.length<=1){this.topPane()?.setFocused(!1),this.focusPane="left",this.refresh();return}let pane=this.stack.pop();pane?.setFocused(!1),pane?.dispose?.(),this.topPane()?.setFocused(this._focused&&this.focusPane==="right"),this.refresh()}resetRightStack(){for(let pane of this.stack)pane.dispose?.();let item=this.leftItems[this.leftIndex];this.stack=[this.createBasePane(item)],this.topPane()?.setFocused(this._focused&&this.focusPane==="right")}createBasePane(item){switch(item?.kind){case"apiAuth":return new ApiAuthPane(this.host,this.options.registry);case"fetch":return new FetchModelsPane(this.host);case"model":return new ModelFieldsPane(this.host,this.persistedHandle(item.modelId));case"draft":return new ModelFieldsPane(this.host,this.draft);case"addModel":return new InfoPane(this.host,["Press Enter to create a model.","A draft is kept in memory until its id is set; Esc on the draft discards it."],()=>this.activateLeftItem("activate"));case"deleteProvider":return new InfoPane(this.host,["Press Enter to delete this provider from models.json."],()=>this.activateLeftItem("activate"));default:return new InfoPane(this.host,[])}}persistedHandle(modelId){return this.edits.model(modelId,(oldId,newId)=>{let selected=this.leftItems[this.leftIndex];selected?.kind==="model"&&selected.modelId===oldId&&(selected.modelId=newId),this.syncFromStore()})}createHost(){let store=this.options.store,providerId=this.options.providerId;return{tui:this.tui,theme:this.theme,keybindings:this.keybindings,store,edits:this.edits,providerId,pushPane:pane=>this.pushPane(pane),popPane:()=>this.popPane(),refresh:()=>this.refresh(),notify:(message,type)=>this.options.notify(message,type),effectiveApi:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).api,effectiveBaseUrl:model=>effectiveModelSettings(providerId,store.getProvider(providerId),model).baseUrl,commitModelDraft:()=>this.commitModelDraft(),discardModelDraft:()=>this.discardModelDraft(),isCurrentModel:modelId=>this.options.currentModel?.provider===providerId&&this.options.currentModel.id===modelId,isCurrentProvider:()=>this.options.currentModel?.provider===providerId,setFetchStatus:status=>{this.fetchStatus=status,this.refresh()},runFetch:signal=>fetchProviderModels(this.options,signal),importModels:async(models,signal)=>{let error=await importProviderModels({...this.options,edits:this.edits},models,signal);return this.disposed||this.syncFromStore(),error},confirm:(message,actionLabel,action)=>this.pushPane(new ConfirmPane(this.host,message,actionLabel,action)),onModelRemoved:()=>{for(this.rebuildLeftItems(),this.leftIndex=Math.min(this.leftIndex,this.leftItems.length-1);this.leftIndex>0&&this.leftItems[this.leftIndex]?.kind==="separator";)this.leftIndex--;this.leftItems[this.leftIndex]?.kind==="separator"&&(this.leftIndex=this.selectableIndex(0)),this.focusPane="left",this.resetRightStack(),this.refresh()}}}discardModelDraft(){if(!this.draft)return;this.draft=void 0,this.rebuildLeftItems();let addIndex=this.leftItems.findIndex(item=>item.kind==="addModel");this.leftIndex=addIndex>=0?addIndex:this.selectableIndex(0),this.focusPane="left",this.resetRightStack(),this.refresh()}commitModelDraft(){let draft=this.draft;if(!draft)return"No model draft.";let error=this.edits.commitDraft(draft);if(error)return error;let id=draft.read().id.trim();this.draft=void 0,this.rebuildLeftItems();let index3=this.leftItems.findIndex(item=>item.kind==="model"&&item.modelId===id);index3>=0&&(this.leftIndex=index3),this.resetRightStack(),this.refresh()}refresh(){this.invalidate(),this.tui.requestRender()}renderFrame(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0];if(width<MIN_WIDTH)return[border,truncateToWidth(theme2.fg("warning",` /provider needs at least ${MIN_WIDTH} columns`),width),border];let leftWidth=this.computeLeftWidth(width),rightWidth=width-leftWidth-3,separator=theme2.fg("border"," \u2502 "),title=this.renderTitle(width),crumb=truncateToWidth(this.theme.fg("muted",this.topPane()?.crumb??""),rightWidth),leftLines=this.renderLeft(leftWidth),pane=this.topPane(),paneLines=pane?windowLines(theme2,pane.render(rightWidth),BODY_ROWS-1,pane.scrollWindow?.()):[],rightLines=[crumb,...paneLines],body2=[];for(let row=0;row<BODY_ROWS;row++){let left=padTo(truncateToWidth(leftLines[row]??"",leftWidth),leftWidth),right=truncateToWidth(rightLines[row]??"",rightWidth);body2.push(left+separator+right)}let footerLines=this.renderFooter(width);return[border,title,border,...body2,border,...footerLines,border]}computeLeftWidth(width){let longest=12;for(let item of this.leftItems){if(item.kind==="separator")continue;let{text:text2,note}=this.leftItemContent(item),label=text2+(note?` ${note}`:"");longest=Math.max(longest,visibleWidth(label))}let fit=Math.max(LEFT_WIDTH_MIN,Math.min(LEFT_WIDTH_MAX,longest+2));return Math.min(fit,Math.max(LEFT_WIDTH_MIN,Math.floor(width*.45)))}renderTitle(width){let theme2=this.theme,title=` /provider \xB7 ${this.options.providerId}`;return isBuiltinProviderId(this.options.providerId)&&(title+=" \xB7 overlays built-in catalog"),truncateToWidth(theme2.fg("accent",theme2.bold(title)),width)}renderFooter(width){if(this.focusPane==="right"){let hints2=[this.topPane()?.hints()??"",keyHint("app.provider.switchPaneLeft","focus left")].filter(Boolean).join(" ");return[truncateToWidth(hints2,width)]}let hints=[rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm",this.leftActivateLabel()),keyHint("app.provider.switchPaneRight","focus right"),keyHint("tui.select.cancel","back")].join(" ");return[truncateToWidth(hints,width)]}leftActivateLabel(){switch(this.leftItems[this.leftIndex]?.kind){case"fetch":return"fetch";case"addModel":return"create";case"deleteProvider":return"delete";default:return"open"}}};function modelDisplayName(model){return model.name??model.id}var LIST_ROWS=12,ProviderListScreen=class{constructor(tui,theme2,keybindings,done,store){this.mode="list",this.query="",this.index=0,this.active=!1,this.tui=tui,this.theme=theme2,this.keybindings=keybindings,this.done=done,this.store=store,this.input=new ValueEditor({onCommit:()=>this.confirm(),onCancel:()=>this.cancel()})}get focused(){return this.active}set focused(value){this.active=value,this.input.focused=value}invalidate(){}filtered(){let ids=this.store.getProviderIds();return this.query.trim()?fuzzyFilter(ids,this.query,id=>id):ids}render(width){let theme2=this.theme,border=new DynamicBorder(text2=>theme2.fg("border",text2)).render(width)[0]??"",lines=[border,truncateToWidth(theme2.fg("accent",theme2.bold(" /provider \u2014 models.json providers")),width),border,renderKeyValueLine(theme2,{keyLabel:this.mode==="list"?"Search":"Provider id",active:!1,paneFocused:this.active,editing:this.input,width}),""],area=[];if(this.mode==="list"){let entries=this.filtered(),total=entries.length+1;this.index=Math.min(this.index,total-1);let rows=[];for(let row=0;row<total;row++){let id=entries[row-1],provider=id===void 0?void 0:this.store.getProvider(id),note=id===void 0?void 0:provider?[`${String(provider.models?.length??0)} ${plural(provider.models?.length??0,"model")}`,provider.api].filter(Boolean).join(" \xB7 "):"pending deletion";rows.push(renderPlainLine(theme2,row===0?"+ Add Provider":id,{active:row===this.index,paneFocused:this.active,note,width}))}entries.length===0&&rows.push(renderInfoLine(theme2,this.query?"No matching providers.":"No providers yet.",width)),area.push(...windowLines(theme2,rows,LIST_ROWS,{cursor:this.index}))}else this.error&&area.push(truncateToWidth(theme2.fg("error",this.error),width));for(;area.length<LIST_ROWS;)area.push("");let hints=this.mode==="newProvider"?[keyHint("tui.input.submit","create"),keyHint("tui.select.cancel","cancel")]:[rawKeyHint("type","filter"),rawKeyHint("\u2191\u2193","move"),keyHint("tui.select.confirm","open"),keyHint("tui.select.cancel","close")];return[...lines,...area,border,truncateToWidth(hints.join(" "),width),border]}handleInput(data){let kb=this.keybindings;if(kb.matches(data,"tui.select.cancel")){this.cancel();return}if(this.mode==="list"){let total=this.filtered().length+1;if(kb.matches(data,"tui.select.up"))this.index=(this.index+total-1)%total;else if(kb.matches(data,"tui.select.down"))this.index=(this.index+1)%total;else if(kb.matches(data,"tui.select.confirm")){this.confirm();return}else{let previous=this.query;this.input.handleInput(data),this.query=this.input.value,this.query!==previous&&(this.index=this.query&&this.filtered().length>0?1:0)}}else this.input.handleInput(data);this.tui.requestRender()}confirm(){if(this.mode==="newProvider"){let id=this.input.value.trim();if(!id)this.error="Provider id must be non-empty.";else if(this.store.getProviderIds().includes(id))this.error="This provider id already exists.";else{this.store.ensureProviderView(id),this.done({kind:"open",providerId:id});return}}else if(this.index===0)this.mode="newProvider",this.error=void 0,this.input.reset(this.query);else{let id=this.filtered()[this.index-1];id&&this.done({kind:"open",providerId:id})}this.tui.requestRender()}cancel(){if(this.mode==="list"){this.done({kind:"close"});return}this.mode="list",this.error=void 0,this.input.reset(this.query),this.tui.requestRender()}};var ProviderTuiSession=class extends Container{constructor(tui){super(),this.controller=new AbortController,this.active=!1,this.tui=tui}get signal(){return this.controller.signal}get focused(){return this.active}set focused(value){this.active=value,this.screen&&isFocusable(this.screen)&&(this.screen.focused=value)}setScreen(screen){if(this.signal.aborted){screen.dispose?.();return}this.disposeScreen(),this.screen=screen,this.clear(),this.addChild(screen),this.tui.setFocus(this),this.tui.requestRender()}handleInput(data){this.signal.aborted||this.screen?.handleInput?.(data)}dispose(){this.signal.aborted||(this.controller.abort(),this.disposeScreen(),this.clear())}disposeScreen(){let previous=this.screen;this.screen=void 0,previous&&isFocusable(previous)&&(previous.focused=!1),previous?.dispose?.()}};var SavingScreen=class extends Container{constructor(theme2,keybindings,onCancel){super(),this.keybindings=keybindings,this.onCancel=onCancel,this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2))),this.addChild(new Text(theme2.fg("muted","Saving provider changes and updating models\u2026"),1,1)),this.addChild(new Text(keyHint("tui.select.cancel","return to providers"),1,0)),this.addChild(new DynamicBorder(text2=>theme2.fg("border",text2)))}handleInput(data){this.keybindings.matches(data,"tui.select.cancel")&&this.onCancel()}};function createProviderErrorScreen(tui,done,error){return new ExtensionSelectorComponent("models.json cannot be edited",["Back"],done,done,{tui,description:`${truncate3(error,2400)}
|
|
2069
2048
|
|
|
2070
|
-
Fix the file manually and open /provider again.`})}function createProviderApp(tui,theme2,keybindings,done,options){let{store,registry,runtime}=options,session=new ProviderTuiSession(tui),refresher=new RefreshCoordinator(runtime),activeEditor,closing;function notify(message,type){session.signal.aborted||options.notify(message,type)}store.onSaveResult=result2=>{session.signal.aborted||((result2.kind==="invalid"||result2.kind==="error")&¬ify(result2.error,"error"),activeEditor?.syncFromStore(),tui.requestRender())};function showList(){session.signal.aborted||(activeEditor=void 0,session.setScreen(new ProviderListScreen(tui,theme2,keybindings,result2=>{result2.kind==="close"?requestClose():openProvider(result2.providerId)},store)))}function openProvider(providerId){if(!store.getProviderIds().includes(providerId)){notify(`No provider ${JSON.stringify(providerId)} in models.json.`,"warning"),showList();return}activeEditor=new ProviderEditorScreen(tui,theme2,keybindings,showList,{store,refresher,providerId,registry,runtime,currentModel:options.getCurrentModel(),notify}),session.setScreen(activeEditor)}function showUnsaved(error){let back="Return to providers",retry="Retry saving",discard3="Discard unsaved changes and close";session.setScreen(new ExtensionSelectorComponent("Some changes are not saved",[back,retry,discard3],choice=>{if(choice===back){showList();return}choice===retry&&store.retrySave(),choice===discard3&&store.discardPending(),requestClose()},showList,{tui,description:truncate3(error,2400)}))}function requestClose(){if(closing||session.signal.aborted)return;let controller=new AbortController;closing=controller;let signal=AbortSignal.any([session.signal,controller.signal]);activeEditor=void 0,session.setScreen(new SavingScreen(theme2,keybindings,()=>{controller.abort(),closing=void 0,showList()})),finishClose(controller,signal)}async function finishClose(controller,signal){try{if(await store.flush(),signal.aborted)return;let unsaved=store.getPendingError();if(unsaved){closing=void 0,showUnsaved(unsaved);return}let outcome=await refresher.flush(signal);if(signal.aborted)return;outcome.ok||notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`,"warning");let current=options.getCurrentModel();if(current&&refresher.touchedProviders.includes(current.provider)){let refreshed=registry.find(current.provider,current.id);refreshed&&!await options.setModel(refreshed)&¬ify("Reselect the current model with /model to apply its updated configuration.","warning"),refreshed||notify("The current model is no longer available; select another with /model.","warning")}signal.aborted||done()}catch(error){signal.aborted||(notify(formatError2(error),"error"),showList())}finally{closing===controller&&(closing=void 0)}}return options.initialProviderId?openProvider(options.initialProviderId):showList(),session}function providerExtension(pi){let modelsPath;pi.on("session_start",(_event,ctx)=>{modelsPath=ctx.modelRuntime.getModelsPath()}),pi.registerCommand(COMMAND_NAME,{description:COMMAND_DESCRIPTION,getArgumentCompletions:async prefix=>{if(!modelsPath)return null;let load=await ModelsJsonStore.load(modelsPath);if(!load.ok)return null;let query=prefix.trim().toLowerCase(),items=load.store.getProviderIds().filter(id=>id.toLowerCase().startsWith(query)).map(id=>{let count=load.store.getModels(id).length;return{value:id,label:id,description:`${String(count)} ${plural(count,"model")}`}});return items.length?items:null},handler:async(args,ctx)=>{if(!ctx.hasUI||ctx.mode!=="tui"){ctx.ui.notify(NO_UI_WARNING,"warning");return}let path14=ctx.modelRuntime.getModelsPath();if(modelsPath=path14,!path14){ctx.ui.notify(NO_MODELS_FILE_WARNING,"warning");return}try{let load=await ModelsJsonStore.load(path14);if(!load.ok){await ctx.ui.custom((tui,_theme,_keybindings,done)=>createProviderErrorScreen(tui,done,load.error));return}await ctx.ui.custom((tui,theme2,keybindings,done)=>createProviderApp(tui,theme2,keybindings,done,{store:load.store,runtime:ctx.modelRuntime,registry:ctx.modelRegistry,getCurrentModel:()=>ctx.model,setModel:model=>pi.setModel(model),notify:(message,type)=>ctx.ui.notify(message,type),initialProviderId:args.trim()||void 0}))}catch(error){ctx.ui.notify(formatError2(error),"error")}}})}var QUESTION_TOOL_NAME="question",QUESTION_LABEL="Question",QUESTION_DESCRIPTION="Ask the user 1-4 structured multiple-choice questions and return their selections. Never author an 'Other'-style option or a vague label like 'Option A' \u2014 the UI adds a custom-answer path itself. If you recommend an option, put it first and append ' (Recommended)' to its label.",QUESTION_PROMPT_SNIPPET="Ask the user structured multiple-choice questions when blocked on a decision only they can make",QUESTION_PROMPT_GUIDELINES=["Use `question` only for decisions you cannot resolve from the request, the code, or sensible defaults (direction, preference, permissions, destructive choices); for everything else choose a reasonable default and state it.","Batch related decisions into one `question` call (1-4 questions); ask no more than needed to unblock the next step.","Treat `question` answers as decisions: act on them without re-litigating, and do not re-ask unless circumstances change."];
|
|
2049
|
+
Fix the file manually and open /provider again.`})}function createProviderApp(tui,theme2,keybindings,done,options){let{store,registry,runtime}=options,session=new ProviderTuiSession(tui),refresher=new RefreshCoordinator(runtime),activeEditor,closing;function notify(message,type){session.signal.aborted||options.notify(message,type)}store.onSaveResult=result2=>{session.signal.aborted||((result2.kind==="invalid"||result2.kind==="error")&¬ify(result2.error,"error"),activeEditor?.syncFromStore(),tui.requestRender())};function showList(){session.signal.aborted||(activeEditor=void 0,session.setScreen(new ProviderListScreen(tui,theme2,keybindings,result2=>{result2.kind==="close"?requestClose():openProvider(result2.providerId)},store)))}function openProvider(providerId){if(!store.getProviderIds().includes(providerId)){notify(`No provider ${JSON.stringify(providerId)} in models.json.`,"warning"),showList();return}activeEditor=new ProviderEditorScreen(tui,theme2,keybindings,showList,{store,refresher,providerId,registry,runtime,currentModel:options.getCurrentModel(),notify}),session.setScreen(activeEditor)}function showUnsaved(error){let back="Return to providers",retry="Retry saving",discard3="Discard unsaved changes and close";session.setScreen(new ExtensionSelectorComponent("Some changes are not saved",[back,retry,discard3],choice=>{if(choice===back){showList();return}choice===retry&&store.retrySave(),choice===discard3&&store.discardPending(),requestClose()},showList,{tui,description:truncate3(error,2400)}))}function requestClose(){if(closing||session.signal.aborted)return;let controller=new AbortController;closing=controller;let signal=AbortSignal.any([session.signal,controller.signal]);activeEditor=void 0,session.setScreen(new SavingScreen(theme2,keybindings,()=>{controller.abort(),closing=void 0,showList()})),finishClose(controller,signal)}async function finishClose(controller,signal){try{if(await store.flush(),signal.aborted)return;let unsaved=store.getPendingError();if(unsaved){closing=void 0,showUnsaved(unsaved);return}let outcome=await refresher.flush(signal);if(signal.aborted)return;outcome.ok||notify(`Changes saved, but model refresh failed: ${outcome.errors.join("; ")}`,"warning");let current=options.getCurrentModel();if(current&&refresher.touchedProviders.includes(current.provider)){let refreshed=registry.find(current.provider,current.id);refreshed&&!await options.setModel(refreshed)&¬ify("Reselect the current model with /model to apply its updated configuration.","warning"),refreshed||notify("The current model is no longer available; select another with /model.","warning")}signal.aborted||done()}catch(error){signal.aborted||(notify(formatError2(error),"error"),showList())}finally{closing===controller&&(closing=void 0)}}return options.initialProviderId?openProvider(options.initialProviderId):showList(),session}function providerExtension(pi){let modelsPath;pi.on("session_start",(_event,ctx)=>{modelsPath=ctx.modelRuntime.getModelsPath()}),pi.registerCommand(COMMAND_NAME,{description:COMMAND_DESCRIPTION,getArgumentCompletions:async prefix=>{if(!modelsPath)return null;let load=await ModelsJsonStore.load(modelsPath);if(!load.ok)return null;let query=prefix.trim().toLowerCase(),items=load.store.getProviderIds().filter(id=>id.toLowerCase().startsWith(query)).map(id=>{let count=load.store.getModels(id).length;return{value:id,label:id,description:`${String(count)} ${plural(count,"model")}`}});return items.length?items:null},handler:async(args,ctx)=>{if(!ctx.hasUI||ctx.mode!=="tui"){ctx.ui.notify(NO_UI_WARNING,"warning");return}let path14=ctx.modelRuntime.getModelsPath();if(modelsPath=path14,!path14){ctx.ui.notify(NO_MODELS_FILE_WARNING,"warning");return}try{let load=await ModelsJsonStore.load(path14);if(!load.ok){await ctx.ui.custom((tui,_theme,_keybindings,done)=>createProviderErrorScreen(tui,done,load.error));return}await ctx.ui.custom((tui,theme2,keybindings,done)=>createProviderApp(tui,theme2,keybindings,done,{store:load.store,runtime:ctx.modelRuntime,registry:ctx.modelRegistry,getCurrentModel:()=>ctx.model,setModel:model=>pi.setModel(model),notify:(message,type)=>ctx.ui.notify(message,type),initialProviderId:args.trim()||void 0}))}catch(error){ctx.ui.notify(formatError2(error),"error")}}})}var QUESTION_TOOL_NAME="question",QUESTION_LABEL="Question",QUESTION_DESCRIPTION="Ask the user 1-4 structured multiple-choice questions and return their selections. Never author an 'Other'-style option or a vague label like 'Option A' \u2014 the UI adds a custom-answer path itself. If you recommend an option, put it first and append ' (Recommended)' to its label.",QUESTION_PROMPT_SNIPPET="Ask the user structured multiple-choice questions when blocked on a decision only they can make",QUESTION_PROMPT_GUIDELINES=["Use `question` only for decisions you cannot resolve from the request, the code, or sensible defaults (direction, preference, permissions, destructive choices); for everything else choose a reasonable default and state it.","Batch related decisions into one `question` call (1-4 questions); ask no more than needed to unblock the next step.","Treat `question` answers as decisions: act on them without re-litigating, and do not re-ask unless circumstances change."];var DetailPane=class{constructor(){this.key="",this.offset=0,this.maxOffset=0,this.pageRows=1,this.pendingPages=0}reset(){this.key="",this.offset=0,this.maxOffset=0,this.pendingPages=0}page(key,direction){this.key!==key&&this.reset(),this.key=key,this.pendingPages+=direction}render(key,title,content,width,rows,scrollHint,theme2){this.key!==key&&(this.reset(),this.key=key);let bodyRows=Math.max(1,rows-2),wasAtEnd=this.maxOffset>0&&this.offset===this.maxOffset;this.maxOffset=Math.max(0,content.length-bodyRows),this.pageRows=Math.max(1,bodyRows-1);let anchored2=wasAtEnd?this.maxOffset:this.offset;this.offset=Math.max(0,Math.min(this.maxOffset,anchored2+this.pendingPages*this.pageRows)),this.pendingPages=0;let body2=content.slice(this.offset,this.offset+bodyRows);if(rows<3)return body2.slice(0,rows);let lines=[theme2.fg("muted",truncateToWidth(` ${title.replace(/\s+/gu," ")}`,width)),...body2];if(this.maxOffset>0){for(;lines.length<rows-1;)lines.push("");let range2=`${this.offset+1}\u2013${this.offset+body2.length}/${content.length}`;lines.push(theme2.fg("dim",truncateToWidth(` ${range2}${scrollHint?` \u2022 ${scrollHint}`:""}`,width)))}return lines}};function ruleBorder(theme2,width,color2="accent"){return theme2.fg(color2,"\u2500".repeat(Math.max(0,width)))}function wrapWithPrefix(prefix,text2,width,outputLines){let prefixWidth=visibleWidth(prefix);if(prefixWidth>=width){for(let line of wrapTextWithAnsi(prefix+text2,width))outputLines.push(line);return}let wrappedLines=wrapTextWithAnsi(text2,width-prefixWidth),continuationPrefix=" ".repeat(prefixWidth);for(let lineIndex=0;lineIndex<wrappedLines.length;lineIndex++)outputLines.push(`${lineIndex===0?prefix:continuationPrefix}${wrappedLines[lineIndex]}`)}function moreOptionsHint(direction,count){let arrow=direction==="up"?"\u2191":"\u2193";return count<=0?`${arrow} more ${direction==="up"?"above":"below"}`:`${arrow} ${count} more option${count===1?"":"s"}`}function windowItems(items,focus,rows){let count=items.length,total=items.reduce((sum,item)=>sum+item.height,0),build=(first,last,contentRows)=>({first,last,contentRows,showAbove:first>0,showBelow:last<count-1,hiddenAbove:items.slice(0,first).filter(item=>item.countsAsOption).length,hiddenBelow:items.slice(last+1).filter(item=>item.countsAsOption).length});if(total<=rows)return build(0,count-1,rows);let windowFor=contentRows=>{let first=focus,last=focus,used=items[focus].height;for(let grew=!0;grew;)grew=!1,last+1<count&&used+items[last+1].height<=contentRows&&(last++,used+=items[last].height,grew=!0),first>0&&used+items[first-1].height<=contentRows&&(first--,used+=items[first].height,grew=!0);return build(first,last,contentRows)};if(rows<=2)return{...windowFor(Math.max(1,rows)),showAbove:!1,showBelow:!1};let window2=windowFor(rows-2);return window2.first===0||window2.last===count-1?windowFor(rows-1):window2}var PreviewLinesCache=class{constructor(){this.cache=new Map}get(previewText,width,compute){let byWidth=this.cache.get(previewText);byWidth||(byWidth=new Map,this.cache.set(previewText,byWidth));let lines=byWidth.get(width);return lines||(lines=compute(),byWidth.set(width,lines)),lines}},WidthCachedRender=class{invalidate(){this.cachedLines=void 0}get(width,height,compute){return this.cachedLines!==void 0&&this.cachedWidth===width&&this.cachedHeight===height?this.cachedLines:(this.cachedLines=compute(width,height),this.cachedWidth=width,this.cachedHeight=height,this.cachedLines)}};var QUESTION_LIMITS={questionChars:400,headerChars:32,optionLabelChars:80,optionDescriptionChars:300,previewChars:8e3,userTextChars:4e3,modelResultChars:12e3},TRUNCATION_FOLLOW_UP="Ask the user a focused follow-up question to clarify the omitted portion.";var DECLINE_MESSAGE="User declined to answer the questions.",CLARIFICATION_MESSAGE="The user wants to discuss these questions before choosing an answer.",ENVELOPE_PREFIX="User decisions:",ENVELOPE_SUFFIX="Continue with these decisions in mind.",CLARIFICATION_FOLLOW_UP="Explain the trade-offs or ask what the user would like clarified.",SHORTENED_NOTICE=`
|
|
2071
2050
|
|
|
2072
2051
|
[Long answers or notes were shortened where marked "chars truncated". ${TRUNCATION_FOLLOW_UP}]`;function buildToolResult(text2,details){return{content:[{type:"text",text:text2}],details}}function fairShare(lengths,budget){let sorted=[...lengths].sort((a,b2)=>a-b2),remaining=budget;for(let index3=0;index3<sorted.length;index3++){let share=Math.floor(remaining/(sorted.length-index3));if(sorted[index3]>share)return Math.max(0,share);remaining-=sorted[index3]}return Number.POSITIVE_INFINITY}function shorten(text2,cap){if(text2.length<=cap)return text2;let marker=`\u2026${text2.length} chars truncated\u2026`;return truncateMiddle(text2,Math.max(0,cap-marker.length)).content}function boundedAnswers(answers,envelope){let full=envelope(answers.map(answer=>answerSegment(answer,text2=>text2)).join(`
|
|
2073
2052
|
|
|
@@ -2211,7 +2190,34 @@ ${lines.join(`
|
|
|
2211
2190
|
|
|
2212
2191
|
${blocks.join(`
|
|
2213
2192
|
|
|
2214
|
-
`)}`).content}function search(pi){pi.registerTool({name:"code_search",label:"Code Search",description:"Find where behavior lives in the local repository from a description of it. Returns candidate files with line ranges.",promptSnippet:"Find code by describing its behavior",promptGuidelines:["Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.","Read the returned ranges before editing; the locations are candidates, not answers."],parameters:CodeSearchParams,renderCall:renderCodeSearchCall,renderResult:renderCodeSearchResult,async execute(_toolCallId,params,signal,onUpdate,ctx){let root=resolve17(ctx.cwd,params.path??".");if(!isInside(ctx.cwd,root))throw new Error(`path must be inside the working directory (${ctx.cwd}).`);let locations=await withDevin(apiKey=>codeSearch({apiKey,query:params.query.trim(),root,cwd:ctx.cwd,signal,onProgress:text2=>onUpdate?.({content:[{type:"text",text:text2}],details:{locations:[]}})}));return{content:[{type:"text",text:formatLocations(locations)}],details:{locations}}}});let currentMonth=new Date().toLocaleDateString("en-US",{month:"long",year:"numeric"});pi.registerTool({name:"web_search",label:"Web Search",description:"Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.",promptSnippet:"Search the live web for current information",promptGuidelines:["Use `web_search` for information beyond your knowledge cutoff.",`It is ${currentMonth}; put this year in \`web_search\` queries for recent releases, versions, or events, not the year your training data suggests.`,"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL)."],parameters:WebSearchParams,renderCall:renderWebSearchCall,renderResult:renderWebSearchResult,async execute(_toolCallId,params,signal){let query=params.query.trim(),results=await withDevin(apiKey=>webSearch(apiKey,query,params.max_results??5,signal));return{content:[{type:"text",text:formatWebResults(query,results)}],details:{results:results.map(({url,title})=>({url,title}))}}}}),registerSearchCommand(pi),pi.on("session_start",async()=>syncTools(pi))}var CONTEXT_WARNING_PERCENT=40,CONTEXT_ERROR_PERCENT=80,MIN_GAP=1;function formatWorkingDirectory(cwd,home){let homeDirectory=home.replace(/[\\/]+$/,"");if(!homeDirectory)return cwd;let normalizePath3=filePath=>filePath.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase(),normalizedHomeDirectory=normalizePath3(homeDirectory),normalizedCwd=normalizePath3(cwd);return normalizedCwd===normalizedHomeDirectory?"~":normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)?`~${cwd.slice(homeDirectory.length).replace(/\\/g,"/")}`:cwd}function pathBasename(displayPath2){let normalized=displayPath2.replace(/\\/g,"/").replace(/\/+$/,"");if(!normalized||normalized==="~")return normalized||displayPath2;let slash=normalized.lastIndexOf("/");if(slash<0)return normalized;let base=normalized.slice(slash+1);return normalized.startsWith("~/")?`~/${base}`:base}function formatTokenCount2(count){return count<1e3?`${count}`:count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function joinSegments(segments,separator){return segments.filter(Boolean).join(separator)}function formatContextUsage(data,theme2){let contextWindow=data.contextUsage?.contextWindow??data.model?.contextWindow,suffix=contextWindow?`/${formatTokenCount2(contextWindow)}`:"",percent=data.contextUsage?.percent,label=`CTX ${percent==null?"?":percent.toFixed(1)}%${suffix}`;return percent!=null&&percent>CONTEXT_ERROR_PERCENT?theme2.fg("error",label):percent!=null&&percent>CONTEXT_WARNING_PERCENT?theme2.fg("warning",label):theme2.fg("accent",label)}function formatUsageCandidates(summary,subscription,theme2){let tokens2=[summary.input>0?`\u2191${formatTokenCount2(summary.input)}`:"",summary.output>0?`\u2193${formatTokenCount2(summary.output)}`:""],read=summary.cacheRead>0?`R${formatTokenCount2(summary.cacheRead)}`:"",write=summary.cacheWrite>0?`W${formatTokenCount2(summary.cacheWrite)}`:"",suffix=[summary.latestCacheHitPercent===void 0?"":`CH${summary.latestCacheHitPercent.toFixed(1)}%`,summary.cost>0?`$${summary.cost.toFixed(3)}${subscription?" (sub)":""}`:""],candidates=[[read,write],[read],[]].map(cache=>joinSegments([...tokens2,...cache,...suffix]," "));return[...new Set(candidates.filter(Boolean))].map(text2=>theme2.fg("dim",text2))}function formatExtensionStatuses(statuses,theme2){return[...statuses.entries()].sort(([first],[second])=>first.localeCompare(second)).map(([,text2])=>text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()).filter(Boolean).map(text2=>text2.includes("\x1B[")?text2:theme2.fg("muted",text2)).join(" ")}function fitsLeftRight(left,right,width){return visibleWidth(left)+visibleWidth(right)+(left&&right?MIN_GAP:0)<=width}function layoutLeftRight(left,right,width,ellipsis){if(width<=0)return"";if(!right)return truncateToWidth(left,width,ellipsis);let rightWidth=visibleWidth(right);if(!left)return`${" ".repeat(Math.max(0,width-rightWidth))}${truncateToWidth(right,width,ellipsis)}`;let leftWidth=visibleWidth(left);if(leftWidth+rightWidth+MIN_GAP>width){let maxRightWidth=Math.min(rightWidth,Math.max(8,Math.floor(width*.45)));right=truncateToWidth(right,maxRightWidth,ellipsis),rightWidth=visibleWidth(right);let maxLeftWidth=width-rightWidth-MIN_GAP;if(maxLeftWidth<1)return truncateToWidth(right,width,ellipsis);left=truncateToWidth(left,maxLeftWidth,ellipsis),leftWidth=visibleWidth(left)}return`${left}${" ".repeat(Math.max(MIN_GAP,width-leftWidth-rightWidth))}${right}`}function layoutSecondaryLine(left,status,right,width,ellipsis){let leftWidth=visibleWidth(left),statusWidth=visibleWidth(status),rightWidth=visibleWidth(right),free=width-leftWidth-statusWidth-rightWidth;if(!status||free<MIN_GAP*2)return layoutLeftRight(left,right,width,ellipsis);let leftPad=Math.floor((width-statusWidth)/2)-leftWidth;return(leftPad<MIN_GAP||free-leftPad<MIN_GAP)&&(leftPad=Math.floor(free/2)),`${left}${" ".repeat(leftPad)}${status}${" ".repeat(free-leftPad)}${right}`}function renderPrimaryLine(data,theme2,width,ellipsis){let{model,thinkingLevel}=data,name=theme2.fg("toolTitle",theme2.bold(model?.name??model?.id??"no-model")),provider=model?.provider?theme2.fg("muted",`(${model.provider})`):"",effort=model?.reasoning&&thinkingLevel!=="off"?theme2.getThinkingBorderColor(thinkingLevel)(thinkingLevel):"",separator=theme2.fg("dim"," \xB7 "),rich=joinSegments([joinSegments([name,provider]," "),effort],separator),plain=joinSegments([name,effort],separator),cwd=formatWorkingDirectory(data.cwd,data.home),full=theme2.fg("success",cwd),short=theme2.fg("success",pathBasename(cwd)),branch=data.gitBranch?theme2.fg("accent",data.gitBranch):"",chosen=[{left:rich,right:joinSegments([full,branch],separator)},{left:rich,right:full},{left:rich,right:joinSegments([short,branch],separator)},{left:rich,right:short},{left:plain,right:joinSegments([short,branch],separator)},{left:plain,right:short},{left:plain,right:""}].find(({left,right})=>fitsLeftRight(left,right,width))??{left:plain,right:short};return layoutLeftRight(chosen.left,chosen.right,width,ellipsis)}function renderStatusline(data,theme2,width){let ellipsis=theme2.fg("dim","..."),primary=renderPrimaryLine(data,theme2,width,ellipsis),context=formatContextUsage(data,theme2),status=formatExtensionStatuses(data.statuses,theme2),candidates=formatUsageCandidates(data.usage,data.usesSubscription,theme2),usage=candidates.find(candidate=>fitsLeftRight(context,candidate,width)),secondary=candidates.length>0&&usage===void 0?layoutLeftRight(context,candidates[0],width,ellipsis):layoutSecondaryLine(context,status,usage??"",width,ellipsis);return[primary,secondary]}var BranchUsage=class{invalidate(){this.cached=void 0}read(manager){let sessionId=manager.getSessionId(),leafId=manager.getLeafId();if(this.cached?.manager===manager&&this.cached.sessionId===sessionId&&this.cached.leafId===leafId)return this.cached.usage;let entries=manager.getBranch(),totals=createUsageTotals();for(let usage2 of getAccountedUsages(entries))addUsageToTotals(totals,usage2);let latestCacheHitPercent;for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type!=="message"||entry.message.role!=="assistant")continue;let{input:input2,cacheRead,cacheWrite}=entry.message.usage,promptTokens=input2+cacheRead+cacheWrite;(cacheRead>0||cacheWrite>0)&&promptTokens>0&&(latestCacheHitPercent=cacheRead/promptTokens*100);break}let usage={...totals,latestCacheHitPercent};return this.cached={manager,sessionId,leafId,usage},usage}};function statusline(pi){pi.on("session_start",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter((tui,theme2,footerData)=>{let usage=new BranchUsage;return{dispose:footerData.onBranchChange(()=>tui.requestRender()),invalidate(){usage.invalidate()},render(width){let model=ctx.model;return renderStatusline({model,thinkingLevel:ctx.thinkingLevel??"off",cwd:ctx.cwd,home:process.env.USERPROFILE||process.env.HOME||"",gitBranch:footerData.getGitBranch(),contextUsage:ctx.getContextUsage(),usage:usage.read(ctx.sessionManager),usesSubscription:model?ctx.modelRegistry.isUsingOAuth(model):!1,statuses:footerData.getExtensionStatuses()},theme2,width)}}})}),pi.on("session_shutdown",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter(void 0)})}var builtInExtensions=[{name:"codemode",factory:codemode_default,replaceable:!0,builtin:!0},{name:"mcp",factory:mcp_default,replaceable:!0,builtin:!0},{name:"tool-search",factory:tool_search_default,replaceable:!0,builtin:!0},{name:"cached-compaction",factory:cachedCompaction,replaceable:!0,builtin:!0},{name:"llama.cpp",factory:llamaExtension,builtin:!0},{name:"btw",factory:btwExtension,builtin:!0},{name:"deepwiki",factory:deepwiki,builtin:!0},{name:"provider",factory:providerExtension,builtin:!0},{name:"question",factory:question,builtin:!0},{name:"statusline",factory:statusline,builtin:!0},{name:"search",factory:search,builtin:!0}];var cli_exports={};__export(cli_exports,{runMcpCommand:()=>runMcpCommand});import{existsSync as existsSync26}from"node:fs";import{join as join47}from"node:path";import{createInterface as createInterface5}from"node:readline/promises";var HELP=`${source_default.bold("Usage:")}
|
|
2193
|
+
`)}`).content}function search(pi){pi.registerTool({name:"code_search",label:"Code Search",description:"Find where behavior lives in the local repository from a description of it. Returns candidate files with line ranges.",promptSnippet:"Find code by describing its behavior",promptGuidelines:["Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.","Read the returned ranges before editing; the locations are candidates, not answers."],parameters:CodeSearchParams,renderCall:renderCodeSearchCall,renderResult:renderCodeSearchResult,async execute(_toolCallId,params,signal,onUpdate,ctx){let root=resolve17(ctx.cwd,params.path??".");if(!isInside(ctx.cwd,root))throw new Error(`path must be inside the working directory (${ctx.cwd}).`);let locations=await withDevin(apiKey=>codeSearch({apiKey,query:params.query.trim(),root,cwd:ctx.cwd,signal,onProgress:text2=>onUpdate?.({content:[{type:"text",text:text2}],details:{locations:[]}})}));return{content:[{type:"text",text:formatLocations(locations)}],details:{locations}}}});let currentMonth=new Date().toLocaleDateString("en-US",{month:"long",year:"numeric"});pi.registerTool({name:"web_search",label:"Web Search",description:"Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.",promptSnippet:"Search the live web for current information",promptGuidelines:["Use `web_search` for information beyond your knowledge cutoff.",`It is ${currentMonth}; put this year in \`web_search\` queries for recent releases, versions, or events, not the year your training data suggests.`,"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL)."],parameters:WebSearchParams,renderCall:renderWebSearchCall,renderResult:renderWebSearchResult,async execute(_toolCallId,params,signal){let query=params.query.trim(),results=await withDevin(apiKey=>webSearch(apiKey,query,params.max_results??5,signal));return{content:[{type:"text",text:formatWebResults(query,results)}],details:{results:results.map(({url,title})=>({url,title}))}}}}),registerSearchCommand(pi),pi.on("session_start",async()=>syncTools(pi))}var CONTEXT_WARNING_PERCENT=40,CONTEXT_ERROR_PERCENT=80,MIN_GAP=1;function formatWorkingDirectory(cwd,home){let homeDirectory=home.replace(/[\\/]+$/,"");if(!homeDirectory)return cwd;let normalizePath3=filePath=>filePath.replace(/\\/g,"/").replace(/\/+$/,"").toLowerCase(),normalizedHomeDirectory=normalizePath3(homeDirectory),normalizedCwd=normalizePath3(cwd);return normalizedCwd===normalizedHomeDirectory?"~":normalizedCwd.startsWith(`${normalizedHomeDirectory}/`)?`~${cwd.slice(homeDirectory.length).replace(/\\/g,"/")}`:cwd}function pathBasename(displayPath2){let normalized=displayPath2.replace(/\\/g,"/").replace(/\/+$/,"");if(!normalized||normalized==="~")return normalized||displayPath2;let slash=normalized.lastIndexOf("/");if(slash<0)return normalized;let base=normalized.slice(slash+1);return normalized.startsWith("~/")?`~/${base}`:base}function formatTokenCount2(count){return count<1e3?`${count}`:count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function joinSegments(segments,separator){return segments.filter(Boolean).join(separator)}function formatContextUsage(data,theme2){let contextWindow=data.contextUsage?.contextWindow??data.model?.contextWindow,suffix=contextWindow?`/${formatTokenCount2(contextWindow)}`:"",percent=data.contextUsage?.percent,label=`CTX ${percent==null?"?":percent.toFixed(1)}%${suffix}`;return percent!=null&&percent>CONTEXT_ERROR_PERCENT?theme2.fg("error",label):percent!=null&&percent>CONTEXT_WARNING_PERCENT?theme2.fg("warning",label):theme2.fg("accent",label)}function formatUsageCandidates(summary,subscription,theme2){let tokens2=[summary.input>0?`\u2191${formatTokenCount2(summary.input)}`:"",summary.output>0?`\u2193${formatTokenCount2(summary.output)}`:""],read=summary.cacheRead>0?`R${formatTokenCount2(summary.cacheRead)}`:"",write=summary.cacheWrite>0?`W${formatTokenCount2(summary.cacheWrite)}`:"",suffix=[summary.latestCacheHitPercent===void 0?"":`CH${summary.latestCacheHitPercent.toFixed(1)}%`,summary.cost>0?`$${summary.cost.toFixed(3)}${subscription?" (sub)":""}`:""],candidates=[[read,write],[read],[]].map(cache=>joinSegments([...tokens2,...cache,...suffix]," "));return[...new Set(candidates.filter(Boolean))].map(text2=>theme2.fg("dim",text2))}function formatExtensionStatuses(statuses,theme2){return[...statuses.entries()].sort(([first],[second])=>first.localeCompare(second)).map(([,text2])=>text2.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()).filter(Boolean).map(text2=>text2.includes("\x1B[")?text2:theme2.fg("muted",text2)).join(" ")}function fitsLeftRight(left,right,width){return visibleWidth(left)+visibleWidth(right)+(left&&right?MIN_GAP:0)<=width}function layoutLeftRight(left,right,width,ellipsis){if(width<=0)return"";if(!right)return truncateToWidth(left,width,ellipsis);let rightWidth=visibleWidth(right);if(!left)return`${" ".repeat(Math.max(0,width-rightWidth))}${truncateToWidth(right,width,ellipsis)}`;let leftWidth=visibleWidth(left);if(leftWidth+rightWidth+MIN_GAP>width){let maxRightWidth=Math.min(rightWidth,Math.max(8,Math.floor(width*.45)));right=truncateToWidth(right,maxRightWidth,ellipsis),rightWidth=visibleWidth(right);let maxLeftWidth=width-rightWidth-MIN_GAP;if(maxLeftWidth<1)return truncateToWidth(right,width,ellipsis);left=truncateToWidth(left,maxLeftWidth,ellipsis),leftWidth=visibleWidth(left)}return`${left}${" ".repeat(Math.max(MIN_GAP,width-leftWidth-rightWidth))}${right}`}function layoutSecondaryLine(left,status,right,width,ellipsis){let leftWidth=visibleWidth(left),statusWidth=visibleWidth(status),rightWidth=visibleWidth(right),free=width-leftWidth-statusWidth-rightWidth;if(!status||free<MIN_GAP*2)return layoutLeftRight(left,right,width,ellipsis);let leftPad=Math.floor((width-statusWidth)/2)-leftWidth;return(leftPad<MIN_GAP||free-leftPad<MIN_GAP)&&(leftPad=Math.floor(free/2)),`${left}${" ".repeat(leftPad)}${status}${" ".repeat(free-leftPad)}${right}`}function renderPrimaryLine(data,theme2,width,ellipsis){let{model,thinkingLevel}=data,name=theme2.fg("toolTitle",theme2.bold(model?.name??model?.id??"no-model")),provider=model?.provider?theme2.fg("muted",`(${model.provider})`):"",effort=model?.reasoning&&thinkingLevel!=="off"?theme2.getThinkingBorderColor(thinkingLevel)(thinkingLevel):"",separator=theme2.fg("dim"," \xB7 "),rich=joinSegments([joinSegments([name,provider]," "),effort],separator),plain=joinSegments([name,effort],separator),cwd=formatWorkingDirectory(data.cwd,data.home),full=theme2.fg("success",cwd),short=theme2.fg("success",pathBasename(cwd)),branch=data.gitBranch?theme2.fg("accent",data.gitBranch):"",chosen=[{left:rich,right:joinSegments([full,branch],separator)},{left:rich,right:full},{left:rich,right:joinSegments([short,branch],separator)},{left:rich,right:short},{left:plain,right:joinSegments([short,branch],separator)},{left:plain,right:short},{left:plain,right:""}].find(({left,right})=>fitsLeftRight(left,right,width))??{left:plain,right:short};return layoutLeftRight(chosen.left,chosen.right,width,ellipsis)}function renderStatusline(data,theme2,width){let ellipsis=theme2.fg("dim","..."),primary=renderPrimaryLine(data,theme2,width,ellipsis),context=formatContextUsage(data,theme2),status=formatExtensionStatuses(data.statuses,theme2),candidates=formatUsageCandidates(data.usage,data.usesSubscription,theme2),usage=candidates.find(candidate=>fitsLeftRight(context,candidate,width)),secondary=candidates.length>0&&usage===void 0?layoutLeftRight(context,candidates[0],width,ellipsis):layoutSecondaryLine(context,status,usage??"",width,ellipsis);return[primary,secondary]}var BranchUsage=class{invalidate(){this.cached=void 0}read(manager){let sessionId=manager.getSessionId(),leafId=manager.getLeafId();if(this.cached?.manager===manager&&this.cached.sessionId===sessionId&&this.cached.leafId===leafId)return this.cached.usage;let entries=manager.getBranch(),totals=createUsageTotals();for(let usage2 of getAccountedUsages(entries))addUsageToTotals(totals,usage2);let latestCacheHitPercent;for(let index3=entries.length-1;index3>=0;index3--){let entry=entries[index3];if(entry.type!=="message"||entry.message.role!=="assistant")continue;let{input:input2,cacheRead,cacheWrite}=entry.message.usage,promptTokens=input2+cacheRead+cacheWrite;(cacheRead>0||cacheWrite>0)&&promptTokens>0&&(latestCacheHitPercent=cacheRead/promptTokens*100);break}let usage={...totals,latestCacheHitPercent};return this.cached={manager,sessionId,leafId,usage},usage}};function statusline(pi){pi.on("session_start",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter((tui,theme2,footerData)=>{let usage=new BranchUsage;return{dispose:footerData.onBranchChange(()=>tui.requestRender()),invalidate(){usage.invalidate()},render(width){let model=ctx.model;return renderStatusline({model,thinkingLevel:ctx.thinkingLevel??"off",cwd:ctx.cwd,home:process.env.USERPROFILE||process.env.HOME||"",gitBranch:footerData.getGitBranch(),contextUsage:ctx.getContextUsage(),usage:usage.read(ctx.sessionManager),usesSubscription:model?ctx.modelRegistry.isUsingOAuth(model):!1,statuses:footerData.getExtensionStatuses()},theme2,width)}}})}),pi.on("session_shutdown",(_event,ctx)=>{ctx.mode==="tui"&&ctx.ui.setFooter(void 0)})}function formatDuration2(ms){if(ms<500)return"<1s";let seconds=Math.round(ms/1e3);if(seconds<60)return`${seconds}s`;let minutes=Math.floor(seconds/60);if(minutes<60){let remainder2=seconds%60;return remainder2===0?`${minutes}m`:`${minutes}m ${remainder2}s`}let hours=Math.floor(minutes/60),remainder=minutes%60;return remainder===0?`${hours}h`:`${hours}h ${remainder}m`}function runtimeLabel(task,now=Date.now()){return formatDuration2((task.endedAt??now)-task.startedAt)}var TASKS_LOGS_DEFAULT_BYTES=8*1024,TASKS_LOGS_MIN_BYTES=256,TASKS_LIST_FINISHED_SHOWN=5,TASKS_WAIT_DELTA_BYTES=32*1024,TASKS_DETACH_HINT_DELAY_MS=1e4;var tasksSchema=typebox_exports.Object({action:StringEnum(["read","wait","kill","list"],{description:"Which task operation to perform"}),taskId:typebox_exports.Optional(typebox_exports.String({description:"Task execution id (read/wait/kill). Omit for wait to wait for any task running at call time."})),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(TASKS_LOGS_DEFAULT_BYTES)}, max ${formatSize(TASK_RESULT_BYTES)})`})),waitMs:typebox_exports.Optional(typebox_exports.Number({description:`Maximum wait window in ms (default ${formatDuration2(2e4)}, max ${formatDuration2(6e5)}). Only the wait ends on timeout; execution continues.`})),sinceBytes:typebox_exports.Optional(typebox_exports.Number({description:"Only return output written after this byte offset \u2014 use the 'next sinceBytes' value from a previous read or wait (wait with taskId only)"}))});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 value=bytes!==void 0&&Number.isFinite(bytes)?bytes:TASKS_LOGS_DEFAULT_BYTES;return Math.min(TASK_RESULT_BYTES,Math.max(TASKS_LOGS_MIN_BYTES,Math.floor(value)))}function clampWaitMs(waitMs){let value=waitMs!==void 0&&Number.isFinite(waitMs)?waitMs:2e4;return Math.min(6e5,Math.max(1e3,Math.floor(value)))}function clampSinceBytes(sinceBytes){return sinceBytes===void 0||!Number.isFinite(sinceBytes)?void 0:Math.max(0,Math.floor(sinceBytes))}var TASKS_TOOL_DESCRIPTION="Inspect and control background tasks started by native tools or extensions. 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: observe one task, or any task running at call time, for up to waitMs; no running tasks returns immediately. New steering input ends only the wait with outcome interrupted; it never stops the task. kill: request cancellation of a whole task. tasks cannot start work; submit background work through its owning tool. A wait ends as settled, interrupted, timed_out, or no_tasks. Timeout or cancellation ends only the wait, never execution. Reads and settled waits report byte ranges; use next sinceBytes only with that task's ID. Output is capped at 50KB per response.",TASKS_PROMPT_SNIPPET="Manage background tasks; wait for a specific task or any running task",TASKS_PROMPT_GUIDELINES=["Start background work through its owning tool with background: true; continue independent work while it runs.","A finished background task delivers its result automatically as a notification. Use tasks wait only when your next step is blocked: provide taskId for one task or omit it for any task running at call time; never sleep-poll with repeated reads.","A new steering message interrupts only an active tasks wait so you can read the new input; it does not cancel execution. A wait timeout is not a task failure."];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?`
|
|
2194
|
+
${omitted} foreground ${omitted===1?"execution":"executions"} omitted \u2014 foreground work is delivered inline in the transcript.`:""}function lookupFailure(background,id,error){if(!(error instanceof TaskLookupError))return error instanceof Error?error:new Error(String(error));if(error.kind==="ambiguous"){let lines2=error.matches.map(task=>describeTaskLine(task)).join(`
|
|
2195
|
+
`);return new Error(`Ambiguous task ID "${id}" matches ${error.matches.length} tasks:
|
|
2196
|
+
${lines2}`)}let{tasks,foregroundOmitted}=listedTasks(background),active=tasks.filter(task=>!isTaskTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isTaskTerminal(task.status))),shown=[...active,...finished].slice(0,LOOKUP_LIST_LIMIT);if(shown.length===0)return new Error(`No task "${id}" in this session. No background tasks in this session.`);let lines=shown.map(task=>describeTaskLine(task)).join(`
|
|
2197
|
+
`);return new Error(`No task "${id}" in this session. IDs from other sessions are not valid here.
|
|
2198
|
+
Current background tasks:
|
|
2199
|
+
${lines}${foregroundOmissionNote(foregroundOmitted)}`)}function rangeText(slice,sinceBytes){let from=slice.fromByte??0,to=from+Buffer.byteLength(slice.text),floor=sinceBytes===void 0||sinceBytes>slice.totalBytes?0:sinceBytes;return[`bytes ${from}\u2013${to} of ${slice.totalBytes}`,sinceBytes!==void 0&&from>floor?`skipped ${from-floor} bytes after sinceBytes ${floor}`:"",`next sinceBytes ${to}`].filter(Boolean).join(" \xB7 ")}function readText(header2,slice){let boundedField=(text2,maxBytes)=>truncateHead(boundText(sanitizeBinaryOutput(text2),maxBytes),{maxBytes,maxLines:100}).content;return[boundedField(header2,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(`
|
|
2200
|
+
`)}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 ${rangeText(slice)}]`,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)}}function activeBackgroundTasks(background){return background.list().filter(task=>task.mode==="background"&&!isTaskTerminal(task.status))}function stillRunningText(tasks){return tasks.length>0?`
|
|
2201
|
+
|
|
2202
|
+
[still_running]
|
|
2203
|
+
${tasks.map(task=>describeTaskLine(task)).join(`
|
|
2204
|
+
`)}`:""}function emptyWaitDetails(outcome,waitedMs,running){return{action:"wait",outcome,timedOut:outcome==="timed_out",exitCode:void 0,waitedMs,deltaBytes:0,totalBytes:0,deltaTruncated:!1,outputPath:"",running}}async function runWaitAny(background,input2,signal,onReady,interruptSignal){let candidates=activeBackgroundTasks(background);if(candidates.length===0)return result("No background tasks are running, so there is nothing to wait for. Finished tasks report back via automatic notification.",emptyWaitDetails("no_tasks",0,0));let releases=candidates.map(task=>background.holdDelivery(task.id)),start=Date.now();try{let task=await background.waitAny(clampWaitMs(input2.waitMs),signal,interruptSignal),ids=new Set(candidates.map(candidate=>candidate.id)),running=activeBackgroundTasks(background).filter(candidate=>ids.has(candidate.id));if(!task){let interrupted=!background.closed&&interruptSignal?.aborted===!0,outcome=interrupted?"interrupted":"timed_out",note=background.closed?"The host closed; execution state is unconfirmed.":interrupted?"New steering input ended this wait early. Read the new input before deciding what to do next; no task was stopped.":"The wait window expired; running tasks continue. Prefer other work over waiting again.";return result(`${note}${stillRunningText(running)}`,emptyWaitDetails(outcome,Date.now()-start,running.length))}let slice=await background.read(task.id,{bytes:TASKS_WAIT_DELTA_BYTES});return signal?.throwIfAborted(),onReady?.(task.id),result(`${readText(`[${describeTaskLine(task)} \xB7 waitAny settled \xB7 ${rangeText(slice)}]`,slice)}${stillRunningText(running)}`,{action:"wait",outcome:"settled",taskId:task.id,status:task.status,kind:task.kind,timedOut:!1,exitCode:task.exitCode,waitedMs:Date.now()-start,deltaBytes:Buffer.byteLength(slice.text),totalBytes:slice.totalBytes,deltaTruncated:slice.truncated,outputPath:task.outputPath??"",running:running.length})}finally{for(let release2 of releases)release2()}}async function runWait(background,input2,signal,onReady,interruptSignal){if(!input2.taskId?.trim()){if(input2.sinceBytes!==void 0)throw new Error("action 'wait' without 'taskId' does not accept 'sinceBytes'; offsets belong to one task.");return runWaitAny(background,input2,signal,onReady,interruptSignal)}let id=requireTaskId(input2);try{let release2=background.holdDelivery(id);try{let start=Date.now(),task=await background.wait(id,clampWaitMs(input2.waitMs),signal,interruptSignal),settled=isTaskTerminal(task.status),interrupted=!settled&&!background.closed&&interruptSignal?.aborted===!0,timedOut=!settled&&!interrupted,outcome=settled?"settled":interrupted?"interrupted":"timed_out",waitedMs=Date.now()-start;if(interrupted)return result(`[${describeTaskLine(task)} \xB7 interrupted by steering; execution continues]
|
|
2205
|
+
Read the new input before deciding whether to wait again; the task was not stopped.`,{action:"wait",outcome,taskId:task.id,status:task.status,kind:task.kind,timedOut:!1,exitCode:task.exitCode,waitedMs,deltaBytes:0,totalBytes:0,deltaTruncated:!1,outputPath:task.outputPath??""});let windowNote=background.closed?" \xB7 host closed; execution state unconfirmed":timedOut?" \xB7 wait window expired; execution continues":"",sinceBytes=clampSinceBytes(input2.sinceBytes),slice=await background.read(id,{bytes:TASKS_WAIT_DELTA_BYTES,sinceBytes});return signal?.throwIfAborted(),settled&&onReady?.(task.id),result(readText(`[${describeTaskLine(task)}${windowNote} \xB7 ${rangeText(slice,sinceBytes)}]`,slice),{action:"wait",outcome,taskId:task.id,status:task.status,kind:task.kind,timedOut,exitCode:task.exitCode,waitedMs,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=>!isTaskTerminal(task.status)),finished=recentFinishedFirst(tasks.filter(task=>isTaskTerminal(task.status))),shown=[...active,...finished.slice(0,TASKS_LIST_FINISHED_SHOWN)].slice(0,100),hidden=tasks.length-shown.length;return result(shown.length?`${shown.map(task=>describeTaskLine(task)).join(`
|
|
2206
|
+
`)}${hidden>0?`
|
|
2207
|
+
${hidden} more records not shown.`:""}${foregroundOmissionNote(foregroundOmitted)}`:`No background tasks. Start work through its owning tool with background: true.${foregroundOmissionNote(foregroundOmitted)}`,{action:"list",running:active.length,finished:finished.length,shown:shown.length,hidden,...foregroundOmitted>0?{foregroundOmitted}:{}})}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 frame3=Math.floor(now/STATUS_SPINNER_INTERVAL_MS)%STATUS_SPINNER_FRAMES.length;return STATUS_SPINNER_FRAMES[frame3]??STATUS_SPINNER_FRAMES[0]??"\xB7"}function statusMarker(status,opts){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"stopping":case"partial":case"aborted":return{glyph:"\u25CB",color:"warning"};case"queued":return{glyph:"\u25CB",color:"muted"};default:return{glyph:"\u2022",color:"muted"}}}function statusName(status){return status==="timeout"?"Timed out":status?status[0].toUpperCase()+status.slice(1):"Unknown"}function exitSuffix(exitCode,separator){return exitCode!=null?`${separator}exit ${exitCode}`:""}function statusGlyph(status){return statusMarker(status).glyph}function statusColor(status){return statusMarker(status).color}function cleanTaskText(text2){return sanitizeBinaryOutput(stripTerminalSequences(text2)).replace(/\r\n?/g,`
|
|
2208
|
+
`)}function firstCommandLine(command){return(command.split(/\r?\n/).find(candidate=>candidate.trim().length>0)??command).trim()}function fileNameOf(path14){return path14.replace(/\\/g,"/").split("/").at(-1)??path14}var RESULT_EXPAND_LIMIT=4e3,WAIT_REFRESH_MS=1e3;function scheduleWaitRefresh(context,pending){let state2=context.state;if(state2!==void 0){if(pending){state2.dispose=()=>scheduleWaitRefresh(context,!1),state2.refreshTimer===void 0&&(state2.refreshTimer=setTimeout(()=>{state2.refreshTimer=void 0,context.invalidate()},WAIT_REFRESH_MS),state2.refreshTimer.unref?.());return}state2.refreshTimer!==void 0&&(clearTimeout(state2.refreshTimer),state2.refreshTimer=void 0),state2.waitStartedAt=void 0}}function capForTranscript(text2,limit){return text2.length>limit?`\u2026${text2.slice(-limit)}`:text2}function renderTasksCall(args,theme2,context){switch(args.action){case"read":{let mode=args.mode??"tail",size=args.bytes!==void 0?` ${formatSize(args.bytes)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks read "))}${theme2.fg("accent",args.taskId??"")}${theme2.fg("muted",` ${mode}${size}`)}`,0,0)}case"wait":return renderWaitCall(args,theme2,context);case"kill":return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks kill "))}${theme2.fg("accent",args.taskId??"")}`,0,0);case"list":return new Text(theme2.fg("toolTitle",theme2.bold("tasks list")),0,0);default:{let action=typeof args.action=="string"?` ${theme2.fg("dim",args.action)}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks"))}${action}`,0,0)}}}function renderWaitCall(args,theme2,context){let taskId=typeof args.taskId=="string"?args.taskId.trim():"",pending=context.executionStarted===!0&&context.isPartial===!0&&context.state!==void 0;if(scheduleWaitRefresh(context,pending),!pending){let ms=args.waitMs!==void 0?` ${formatDuration2(clampWaitMs(args.waitMs))}`:"";return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks wait "))}${theme2.fg("accent",taskId||"any")}${theme2.fg("muted",ms)}`,0,0)}let state2=context.state;state2.waitStartedAt===void 0&&(state2.waitStartedAt=Date.now());let elapsed=`waiting ${formatDuration2(Date.now()-state2.waitStartedAt)} / ${formatDuration2(clampWaitMs(args.waitMs))}`;return new Text(`${theme2.fg("toolTitle",theme2.bold("tasks wait "))}${theme2.fg("accent",taskId||"any")} ${theme2.fg("muted",elapsed)}`,0,0)}function renderTasksResult(result2,options,theme2,context){context.args?.action==="wait"&&!options.isPartial&&scheduleWaitRefresh(context,!1);let details=result2.details,summary=details&&!context.isError?resultSummaryLine(details,theme2,options.expanded):void 0;if(summary===void 0){let text2=result2.content.find(part=>part.type==="text")?.text??"";return new Text(theme2.fg("toolOutput",text2.trimEnd()),0,0)}let container=new Container;if(container.addChild(new TruncatedText(summary,1,0)),options.expanded){let text2=result2.content.find(part=>part.type==="text")?.text??"";container.addChild(new Text("",0,0)),container.addChild(new Text(theme2.fg("toolOutput",capForTranscript(text2,RESULT_EXPAND_LIMIT).trimEnd()),1,0))}return container}function resultSummaryLine(details,theme2,expanded){let shownPath=path14=>expanded?path14:fileNameOf(path14);switch(details.action){case"read":{let size=details.sliceBytes!==details.totalBytes?`${details.mode} ${formatSize(details.sliceBytes)} of ${formatSize(details.totalBytes)}`:formatSize(details.totalBytes);return`${theme2.fg("muted","\u2192 ")}${theme2.fg("accent",details.taskId)}${theme2.fg("muted",`${details.status?` ${statusName(details.status)} \xB7`:""} ${size}${details.outputPath?` \xB7 ${shownPath(details.outputPath)}`:""}`)}`}case"wait":{let outcome=details.outcome??(details.timedOut?"timed_out":"settled");if(outcome==="no_tasks")return theme2.fg("muted","\u2192 No background tasks running");let taskId=details.taskId??"any";if(outcome==="interrupted"){let running=details.running?` \xB7 ${details.running} still running`:"";return`${theme2.fg(statusColor("cancelled"),statusGlyph("cancelled"))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` wait interrupted after ${formatDuration2(details.waitedMs)}${running}`)}`}if(outcome==="timed_out"){let status2=details.status??"running",running=details.taskId?formatSize(details.totalBytes):`${details.running??0} still running`;return`${theme2.fg(statusColor(status2),statusGlyph(status2))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` ${statusName(status2)} \xB7 wait ended after ${formatDuration2(details.waitedMs)} \xB7 ${running}`)}`}let status=details.status??"completed",exit=exitSuffix(details.exitCode,", ");return`${theme2.fg(statusColor(status),statusGlyph(status))} ${theme2.fg("accent",taskId)}${theme2.fg("muted",` ${statusName(status)}${exit} \xB7 waited ${formatDuration2(details.waitedMs)} \xB7 +${formatSize(details.deltaBytes)}`)}`}case"kill":{let status=details.status??(details.requested?"stopping":"cancelled");return`${theme2.fg(statusColor(status),statusGlyph(status))} ${theme2.fg("accent",details.taskId)}${theme2.fg("muted",` ${statusName(status)}${details.requested?" \xB7 cancellation requested":""}`)}`}case"list":{let hidden=details.hidden>0?` \xB7 ${details.hidden} more finished`:"",omitted=details.foregroundOmitted?` \xB7 ${details.foregroundOmitted} foreground omitted`:"";return theme2.fg("muted",`${details.running} running \xB7 ${details.finished} finished${hidden}${omitted}`)}default:return}}function createTasksToolDefinition(){return{name:"tasks",label:"tasks",description:TASKS_TOOL_DESCRIPTION,promptSnippet:TASKS_PROMPT_SNIPPET,promptGuidelines:TASKS_PROMPT_GUIDELINES,parameters:tasksSchema,constrainedSampling:{type:"json_schema",strict:"prefer"},async execute(_id,params,signal,_onUpdate,ctx){try{switch(params.action){case"read":return await runRead(ctx.tasks,params);case"wait":return await runWait(ctx.tasks,params,signal,taskId=>ctx.tasks.session?.prepareWait(_id,taskId),ctx.tasks.session?.waitInterruptSignal);case"kill":return runKill(ctx.tasks,params);case"list":return runList(ctx.tasks)}}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(boundedText(message))}},renderCall:renderTasksCall,renderResult:renderTasksResult}}var toolStyle={marker:{glyph:"\u25CF",color:{pending:"warning",success:"success",error:"error"}},rail:{glyph:"\u2502",color:"dim"},gap:{afterTool:0,afterMultilineTool:1,afterOther:1},collapsed:{headerOnly:new Set(["read","grep","find","ls"]),fallbackLines:10},fallbackArgsWidth:120};function toolStatus(state2){return state2.isPartial?"pending":state2.isError?"error":"success"}function toolMarkerColor(status){return toolStyle.marker.color[status]}function cellWidth(){return Math.max(visibleWidth(toolStyle.marker.glyph),visibleWidth(toolStyle.rail.glyph))}function gutterWidth(){return cellWidth()+1}function gutterCell(glyph,color2){return`${theme.fg(color2,glyph)}${" ".repeat(cellWidth()-visibleWidth(glyph)+1)}`}function isBlankLine(line){return line===""||stripAnsi(line).trim()===""}function dropLeadingBlankLines(lines){let start=0;for(;start<lines.length&&isBlankLine(lines[start]);)start++;return lines.slice(start)}var FramedComponent=class{constructor(component,kind,markerColor){this.component=component,this.kind=kind,this.markerColor=markerColor}render(width){let rendered=this.component.render(Math.max(1,width-gutterWidth())),lines=this.kind==="body"?dropLeadingBlankLines(rendered):rendered.length>1?[rendered[0],...dropLeadingBlankLines(rendered.slice(1))]:rendered;if(lines.length===0)return[];let rail=gutterCell(toolStyle.rail.glyph,toolStyle.rail.color),bareRail=theme.fg(toolStyle.rail.color,toolStyle.rail.glyph);return lines.map((line,index3)=>index3===0&&this.kind==="header"?`${gutterCell(toolStyle.marker.glyph,this.markerColor())}${line}`:isBlankLine(line)?bareRail:`${rail}${line}`)}invalidate(){this.component.invalidate()}};var SOURCE_LIMIT=64*1024,CARD_ROWS=128,OUTPUT_ROWS=20,SHELL_NAMES={bash:"Bash",powershell:"PowerShell"};function clean(text2){return sanitizeBinaryOutput(stripTerminalSequences(text2)).replace(/\r\n?/g,`
|
|
2209
|
+
`)}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?`
|
|
2210
|
+
`:""}${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=readTaskCompletion(message.details);if(!snapshot){let{text:text2,clipped}=savedText(message);return{body:text2,truncated:clipped}}return{title:clean(snapshot.title),duration:runtimeLabel(snapshot),kind:snapshot.kind,status:snapshot.status,id:clean(snapshot.taskId),exitCode:snapshot.exitCode,command:snapshot.command===void 0?void 0:clean(snapshot.command.text),cwd:snapshot.cwd===void 0?void 0:clean(snapshot.cwd),path:snapshot.outputPath===void 0?void 0:clean(snapshot.outputPath),diagnostic:snapshot.error===void 0?void 0:clean(snapshot.error),output:clean(snapshot.output.text),body:"",truncated:snapshot.output.truncated||snapshot.command?.truncated===!0}}function color(status){return status===void 0?"muted":statusMarker(status).color}function shortId(id){return id.replace(/^(.+)-([0-9a-f]{8})-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,"$1-$2")}var CompletionCard=class{constructor(view,options,theme2){this.view=view,this.options=options,this.theme=theme2}invalidate(){}render(width){return width<1?[]:new FramedComponent({render:contentWidth=>this.renderContent(contentWidth),invalidate(){}},"header",()=>color(this.view.status)).render(width).map(line=>truncateToWidth(line,width,""))}renderContent(width){if(!Number.isFinite(width)||width<1)return[];let view=this.view,theme2=this.theme,options=this.options,padding=Math.min(Math.max(0,Math.floor(options.outputPad||0)-1),Math.floor((width-1)/2)),inner=width-padding*2,indent=inner>=3?" ":"",bodyWidth=Math.max(1,inner-indent.length),lines=[],status=view.status?statusName(view.status):"Result received",kind=view.kind===void 0?"Notification":SHELL_NAMES[view.kind]??view.kind;lines.push(`${theme2.fg("toolTitle",theme2.bold(kind))}${theme2.fg("muted",` \xB7 Background ${status.toLowerCase()}${view.duration?` \xB7 ${view.duration}`:""}`)}${view.id?theme2.fg("dim",` \xB7 ${shortId(view.id)}`):""}`);let summary=view.command?`$ ${view.command.split(`
|
|
2211
|
+
`)[0]}`:view.title;if(!options.expanded)summary&&lines.push(theme2.fg("toolOutput",summary)),view.diagnostic&&lines.push(theme2.fg(color(view.status),view.diagnostic));else{view.truncated&&lines.push(theme2.fg("warning","The saved result is truncated; this is not the complete original output."));let section=(title,text2,limit,tail2=!1,error=!1)=>{lines.push("",theme2.fg("muted",theme2.bold(title)));let rendered=wrapTextWithAnsi(text2,bodyWidth).map(line=>theme2.fg(error?"error":"toolOutput",line)),omitted=Math.max(0,rendered.length-limit),selected=tail2?rendered.slice(-limit):rendered.slice(0,limit);tail2&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} earlier display lines omitted`));for(let line of selected)lines.push(indent+line);!tail2&&omitted&&lines.push(theme2.fg("dim",`${indent}\u2026 ${omitted} more display lines omitted`))};view.output===void 0?section("Details",view.body||"No text result.",36):(view.command?section("Command",view.command,8):view.title&§ion("Task",view.title,4),view.cwd&§ion("Directory",view.cwd,2),section(view.status==="failed"||view.status==="timeout"?"Error":"Result",`${view.diagnostic??status}${view.exitCode!==void 0?` \xB7 ${view.exitCode===null?"terminated by signal":`exit ${view.exitCode}`}`:""}`,4,!1,view.status==="failed"),section("Output",view.output.trim()?view.output:"No output.",OUTPUT_ROWS,!0),view.path&§ion("Log",view.path,4)),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."))}return(lines.length>CARD_ROWS?[...lines.slice(0,CARD_ROWS-1),theme2.fg("dim","\u2026 card shortened; use tasks read for retained output")]:lines).map(line=>" ".repeat(padding)+truncateToWidth(line,inner,"\u2026")+" ".repeat(padding))}};function renderTaskCompletion(message,options,theme2){let view;try{view=completionView(message)}catch{view={body:"The saved notification could not be interpreted. Its original message remains in session history.",truncated:!1}}return new CompletionCard(view,options,theme2)}var TaskViewport=class{constructor(follow=!1){this.scroll=0,this.entries=[],this.height=1,this.start=0,this.follow=follow}layout(lines,width,height){this.height=Math.max(1,height),(lines!==this.wrapped?.lines||width!==this.wrapped.width)&&(this.wrapped={lines,width},this.entries=lines.flatMap((line,index3)=>{let column=0;return wrapTextWithAnsi(line,Math.max(1,width)).map(text2=>{let entry={text:text2,line:index3,column};return column+=visibleWidth(text2),entry})}));let offset=this.scroll;if(this.anchor){let anchor=this.anchor,first=this.entries.findIndex(entry=>entry.line===anchor.line);if(first>=0)for(offset=first;offset+1<this.entries.length&&this.entries[offset+1].line===anchor.line&&this.entries[offset+1].column<=anchor.column;)offset++}return this.start=this.follow?this.max:Math.min(offset,this.max),this.entries.slice(this.start,this.start+this.height).map(entry=>entry.text)}get max(){return Math.max(0,this.entries.length-this.height)}move(direction,page,tail2){this.scroll=Math.max(0,Math.min(this.max,this.start+direction*(page?this.height:1)));let entry=this.entries[this.scroll];this.anchor=entry?{line:entry.line,column:entry.column}:void 0,this.follow=tail2&&direction>0&&this.scroll===this.max}jump(bottom,tail2){this.scroll=bottom?this.max:0;let entry=this.entries[this.scroll];this.anchor=entry?{line:entry.line,column:entry.column}:void 0,this.follow=bottom&&tail2}get range(){return`${this.entries.length?this.start+1:0}\u2013${Math.min(this.start+this.height,this.entries.length)}/${this.entries.length}`}};var SHELLS={bash:{name:"Bash",language:"bash"},powershell:{name:"PowerShell",language:"powershell"}};function taskLines(task,read,theme2){let shell=SHELLS[task.kind],command=cleanTaskText(task.command??task.title),[first="",...rest]=shell?highlightCode(command,shell.language):command.split(`
|
|
2212
|
+
`),info=[theme2.fg("accent",shell?.name??task.kind),`${task.command===void 0?"Title ":"Command "}${first}`,...rest,...task.commandTruncated?["[Saved command truncated.]"]:[],...task.cwd?[`Directory ${cleanTaskText(task.cwd)}`]:[],...task.outputPath?[`Log ${cleanTaskText(task.outputPath)}`]:[],...task.exitCode!==void 0?[`Exit ${task.exitCode??"signal"}`]:[]],saved=task.result?.content.filter(block=>block.type==="text").map(block=>block.text).join(`
|
|
2213
|
+
`),empty=task.status==="completed"?"Completed with no output.":isTaskTerminal(task.status)?"No saved output.":"No output yet.",output=cleanTaskText((read?read.text:saved)||empty).split(`
|
|
2214
|
+
`).map(line=>theme2.fg("toolOutput",line));return read?.readError&&output.unshift(theme2.fg("warning","Log unavailable; showing saved result.")),(!read||read.readError)&&task.resultTruncated&&output.push(theme2.fg("warning","Saved result truncated.")),{info,output}}var TaskInspector=class{constructor(options){this.positions=new Map,this.reading=!1,this.disposed=!1,this.options=options}get position(){let id=this.task?.id,position=id?this.positions.get(id):void 0;return position||(position={info:new TaskViewport,output:new TaskViewport(!0)},id&&this.positions.set(id,position)),position}select(task){if(!this.disposed){if(this.task?.id!==task?.id){let release2=task?this.options.host.retain(task.id):void 0,previous=this.release;this.release=release2,previous?.()}this.task=task}}prune(ids){for(let id of this.positions.keys())ids.has(id)||this.positions.delete(id)}invalidate(){this.cache=void 0}async refresh(){let task=this.task;if(this.disposed||!task||this.reading)return;let position=this.position;if(!(position.read&&(!position.output.follow||isTaskTerminal(position.read.task.status)))){this.reading=!0;try{let read=await this.options.host.read(task.id,{mode:"tail",bytes:49152});if(this.disposed||this.task?.id!==task.id||!position.output.follow&&position.read)return;position.read=read}catch(error){!this.disposed&&this.task?.id===task.id&&(position.output.follow||!position.read)&&(position.read={task,text:"",readError:`Cannot read output: ${cleanTaskText(String(error))}`,totalBytes:0,truncated:!1})}finally{this.reading=!1,this.disposed||this.options.requestRender(),!this.disposed&&this.task?.id!==task.id&&await this.refresh()}}}lines(tab){let task=this.task;if(!task)return[];let read=this.position.read;return(this.cache?.task!==task||this.cache.read!==read)&&(this.cache={task,read,lines:taskLines(task,read,this.options.theme)}),this.cache.lines[tab]}dispose(){this.disposed||(this.disposed=!0,this.release?.(),this.release=void 0,this.positions.clear())}};var pad=(text2,width)=>truncateToWidth(text2,Math.max(1,width),"\u2026",!0);function renderTasksLayout(options){let{width,height,theme:theme2,selection,inspector,list:list2,focus,keybindings}=options,hint=key=>keyLabel(key,{keybindings}),result2={hits:[],listWidth:0,listPageSize:1,lines:[]};if(width<1||height<1)return result2;let wide=width>=100,listWidth=wide?Math.min(42,Math.max(32,Math.floor(width*.32))):width,rightWidth=wide?width-listWidth-1:width,rightX=wide?listWidth+1:0,bodyHeight=height-5,hits=result2.hits;result2.listWidth=listWidth,result2.listPageSize=Math.max(1,Math.floor((bodyHeight-1)/2));let pane=(lines,size,active)=>{let border=text2=>theme2.fg(wide&&active?"borderAccent":"borderMuted",text2);return[border(`\u250C${"\u2500".repeat(size-2)}\u2510`),...lines.map(line=>border("\u2502")+pad(line,size-2)+border("\u2502")),border(`\u2514${"\u2500".repeat(size-2)}\u2518`)]};if(width<60||height<14){result2.tooSmall=!0;let message="Terminal too small for /tasks. Enlarge the window to continue.",close=`${hint("tui.select.cancel")} close`,boxWidth=Math.min(width,46),inner=boxWidth-2,wrapped=wrapTextWithAnsi(message,inner).map(line=>theme2.fg("warning",line)),spacious=[theme2.fg("text","Tasks"),"",...wrapped,"",theme2.fg("dim",close)],tight=[theme2.fg("text","Tasks"),...wrapped,theme2.fg("dim",close)],body2=height>=spacious.length+2?spacious:tight;if(inner>=16&&height>=body2.length+2){let box2=pane(body2,boxWidth,!1),left2=Math.floor((width-boxWidth)/2),top=Math.max(0,Math.floor((height-box2.length)/2)),blank=" ".repeat(width);result2.lines=[...Array.from({length:top},()=>blank),...box2.map(line=>" ".repeat(left2)+line+" ".repeat(width-left2-boxWidth)),...Array.from({length:height-top-box2.length},()=>blank)],hits.push({x:left2+1,y:top+body2.length,width:visibleWidth(close),cancel:!0})}else for(result2.lines=["Tasks",message,close].slice(0,height).map(line=>pad(line,width));result2.lines.length<height;)result2.lines.push(" ".repeat(width));return result2}let visible=list2.render(selection,theme2,listWidth-2,bodyHeight),listHeader=theme2.fg("text","Tasks"),searchLabel=`${hint("app.tasks.search")} find`;if(options.searchLine)listHeader=options.searchLine(listWidth-2);else{let x2=Math.max(6,listWidth-2-visibleWidth(searchLabel));listHeader+=" ".repeat(x2-5)+theme2.fg("dim",searchLabel),(wide||focus==="list")&&hits.push({x:x2+1,y:1,width:visibleWidth(searchLabel),key:"app.tasks.search"})}(wide||focus==="list")&&visible.forEach((row,index3)=>{row.taskId&&hits.push({x:1,y:2+index3,width:listWidth-2,taskId:row.taskId})});let left=[listHeader,...Array.from({length:bodyHeight},(_2,i)=>visible[i]?.text??""),theme2.fg("dim",list2.range)],task=inspector.task,tab=selection.state.tab,tabLabel=(id,label)=>theme2.style(label,{fg:"text",underline:tab===id}),right=[`${tabLabel("output","Output")} ${tabLabel("info","Details")}`];(wide||focus==="inspector")&&hits.push({x:rightX+1,y:1,width:6,tab:"output"},{x:rightX+9,y:1,width:7,tab:"info"});let content=[],reading="";if(task){wide||content.push(theme2.fg("text",cleanTaskText(firstCommandLine(task.command??task.title))),theme2.fg("muted",`${statusName(task.status)} \xB7 ${runtimeLabel(task)}`));let lines=inspector.lines(tab),position=inspector.position,read=position.read,diagnostics=[task.error,read?.readError].filter(text2=>!!text2).map(cleanTaskText);tab==="output"&&diagnostics.length&&content.push(theme2.fg("warning",diagnostics.join(" \xB7 ").replace(/\n/g," ")));let source=tab==="info"?[`Task ID ${task.id}`,`Status ${statusName(task.status)} \xB7 ${statusName(task.mode)} \xB7 ${runtimeLabel(task)}`,...diagnostics,...lines]:lines;content.push(...position[tab].layout(source,rightWidth-2,bodyHeight-content.length)),tab==="output"?(reading=position.output.follow?isTaskTerminal(task.status)?"Finished":"Live":isTaskTerminal(task.status)?`Finished \xB7 ${hint("app.tasks.follow")} load final output`:`Browsing \xB7 ${hint("app.tasks.follow")} follow output`,!position.output.follow&&(wide||focus==="inspector")&&hits.push({x:rightX+1,y:height-3,width:Math.min(rightWidth-2,visibleWidth(reading)),key:"app.tasks.follow"}),read?.truncated&&(reading+=` \xB7 Tail preview: ${formatSize(Buffer.byteLength(read.text))} of ${formatSize(read.totalBytes)}`)):tab==="info"&&(reading=`Details ${position.info.range}`)}else content.push(theme2.fg("muted","Select a task to inspect its result."));right.push(...Array.from({length:bodyHeight},(_2,i)=>content[i]??""),theme2.fg("dim",reading));let rightPane=pane(right,rightWidth,focus==="inspector"),panels=wide?pane(left,listWidth,focus==="list").map((line,i)=>`${line} ${rightPane[i]}`):pane(focus==="list"?left:right,width,!1),footer="",addHint=(key,label,target)=>{let text2=`${hint(key)} ${label}`,x2=visibleWidth(footer)+(footer?3:0);x2+visibleWidth(text2)>width||(footer+=(footer?" \xB7 ":"")+text2,target&&hits.push({x:x2,y:height-1,width:visibleWidth(text2),...target}))};if(options.help||options.pendingKill){hits.length=0;let body2;if(options.help){let controls=[["app.tasks.nextFocus","Switch task list / inspector"],["app.tasks.previousFocus","Switch inspector / task list"],["app.tasks.previousTab","Output (inspector only)"],["app.tasks.nextTab","Details (inspector only)"],["tui.select.up","Previous task / scroll up"],["tui.select.down","Next task / scroll down"],["tui.select.pageUp","Page up in task list"],["tui.select.pageDown","Page down in task list"],["tui.editor.pageUp","Page up in inspector"],["tui.editor.pageDown","Page down in inspector"],["app.tasks.top","Top of list / content"],["app.tasks.bottom","Bottom of list / content"],["app.tasks.search","Locate a retained task; Enter chooses, Escape restores selection"],["app.tasks.follow","Follow latest / final output (Output only)"],["app.tasks.detach","Move every eligible foreground execution to the background"],["app.tasks.detachSelected","Move selected foreground task to background"],["app.tasks.kill","Request stop of selected whole task"],["app.tasks.confirmStop","Confirm stop"],["tui.select.cancel","Close current search, help or confirmation; otherwise close panel"]];body2=[theme2.fg("text","Task controls"),...options.help.layout(controls.map(([key,label])=>hint(key).padEnd(14)+label),width-2,height-5),""],addHint("tui.select.up",`/ ${hint("tui.select.down")} scroll`),addHint("tui.select.cancel","back",{cancel:!0})}else{let target=selection.all.find(task2=>task2.id===options.pendingKill),command=wrapTextWithAnsi(cleanTaskText(target?.command??target?.title??options.pendingKill),width-2),preview=command.slice(0,height-8);preview.length<command.length&&(preview[preview.length-1]="\u2026 Full command in Details."),body2=[theme2.fg("text","Stop task?"),"Stops the whole task, including its active work.",`Task ID: ${options.pendingKill}`,"",...preview],addHint("app.tasks.confirmStop","confirm",{key:"app.tasks.confirmStop"}),addHint("tui.select.cancel","cancel",{cancel:!0})}for(;body2.length<height-3;)body2.push("");panels=pane(body2,width,!1)}else if(options.searchLine){for(let i=hits.length-1;i>=0;i--)hits[i].taskId||hits.splice(i,1);addHint("tui.select.up",`/ ${hint("tui.select.down")} choose`),addHint("tui.select.confirm","locate"),addHint("tui.select.cancel","cancel",{cancel:!0})}else addHint("tui.select.up",`/ ${hint("tui.select.down")}${focus==="list"?" tasks":" scroll"}`),addHint("app.tasks.nextFocus",focus==="list"?tab==="output"?"output":"details":"tasks",{key:"app.tasks.nextFocus"}),addHint("tui.select.cancel","close",{cancel:!0}),focus==="list"?addHint("app.tasks.search","find",{key:"app.tasks.search"}):(addHint("app.tasks.previousTab","output",{tab:"output"}),addHint("app.tasks.nextTab","details",{tab:"info"})),task&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&(addHint("app.tasks.kill","stop",{key:"app.tasks.kill"}),task.mode==="foreground"&&options.canDetach&&addHint("app.tasks.detachSelected","background",{key:"app.tasks.detachSelected"})),addHint("app.tasks.help","keys",{key:"app.tasks.help"}),options.feedback&&(footer=options.feedback);return result2.lines=[...panels,theme2.fg(options.pendingKill?"warning":"dim",pad(footer,width))],result2}var TaskList=class{constructor(){this.start=0,this.height=1,this.rows=[],this.selectedLine=-1,this.reveal=!1}showSelection(){this.reveal=!0}scroll(delta){this.start=Math.max(0,Math.min(Math.max(0,this.rows.length-this.height),this.start+delta))}render(selection,theme2,width,height){let rows=[],labels=selection.rows.map(task=>cleanTaskText(firstCommandLine(task.command??task.title))),fitted=labels.map(label=>truncateToWidth(label,Math.max(1,width-3),"\u2026")),group="",selectedLine=-1;for(let[index3,task]of selection.rows.entries()){let nextGroup=isTaskTerminal(task.status)?"Finished":"Active";nextGroup!==group&&(rows.push({text:theme2.fg("dim",nextGroup)}),group=nextGroup);let selected=task.id===selection.state.selectedId;selected&&(selectedLine=rows.length);let marker=statusMarker(task.status,{now:Date.now()}),duplicate=fitted.some((label,other)=>other!==index3&&label===fitted[index3]),meta=`${runtimeLabel(task)}${duplicate?` \xB7 ${task.id.slice(-8)}`:""}`,texts=[`${theme2.fg(marker.color,marker.glyph)} ${theme2.fg("text",labels[index3])}`,` ${theme2.fg(marker.color,statusName(task.status))}${theme2.fg("muted",` \xB7 ${meta}`)}`];for(let text2 of texts){let padded=truncateToWidth(text2,width,"\u2026",!0);rows.push({text:selected?theme2.getBgAnsi("selectedBg")==="\x1B[49m"?theme2.style(stripTerminalSequences(padded),{inverse:!0}):theme2.bg("selectedBg",padded):padded,taskId:task.id})}}rows.length||rows.push({text:theme2.fg("muted",selection.query?"No matching tasks.":"No retained tasks.")});let sameSelection=this.selectedId===selection.state.selectedId,selectedWasVisible=sameSelection&&this.selectedLine>=this.start&&this.selectedLine<this.start+this.height&&selectedLine>=0;if(selectedWasVisible)this.start+=selectedLine-this.selectedLine;else{let anchor=this.rows[this.start]?.taskId,offset=anchor&&this.rows[this.start-1]?.taskId===anchor?1:0,next=anchor?rows.findIndex(row=>row.taskId===anchor):-1;next>=0&&(this.start=next+offset)}return selectedLine>=0&&(!sameSelection||this.reveal||selectedWasVisible)&&(selectedLine<this.start?this.start=selectedLine:selectedLine+1>=this.start+height&&(this.start=selectedLine+2-height)),this.start=Math.max(0,Math.min(Math.max(0,rows.length-height),this.start)),this.rows=rows,this.height=height,this.selectedId=selection.state.selectedId,this.selectedLine=selectedLine,this.reveal=!1,rows.slice(this.start,this.start+height)}get range(){if(this.rows.length<=this.height)return"";let ids=[...new Set(this.rows.flatMap(row=>row.taskId?[row.taskId]:[]))],visible=this.rows.slice(this.start,this.start+this.height).flatMap(row=>row.taskId?[row.taskId]:[]);return`Tasks ${ids.indexOf(visible[0])+1}-${ids.indexOf(visible.at(-1))+1} of ${ids.length}`}};var TaskSelection=class{constructor(state2){this.all=[],this.rows=[],this.query="",this.state=state2}get selected(){return this.rows.find(task=>task.id===this.state.selectedId)}get activeCount(){return this.all.filter(task=>!isTaskTerminal(task.status)).length}sync(all){this.all=all,this.refresh()}select(id){this.state.selectedId=id,this.refresh()}refresh(){let{selectedId}=this.state,active=this.all.filter(task=>!isTaskTerminal(task.status)).sort((a,b2)=>b2.startedAt-a.startedAt||a.id.localeCompare(b2.id)),history=this.all.filter(task=>isTaskTerminal(task.status)).sort((a,b2)=>(b2.endedAt??0)-(a.endedAt??0)||a.id.localeCompare(b2.id)),rows=[...active,...history],search2=this.query.toLocaleLowerCase().trim();this.rows=search2?rows.filter(task=>`${task.title}
|
|
2215
|
+
${task.command??""}
|
|
2216
|
+
${task.kind}
|
|
2217
|
+
${task.id}`.toLocaleLowerCase().includes(search2)):rows,this.rows.some(task=>task.id===selectedId)||(this.state.selectedId=this.rows[0]?.id)}};var actions=["app.tasks.search","app.tasks.kill","app.tasks.detachSelected","app.tasks.previousTab","app.tasks.nextTab","app.tasks.follow","app.tasks.top","app.tasks.bottom","app.tasks.nextFocus","app.tasks.previousFocus","app.tasks.help"],TasksMenu=class{constructor(options){this.focused=!1,this.list=new TaskList,this.focus="list",this.searching=!1,this.dirty=!0,this.tickQueued=!1,this.refreshQueued=!1,this.disposed=!1,this.options=options,this.width=options.tui.terminal.columns,this.selection=new TaskSelection(options.state??{tab:"output"}),this.inspector=new TaskInspector({host:options.host,theme:options.theme,requestRender:()=>options.tui.requestRender()}),this.search=new Input({prompt:"Find task: ",placeholder:"title, command, kind or ID"}),this.sync(),this.unsubscribe=options.host.subscribe(()=>{this.dirty=!0,this.queueTick(),options.tui.requestRender()}),this.pollTimer=setInterval(()=>{this.queueTick(!0),this.selection.activeCount&&options.tui.requestRender()},options.pollIntervalMs??1e3),this.pollTimer.unref?.(),this.queueTick(!0)}sync(){if(this.disposed||!this.dirty)return;this.dirty=!1;let previous=this.selection.selected;this.selection.sync(this.options.host.list()),this.inspector.select(this.selection.selected),this.inspector.prune(new Set(this.selection.all.map(task=>task.id)));let selected=this.selection.selected;selected&&isTaskTerminal(selected.status)&&previous&&!isTaskTerminal(previous.status)&&(this.feedback=void 0),this.pendingKill&&(this.pendingKill!==selected?.id||selected&&isTaskTerminal(selected.status))&&this.clearKill();let animates=this.selection.all.some(task=>task.status==="running");animates&&!this.animationTimer?(this.animationTimer=setInterval(()=>this.options.tui.requestRender(),STATUS_SPINNER_INTERVAL_MS),this.animationTimer.unref?.()):animates||(clearInterval(this.animationTimer),this.animationTimer=void 0)}queueTick(refresh=!1){this.disposed||(this.refreshQueued||=refresh,!this.tickQueued&&(this.tickQueued=!0,Promise.resolve().then(async()=>{if(this.tickQueued=!1,this.disposed)return;let refresh2=this.refreshQueued;this.refreshQueued=!1,this.sync(),(refresh2||this.inspector.task&&isTaskTerminal(this.inspector.task.status))&&await this.inspector.refresh()}).catch(()=>{})))}invalidate(){this.inspector.invalidate()}clearKill(){this.pendingKill=void 0}selectedChanged(){this.clearKill(),this.list.showSelection(),this.inspector.select(this.selection.selected),this.queueTick(!0)}stop(confirm=!1){let task=this.selection.selected;if(confirm){let id=this.pendingKill;if(this.clearKill(),!id||id!==task?.id||isTaskTerminal(task.status))return;this.feedback=this.options.host.kill(id)?"Cancellation requested; waiting for cleanup.":"No new cancellation requested."}else task&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&(this.pendingKill=task.id)}finishSearch(cancel){let id=cancel?this.beforeSearch?.id:this.selection.state.selectedId;!cancel&&!id||(this.focus=cancel?this.beforeSearch?.focus??"list":"list",this.searching=!1,this.search.focused=!1,this.selection.query="",this.selection.select(id),this.beforeSearch=void 0,this.selectedChanged())}action(key){switch(key){case"app.tasks.search":this.beforeSearch={id:this.selection.state.selectedId,focus:this.focus},this.focus="list",this.searching=!0,this.search.focused=!0,this.search.setValue("");break;case"app.tasks.previousTab":case"app.tasks.nextTab":this.focus==="inspector"&&(this.selection.state.tab=key==="app.tasks.previousTab"?"output":"info");break;case"app.tasks.nextFocus":case"app.tasks.previousFocus":this.focus=this.focus==="list"?"inspector":"list";break;case"app.tasks.follow":this.focus==="inspector"&&this.selection.state.tab==="output"&&(this.inspector.position.output.jump(!0,!0),this.queueTick(!0));break;case"app.tasks.top":case"app.tasks.bottom":this.focus==="list"?(this.selection.select(key==="app.tasks.top"?this.selection.rows[0]?.id:this.selection.rows.at(-1)?.id),this.selectedChanged()):this.inspector.position[this.selection.state.tab].jump(key==="app.tasks.bottom",this.selection.state.tab==="output");break;case"app.tasks.kill":this.stop();break;case"app.tasks.confirmStop":this.stop(!0);break;case"app.tasks.detachSelected":{let task=this.selection.selected;task?.mode==="foreground"&&!isTaskTerminal(task.status)&&task.status!=="stopping"&&this.options.host.enabled!==!1&&(this.feedback=this.options.host.detach?.(task.id)?"Selected task moved to background; execution continues.":"This task cannot move to background.");break}case"app.tasks.help":this.help=this.help?void 0:new TaskViewport;break}}move(direction,page=!1){if(this.help){this.help.move(direction,page,!1);return}if(this.focus==="list"){let rows=this.selection.rows;if(!rows.length)return;let index3=rows.findIndex(task=>task.id===this.selection.state.selectedId),next=page?Math.max(0,Math.min(rows.length-1,index3+direction*(this.layout?.listPageSize??1))):(index3+direction+rows.length)%rows.length;this.selection.select(rows[next]?.id),this.selectedChanged()}else this.inspector.position[this.selection.state.tab].move(direction,page,this.selection.state.tab==="output")}handleInput(data){if(this.disposed)return;this.sync(),this.render(this.width);let kb=this.options.keybindings;this.feedback=void 0;try{if(this.layout?.tooSmall){if(kb.matches(data,"tui.select.cancel"))if(this.help)this.help=void 0;else if(this.searching)this.finishSearch(!0);else if(this.pendingKill)this.clearKill();else{this.dispose(),this.options.onClose();return}}else if(this.help)kb.matches(data,"tui.select.cancel")||kb.matches(data,"app.tasks.help")?this.help=void 0:kb.matches(data,"app.tasks.top")||kb.matches(data,"app.tasks.bottom")?this.help.jump(kb.matches(data,"app.tasks.bottom"),!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.editor.pageUp")?this.help.move(-1,kb.matches(data,"tui.editor.pageUp"),!1):(kb.matches(data,"tui.select.down")||kb.matches(data,"tui.editor.pageDown"))&&this.help.move(1,kb.matches(data,"tui.editor.pageDown"),!1);else if(this.searching)kb.matches(data,"tui.select.cancel")?this.finishSearch(!0):kb.matches(data,"tui.select.confirm")?this.finishSearch(!1):kb.matches(data,"tui.select.up")||kb.matches(data,"tui.select.pageUp")?this.move(-1,kb.matches(data,"tui.select.pageUp")):kb.matches(data,"tui.select.down")||kb.matches(data,"tui.select.pageDown")?this.move(1,kb.matches(data,"tui.select.pageDown")):(this.search.handleInput(data),this.selection.query=this.search.getValue().slice(0,512),this.selection.refresh(),this.selectedChanged());else if(this.pendingKill)kb.matches(data,"app.tasks.confirmStop")?this.stop(!0):kb.matches(data,"tui.select.cancel")&&this.clearKill();else if(kb.matches(data,"tui.select.cancel")){this.dispose(),this.options.onClose();return}else{let pageUp=kb.matches(data,this.focus==="list"?"tui.select.pageUp":"tui.editor.pageUp"),pageDown=kb.matches(data,this.focus==="list"?"tui.select.pageDown":"tui.editor.pageDown");if(pageUp||kb.matches(data,"tui.select.up"))this.move(-1,pageUp);else if(pageDown||kb.matches(data,"tui.select.down"))this.move(1,pageDown);else{if(kb.matches(data,"tui.select.confirm"))return;{let key=actions.find(key2=>kb.matches(data,key2));key&&this.action(key)}}}}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}this.queueTick(!0),this.options.tui.requestRender()}handleMouse(event){if(this.disposed||event.ctrl||event.alt||event.shift)return;this.feedback=void 0,this.render(event.width);let layout=this.layout;if(event.type==="wheel"&&event.wheelDelta){if(!this.pendingKill&&!layout.tooSmall&&event.y>=2&&event.y<this.options.tui.terminal.rows-3){let delta=Math.sign(event.wheelDelta)*Math.min(20,Math.abs(event.wheelDelta)),region=this.width>=100?event.x<layout.listWidth?"list":"inspector":this.focus;this.help?this.help.move(delta,!1,!1):region==="list"?this.list.scroll(delta):this.searching||this.inspector.position[this.selection.state.tab].move(delta,!1,this.selection.state.tab==="output")}}else if(event.type==="click"&&event.button==="left"){let hit=layout.hits.find(hit2=>hit2.y===event.y&&event.x>=hit2.x&&event.x<hit2.x+hit2.width);try{hit?.cancel?this.searching?this.finishSearch(!0):this.help?this.help=void 0:this.pendingKill?this.clearKill():(this.dispose(),this.options.onClose()):hit?.taskId?(this.selection.select(hit.taskId),this.selectedChanged(),this.focus="list",this.searching&&this.finishSearch(!1)):hit?.tab?(this.focus="inspector",this.selection.state.tab=hit.tab):hit?.key?(hit.key==="app.tasks.follow"&&(this.focus="inspector"),this.action(hit.key)):!this.pendingKill&&!this.searching&&!this.help&&!layout.tooSmall&&event.y>=1&&event.y<this.options.tui.terminal.rows-2&&this.width>=100&&(this.focus=event.x<layout.listWidth?"list":"inspector")}catch(error){this.feedback=cleanTaskText(error instanceof Error?error.message:String(error))}}else return;return this.queueTick(!0),this.options.tui.requestRender(),{handled:!0,focus:event.type==="click"}}render(width){return this.width=width,this.sync(),this.layout=renderTasksLayout({width,height:this.options.tui.terminal.rows,theme:this.options.theme,keybindings:this.options.keybindings,selection:this.selection,inspector:this.inspector,list:this.list,focus:this.focus,searchLine:this.searching?width2=>this.search.render(width2).join(""):void 0,pendingKill:this.pendingKill,feedback:this.feedback,help:this.help,canDetach:this.options.host.enabled!==!1&&!!this.options.host.detach}),this.layout.lines}dispose(){this.disposed||(this.disposed=!0,clearInterval(this.pollTimer),clearInterval(this.animationTimer),this.clearKill(),this.unsubscribe(),this.inspector.dispose())}};function bindTasksUI(ctx){let state2={tab:"output"},unsubscribe,unsubscribeDetachKey,closeMenu,hintTimer,start=()=>{unsubscribe?.(),unsubscribeDetachKey?.();let update=()=>{clearTimeout(hintTimer),hintTimer=void 0;let all=ctx.tasks.list(),background=all.filter(task=>task.mode==="background"&&!isTaskTerminal(task.status)).length,parts=[];background&&(parts.push(theme.fg("text",`${background} background task${background===1?"":"s"}`)),parts.push(theme.fg("accent","/tasks")+theme.fg("muted"," to view")));let detachKey=keyLabel("app.tasks.detach"),now=Date.now(),movable=all.filter(task=>ctx.tasks.canDetach(task.id)),waits=movable.map(task=>task.startedAt+TASKS_DETACH_HINT_DELAY_MS-now).filter(wait=>wait>0);detachKey&&movable.length>waits.length&&parts.push(theme.fg("accent",detachKey)+theme.fg("muted"," to run in background")),detachKey&&waits.length>0&&(hintTimer=setTimeout(update,Math.min(...waits)),hintTimer.unref?.()),ctx.ui.setStatus("background",parts.length?parts.join(theme.fg("dim"," \xB7 ")):void 0)};unsubscribe=ctx.tasks.subscribe(update),unsubscribeDetachKey=ctx.ui.onTerminalInput(data=>{if(!getKeybindings().matches(data,"app.tasks.detach"))return;let count;try{count=ctx.tasks.detachForeground()}catch(error){return ctx.ui.notify(error instanceof Error?error.message:String(error),"warning"),{consume:!0}}if(count!==0)return ctx.ui.notify(`Moved ${count} execution${count===1?"":"s"} to the background. Use /tasks to manage tasks.`),{consume:!0}}),update()},dispose=()=>{unsubscribe?.(),unsubscribe=void 0,unsubscribeDetachKey?.(),unsubscribeDetachKey=void 0,clearTimeout(hintTimer),hintTimer=void 0,closeMenu?.(),closeMenu=void 0,ctx.ui.setStatus("background",void 0)};return start(),{dispose,open:async()=>{closeMenu?.(),await ctx.ui.custom((tui,theme2,keybindings,done)=>{let close=()=>{closeMenu===close&&(closeMenu=void 0),done()};return closeMenu=close,new TasksMenu({state:state2,tui,theme:theme2,keybindings,host:ctx.tasks,onClose:close})},{overlay:!0,overlayOptions:{anchor:"center",width:"100%",maxHeight:"100%"}})}}}async function confirmStopBranchTasks(stopped,confirm){if(stopped.length===0)return!0;let shown=stopped.slice(0,5).map(task=>` ${cleanTaskText(firstCommandLine(task.command??task.title))}`);return stopped.length>shown.length&&shown.push(` \u2026and ${stopped.length-shown.length} more`),confirm(`Stop ${stopped.length} running task${stopped.length===1?"":"s"}?`,`They were started on the branch you are leaving and will be cancelled:
|
|
2218
|
+
${shown.join(`
|
|
2219
|
+
`)}`)}function tasksExtension(pi){let ui,bind=ctx=>{ui?.dispose(),ui=bindTasksUI(ctx)};pi.on("session_start",(_event,ctx)=>bind(ctx)),pi.on("session_shutdown",()=>{ui?.dispose(),ui=void 0}),pi.on("session_before_tree",async(event,ctx)=>{if(!ctx.hasUI)return;let stopped=ctx.tasks.session?.stoppedByTreeNavigation(event.preparation.targetId)??[];if(!await confirmStopBranchTasks(stopped,(title,message)=>ctx.ui.confirm(title,message)))return{cancel:!0}}),pi.registerTool(createTasksToolDefinition()),pi.registerMessageRenderer("task-completion",renderTaskCompletion),pi.registerCommand("tasks",{description:"View and manage session tasks",handler:async(_args,ctx)=>{if(ctx.mode!=="tui"){let tasks=ctx.tasks.list().filter(task=>task.mode==="background");ctx.ui.notify(boundedText(tasks.slice(0,10).map(describeTaskLine).join(`
|
|
2220
|
+
`))||"No background tasks.","info");return}ui||bind(ctx),await ui.open()}})}function formatFallbackArgs(args){if(!args||typeof args!="object")return"";let entries=Object.entries(args);if(entries.length===0)return"";let summary=entries.map(([key,value])=>{try{return`${key}=${JSON.stringify(value)??String(value)}`}catch{return`${key}=${String(value)}`}}).join(" ").replace(/\s+/g," ");return truncateToWidth(summary,toolStyle.fallbackArgsWidth,"...")}function createCallFallback(toolName,args,expanded=!1){if(expanded)return new Text(formatToolCallWithArgs(toolName,args,theme,!0),0,0);let summary=formatFallbackArgs(args),suffix=summary?theme.fg("dim",`(${summary})`):"";return new Text(`${theme.fg("toolTitle",theme.bold(toolName))}${suffix}`,0,0)}var FallbackResultComponent=class{constructor(output,expanded){this.output=output,this.expanded=expanded}render(width){let styledOutput=theme.fg("toolOutput",this.output);if(this.expanded)return new Text(styledOutput,0,0).render(width);let preview=truncateToVisualLines(styledOutput,toolStyle.collapsed.fallbackLines,width);if(preview.skippedCount<=0)return preview.visualLines;let noun=preview.skippedCount===1?"line":"lines",hint=theme.fg("muted",`... (${preview.skippedCount} earlier ${noun},`)+` ${keyHint("app.tools.expand","to expand")}${theme.fg("muted",")")}`;return[truncateToWidth(hint,width,"..."),...preview.visualLines]}invalidate(){}};var builtInRenderers;function builtInResultRenderer(toolName){return builtInRenderers??=createAllToolRenderers(),builtInRenderers[toolName]?.renderResult}function createToolShell(toolName,definition){let resultRenderer=definition?.renderResult;return{get gap(){return toolStyle.gap},frame(component,kind,context){return new FramedComponent(component,kind,()=>toolMarkerColor(toolStatus(context)))},renderCall(args,_theme,context){return createCallFallback(toolName,args,context.expanded)},renderResult(result2,_options,_theme,context){let output=getTextOutput(result2,context.showImages);return output?new FallbackResultComponent(output,context.expanded):new Container},shouldHideResult(context){if(context.expanded||context.isError||!toolStyle.collapsed.headerOnly.has(toolName))return!1;let builtIn=builtInResultRenderer(toolName);return builtIn!==void 0&&builtIn===resultRenderer}}}function withToolShell(toolName,definition){return definition?.renderShell==="self"||definition?.shell?definition:{...definition??{},shell:createToolShell(toolName,definition)}}function toolPresentation(pi){pi.registerToolRenderer((toolName,next)=>withToolShell(toolName,next()))}var builtInExtensions=[{name:"codemode",factory:codemode_default,replaceable:!0,builtin:!0},{name:"mcp",factory:mcp_default,replaceable:!0,builtin:!0},{name:"tool-search",factory:tool_search_default,replaceable:!0,builtin:!0},{name:"cached-compaction",factory:cachedCompaction,replaceable:!0,builtin:!0},{name:"llama.cpp",factory:llamaExtension,builtin:!0},{name:"btw",factory:btwExtension,builtin:!0},{name:"deepwiki",factory:deepwiki,builtin:!0},{name:"provider",factory:providerExtension,builtin:!0},{name:"question",factory:question,builtin:!0},{name:"statusline",factory:statusline,builtin:!0},{name:"tool-presentation",factory:toolPresentation,builtin:!0},{name:"tasks",factory:tasksExtension,replaceable:!0,builtin:!0},{name:"search",factory:search,builtin:!0}];var cli_exports={};__export(cli_exports,{runMcpCommand:()=>runMcpCommand});import{existsSync as existsSync26}from"node:fs";import{join as join47}from"node:path";import{createInterface as createInterface5}from"node:readline/promises";var HELP=`${source_default.bold("Usage:")}
|
|
2215
2221
|
${APP_NAME} mcp add <server> [options] -- <command> [args...]
|
|
2216
2222
|
${APP_NAME} mcp add <server> [options] --url <url>
|
|
2217
2223
|
${APP_NAME} mcp remove <server> [-l]
|
|
@@ -2352,4 +2358,4 @@ Options:
|
|
|
2352
2358
|
`))});try{switch(options.command){case"install":return await packageManager.installAndPersist(source,{local:options.local}),console.log(source_default.green(`Installed ${source}`)),!0;case"remove":return await packageManager.removeAndPersist(source,{local:options.local})?(console.log(source_default.green(`Removed ${source}`)),!0):(console.error(source_default.red(`No matching package found for ${source}`)),process.exitCode=1,!0);case"list":{let configuredPackages=packageManager.listConfiguredPackages(),userPackages=configuredPackages.filter(pkg2=>pkg2.scope==="user"),projectPackages=configuredPackages.filter(pkg2=>pkg2.scope==="project");if(configuredPackages.length===0)return console.log(source_default.dim("No packages installed.")),!0;let formatPackage=pkg2=>{let display=pkg2.filtered?`${pkg2.source} (filtered)`:pkg2.source;console.log(` ${display}`),pkg2.installedPath&&console.log(source_default.dim(` ${pkg2.installedPath}`))};if(userPackages.length>0){console.log(source_default.bold("User packages:"));for(let pkg2 of userPackages)formatPackage(pkg2)}if(projectPackages.length>0){userPackages.length>0&&console.log(),console.log(source_default.bold("Project packages:"));for(let pkg2 of projectPackages)formatPackage(pkg2)}return!0}case"update":{let target=options.updateTarget??{type:"self"};if(options.showExtensionsSkippedNote&&console.log(source_default.dim(`Extensions are skipped. Run ${APP_NAME} update --extensions to update extensions.`)),updateTargetIncludesExtensions(target)){let updateSource=target.type==="extensions"?target.source:void 0;await packageManager.update(updateSource),console.log(updateSource?source_default.green(`Updated ${updateSource}`):source_default.green("Updated packages"))}if(updateTargetIncludesSelf(target)){let managedInstallRoot=getActiveManagedInstallRoot();if(managedInstallRoot&&options.force)return console.error(source_default.red(`Managed ${APP_NAME} installations do not support --force; rerun the installer to repair this installation.`)),process.exitCode=1,!0;let selfUpdatePlan=await getSelfUpdatePlan(options.force);if(!selfUpdatePlan.shouldRun)return!0;if(managedInstallRoot){selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{console.log(source_default.dim(`Updating managed ${APP_NAME} installation...`)),await runManagedSelfUpdate(managedInstallRoot,selfUpdatePlan.version)}catch(error){let message=error instanceof Error?error.message:"Unknown managed update error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}return console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`)),!0}let installMethod=detectInstallMethod();if(process.platform==="win32"&&installMethod!=="npm"&&installMethod!=="pnpm")return console.error(source_default.red(`${APP_NAME} self-update on Windows is only supported for npm and pnpm installs.`)),console.error(source_default.dim(`Detected install method: ${installMethod}. Update ${APP_NAME} manually.`)),process.exitCode=1,!0;let selfUpdateTarget={packageName:selfUpdatePlan.packageName,installSpec:selfUpdatePlan.installSpec},selfUpdateCommand=getSelfUpdateCommand(PACKAGE_NAME,selfUpdateNpmCommand,selfUpdateTarget);if(!selfUpdateCommand)return printSelfUpdateUnavailable(selfUpdateNpmCommand,selfUpdateTarget),process.exitCode=1,!0;selfUpdatePlan.note&&printSelfUpdateNote(selfUpdatePlan.note);try{installMethod==="npm"&&prepareWindowsNpmSelfUpdate(),await runSelfUpdate(selfUpdateCommand)}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),installMethod==="pnpm"&&printPnpmSelfUpdateMetadataHint(),printSelfUpdateFallback(selfUpdateCommand),process.exitCode=1,!0}console.log(source_default.green(`Updated ${APP_NAME} from ${VERSION} to ${selfUpdatePlan.version}`))}return!0}}}catch(error){let message=error instanceof Error?error.message:"Unknown package command error";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}}var EXTENSION_LOAD_FAILURE_HINT=`Hint: Start without extensions using "${APP_NAME} -ne".`;async function readPipedStdin(){if(!process.stdin.isTTY)return new Promise(resolve20=>{let data="";process.stdin.setEncoding("utf8"),process.stdin.on("data",chunk=>{data+=chunk}),process.stdin.on("end",()=>{resolve20(data.trim()||void 0)}),process.stdin.resume()})}function reportDiagnostics(diagnostics){for(let diagnostic of diagnostics){let color2=diagnostic.type==="error"?source_default.red:diagnostic.type==="warning"?source_default.yellow:source_default.dim,prefix=diagnostic.type==="error"?"Error: ":diagnostic.type==="warning"?"Warning: ":"";console.error(color2(`${prefix}${diagnostic.message}`))}}function isTruthyEnvFlag2(value){return value?value==="1"||value.toLowerCase()==="true"||value.toLowerCase()==="yes":!1}function resolveAppMode(parsed,stdinIsTTY,stdoutIsTTY){return parsed.mode==="rpc"?"rpc":parsed.mode==="json"?"json":parsed.print||!stdinIsTTY||!stdoutIsTTY?"print":"interactive"}function toPrintOutputMode(appMode){return appMode==="json"?"json":"text"}function isPlainRuntimeMetadataCommand(parsed){return!parsed.print&&parsed.mode===void 0&&(parsed.help===!0||parsed.listModels!==void 0)}async function runAuthCommand(args){if(isAuthCommandHelp(args))return printAuthCommandHelp(),!0;let command;try{command=parseAuthCommand(args)}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to parse auth command";return console.error(source_default.red(`Error: ${message}`)),process.exitCode=1,!0}if(!command)return!1;let parsed=parseArgs(command.args);if(parsed.unknownFlags.size>0){let option=parsed.unknownFlags.keys().next().value;return console.error(source_default.red(`Unknown option --${option} for "${getAuthCommandName(command.kind)}".`)),console.error(source_default.dim(`Use "${APP_NAME} --help" or "${getAuthCommandUsage(command.kind)}".`)),process.exitCode=1,!0}try{if(parsed.diagnostics.length>0)throw new AuthCommandError(parsed.diagnostics.map(diagnostic=>diagnostic.message).join(`
|
|
2353
2359
|
`));if(command.kind!=="check"){let signal=AbortSignal.timeout(15e3),modelRuntime=await ModelRuntime.create({allowModelNetwork:!1,signal}),credential2=await resolveCredentialForPrint(parsed,modelRuntime,command.kind,command.minExpiryMs,signal);return process.stdout.write(`${credential2}
|
|
2354
2360
|
`),!0}let requestedAuth=validateAuthCommandArgs(parsed,command.kind),result2,credential;try{let credentials=command.noRefresh?new ReadOnlyAuthStorage:AuthStorage.create(),modelRuntime=await createAuthCheckModelRuntime(credentials);result2=await checkProviderAuth(parsed,modelRuntime,{refresh:!command.noRefresh}),command.credentials&&result2.status==="ready"&&(credential=await getProviderCredential(result2.provider,modelRuntime,credentials,{refresh:!command.noRefresh}),credential||(result2={status:"not_ready",provider:result2.provider,reason:"credential_not_available"}))}catch{result2={status:"invalid",provider:requestedAuth.provider??requestedAuth.model,reason:"invalid_state"}}let output=command.json?JSON.stringify({...result2,...credential?{credentials:credential}:{}}):credential??result2.status;process.stdout.write(`${output}
|
|
2355
|
-
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve20=>{let rl=createInterface6({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve20(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.provider&&!parsed.model&&diagnostics.push({type:"error",message:`--provider requires --model (for example: --provider ${parsed.provider} --model <pattern>)`}),parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,inlineApiKey:!!parsed.apiKey,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value=>isLocalPath(value)?resolvePath(value,cwd):value)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings(),setThemeJsonValidator(validateThemeJson);let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;if(args[0]==="mcp"){let{runMcpCommand:runMcpCommand2}=await loadMcpCommand();process.exitCode=await runMcpCommand2(args.slice(1),{cwd,agentDir});return}let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,disabledBuiltinExtensions:parsed.noMcp?["mcp"]:void 0,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`})),...(resourceLoader2.getExtensions().warnings??[]).map(({path:path14,warning})=>({type:"warning",message:`Extension package "${path14}": ${warning}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve20=>setTimeout(resolve20,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve20=>process.stdout.once("drain",resolve20)),process.stderr.writableLength>0&&await new Promise(resolve20=>process.stderr.once("drain",resolve20));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,SettingsManager,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,VIRTUAL_MODEL_STATE_ENTRY,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,createSyntheticSourceInfo,DefaultPackageManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,parseFrontmatter,stripFrontmatter,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,TaskRuntime,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,dist_exports2,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,serializeConversation,DEFAULT_COMPACTION_SETTINGS,calculateContextTokens,getLastAssistantUsage,shouldCompact,estimateTokens2 as estimateTokens,findTurnStartIndex,findCutPoint,generateSummary,generateSummaryWithUsage,compact,collectEntriesForBranchSummary,prepareBranchEntries,generateBranchSummary,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,truncateToVisualLines,formatReadLineRange,createLocalBashOperations,createBashToolDefinition,createBashTool,generateUnifiedPatch,generateDiffString,withFileMutationQueue,renderDiff,createEditToolDefinition,createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool,createWriteToolDefinition,createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,createCodemodeExtension,copyToClipboard,createMcpExtension,createToolSearchExtension,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,ToolExecutionComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|
|
2361
|
+
`),process.exitCode=result2.status==="ready"?0:result2.status==="not_ready"?1:2}catch(error){let message=error instanceof AuthCommandError?error.message:"Failed to resolve credential";console.error(source_default.red(`Error: ${message}`)),process.exitCode=command.kind==="check"?2:1}return!0}async function prepareInitialMessage(parsed,stdinContent){if(parsed.fileArgs.length===0)return buildInitialMessage({parsed,stdinContent});let{text:text2,images}=await processFileArguments(parsed.fileArgs,{autoResizeImages:!1});return buildInitialMessage({parsed,fileText:text2,fileImages:images,stdinContent})}function findLocalSessionByExactId(sessionId,cwd,sessionDir){let path14=SessionManager.findById(cwd,sessionId,sessionDir);return path14?{type:"local",path:path14}:void 0}async function resolveSessionPath(sessionArg,cwd,sessionDir){if(sessionArg.includes("/")||sessionArg.includes("\\")||sessionArg.endsWith(".jsonl"))return{type:"path",path:resolvePath(sessionArg,cwd)};let exactLocalMatch=findLocalSessionByExactId(sessionArg,cwd,sessionDir);if(exactLocalMatch)return exactLocalMatch;let localMatch=(await SessionManager.list(cwd,sessionDir)).find(s=>s.id.startsWith(sessionArg));if(localMatch)return{type:"local",path:localMatch.path};let allSessions=await SessionManager.listAll(sessionDir),globalMatch=allSessions.find(s=>s.id===sessionArg)??allSessions.find(s=>s.id.startsWith(sessionArg));return globalMatch?{type:"global",path:globalMatch.path,cwd:globalMatch.cwd}:{type:"not_found",arg:sessionArg}}async function promptConfirm(message){return new Promise(resolve20=>{let rl=createInterface6({input:process.stdin,output:process.stdout});rl.question(`${message} [y/N] `,answer=>{rl.close(),resolve20(answer.toLowerCase()==="y"||answer.toLowerCase()==="yes")})})}function validateForkFlags(parsed){if(!parsed.fork)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0,parsed.noSession?"--no-session":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --fork cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1))}function validateSessionIdFlags(parsed){if(parsed.sessionId===void 0)return;let conflictingFlags=[parsed.session?"--session":void 0,parsed.continue?"--continue":void 0,parsed.resume?"--resume":void 0].filter(flag=>flag!==void 0);conflictingFlags.length>0&&(console.error(source_default.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(", ")}`)),process.exit(1));try{assertValidSessionId(parsed.sessionId)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function openSessionOrExit(path14,sessionDir){try{return SessionManager.open(path14,sessionDir)}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}function forkSessionOrExit(sourcePath,cwd,sessionDir,sessionId){try{return SessionManager.forkFrom(sourcePath,cwd,sessionDir,{id:sessionId})}catch(error){let message=error instanceof Error?error.message:String(error);console.error(source_default.red(`Error: ${message}`)),process.exit(1)}}async function createSessionManager(parsed,cwd,sessionDir,settingsManager){if(parsed.noSession||parsed.help||parsed.listModels!==void 0)return SessionManager.inMemory(cwd,parsed.sessionId!==void 0?{id:parsed.sessionId}:void 0);if(parsed.fork){parsed.sessionId&&findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir)&&(console.error(source_default.red(`Session already exists with id '${parsed.sessionId}'`)),process.exit(1));let resolved=await resolveSessionPath(parsed.fork,cwd,sessionDir);switch(resolved.type){case"path":case"local":case"global":return forkSessionOrExit(resolved.path,cwd,sessionDir,parsed.sessionId);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.session){let resolved=await resolveSessionPath(parsed.session,cwd,sessionDir);switch(resolved.type){case"path":case"local":return openSessionOrExit(resolved.path,sessionDir);case"global":return console.log(source_default.yellow(`Session found in different project: ${resolved.cwd}`)),await promptConfirm("Fork this session into current directory?")||(console.log(source_default.dim("Aborted.")),process.exit(0)),forkSessionOrExit(resolved.path,cwd,sessionDir);case"not_found":console.error(source_default.red(`No session found matching '${resolved.arg}'`)),process.exit(1)}}if(parsed.resume)try{let selectedPath=await selectSession((onProgress,signal)=>SessionManager.list(cwd,sessionDir,onProgress,signal),(onProgress,signal)=>SessionManager.listAll(sessionDir,onProgress,signal),settingsManager);return selectedPath||(console.log(source_default.dim("No session selected")),process.exit(0)),SessionManager.open(selectedPath,sessionDir)}finally{stopThemeWatcher()}if(parsed.continue)return SessionManager.continueRecent(cwd,sessionDir);if(parsed.sessionId){let existingSession=findLocalSessionByExactId(parsed.sessionId,cwd,sessionDir);if(existingSession)return SessionManager.open(existingSession.path,sessionDir);console.error(source_default.yellow(`Warning: No project session found with id '${parsed.sessionId}'; creating a new session with that id.`))}return SessionManager.create(cwd,sessionDir,{id:parsed.sessionId})}function buildSessionOptions(parsed,scopedModels,hasExistingSession,modelRuntime,settingsManager){let options={},diagnostics=[],cliThinkingFromModel=!1;if(parsed.provider&&!parsed.model&&diagnostics.push({type:"error",message:`--provider requires --model (for example: --provider ${parsed.provider} --model <pattern>)`}),parsed.model){let resolved=resolveCliModel({cliProvider:parsed.provider,cliModel:parsed.model,cliThinking:parsed.thinking,inlineApiKey:!!parsed.apiKey,modelRuntime});resolved.warning&&diagnostics.push({type:"warning",message:resolved.warning}),resolved.error&&diagnostics.push({type:"error",message:resolved.error}),resolved.model&&(options.model=resolved.model,!parsed.thinking&&resolved.thinkingLevel&&(options.thinkingLevel=resolved.thinkingLevel,cliThinkingFromModel=!0))}if(!options.model&&scopedModels.length>0&&!hasExistingSession){let savedProvider=settingsManager.getDefaultProvider(),savedModelId=settingsManager.getDefaultModel(),savedModel=savedProvider&&savedModelId?modelRuntime.getModel(savedProvider,savedModelId):void 0,savedInScope=savedModel?scopedModels.find(sm=>modelsAreEqual(sm.model,savedModel)):void 0;savedInScope?(options.model=savedInScope.model,!parsed.thinking&&savedInScope.thinkingLevel&&(options.thinkingLevel=savedInScope.thinkingLevel)):(options.model=scopedModels[0].model,!parsed.thinking&&scopedModels[0].thinkingLevel&&(options.thinkingLevel=scopedModels[0].thinkingLevel))}return parsed.thinking&&(options.thinkingLevel=parsed.thinking),scopedModels.length>0&&(options.scopedModels=scopedModels.map(sm=>({model:sm.model,thinkingLevel:sm.thinkingLevel}))),parsed.noTools?options.noTools="all":parsed.noBuiltinTools&&(options.noTools="builtin"),parsed.tools&&(options.tools=[...parsed.tools]),parsed.excludeTools&&(options.excludeTools=[...parsed.excludeTools]),{options,cliThinkingFromModel,diagnostics}}function resolveCliPaths(cwd,paths){return paths?.map(value=>isLocalPath(value)?resolvePath(value,cwd):value)}async function promptForMissingSessionCwd(issue,settingsManager){return showStartupSelector(settingsManager,formatMissingSessionCwdPrompt(issue),[{label:"Continue",value:issue.fallbackCwd},{label:"Cancel",value:void 0}])}async function main(args,options){resetTimings(),setThemeJsonValidator(validateThemeJson);let extensionFactories=[...builtInExtensions,...options?.extensionFactories??[]],offlineMode=args.includes("--offline")||isTruthyEnvFlag2(process.env.PI_OFFLINE);if(offlineMode&&(process.env.PI_OFFLINE="1",process.env.PI_SKIP_VERSION_CHECK="1"),await runAuthCommand(args))return;process.platform==="win32"&&cleanupWindowsSelfUpdateQuarantine(getPackageDir()),cleanupManagedInstall();let cwd=process.cwd(),agentDir=getAgentDir(),bootstrapSettingsManager=SettingsManager.create(cwd,agentDir,{projectTrusted:!1});if(applyHttpProxySettings(bootstrapSettingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(),await handlePackageCommand(args,{extensionFactories})){let exitCode=process.exitCode??0;if(process.platform==="win32"&&exitCode===0&&args[0]==="update")return;process.exit(exitCode);return}if(await handleConfigCommand(args,{extensionFactories}))return;if(args[0]==="mcp"){let{runMcpCommand:runMcpCommand2}=await loadMcpCommand();process.exitCode=await runMcpCommand2(args.slice(1),{cwd,agentDir});return}let parsed=parseArgs(args);if(parsed.diagnostics.length>0){for(let d of parsed.diagnostics){let color2=d.type==="error"?source_default.red:source_default.yellow;console.error(color2(`${d.type==="error"?"Error":"Warning"}: ${d.message}`))}parsed.diagnostics.some(d=>d.type==="error")&&process.exit(1)}if(time("parseArgs"),parsed.version&&(console.log(VERSION),process.exit(0)),parsed.export){let result2;try{let outputPath=parsed.messages.length>0?parsed.messages[0]:void 0;result2=await exportFromFile(parsed.export,outputPath)}catch(error){let message=error instanceof Error?error.message:"Failed to export session";console.error(source_default.red(`Error: ${message}`)),process.exit(1)}console.log(`Exported to: ${result2}`),process.exit(0)}let appMode=resolveAppMode(parsed,process.stdin.isTTY,process.stdout.isTTY);appMode!=="interactive"&&!isPlainRuntimeMetadataCommand(parsed)&&takeOverStdout(),parsed.mode==="rpc"&&parsed.fileArgs.length>0&&(console.error(source_default.red("Error: @file arguments are not supported in RPC mode")),process.exit(1)),validateForkFlags(parsed),validateSessionIdFlags(parsed);let{migratedAuthProviders:migratedProviders,deprecationWarnings}=runMigrations(cwd);time("runMigrations");let startupSettingsManager=SettingsManager.create(cwd,agentDir),startupSettingsDiagnostics=collectSettingsDiagnostics(startupSettingsManager);appMode==="interactive"&&!parsed.help&&parsed.listModels===void 0&&shouldRunFirstTimeSetup()&&(await showFirstTimeSetup(startupSettingsManager),time("firstTimeSetup")),appMode==="interactive"&&parsed.useTheme!==void 0&&startupSettingsManager.applyOverrides({theme:parsed.useTheme});let envSessionDir=process.env[ENV_SESSION_DIR],sessionDir=(parsed.sessionDir?normalizePath(parsed.sessionDir):void 0)??(envSessionDir?expandTildePath(envSessionDir):void 0)??startupSettingsManager.getSessionDir(),sessionManager=await createSessionManager(parsed,cwd,sessionDir,startupSettingsManager),missingSessionCwdIssue=getMissingSessionCwdIssue(sessionManager,cwd);if(missingSessionCwdIssue)if(appMode==="interactive"){let selectedCwd=await promptForMissingSessionCwd(missingSessionCwdIssue,startupSettingsManager);selectedCwd||process.exit(0),sessionManager=SessionManager.open(missingSessionCwdIssue.sessionFile,sessionDir,selectedCwd)}else console.error(source_default.red(new MissingSessionCwdError(missingSessionCwdIssue).message)),process.exit(1);if(parsed.name!==void 0){let name=normalizeSessionName(parsed.name);name===void 0&&(console.error(source_default.red("Error: --name requires a non-empty value")),process.exit(1)),sessionManager.appendSessionInfo(name)}time("createSessionManager");let trustStore=new ProjectTrustStore(agentDir),sessionCwd=sessionManager.getCwd(),autoTrustOnReloadCwd=parsed.projectTrustOverride===void 0&&!hasTrustRequiringProjectResources(sessionCwd)?sessionCwd:void 0,trustPromptMode=parsed.help||parsed.listModels!==void 0?"print":appMode,projectTrustByCwd=new Map,resolvedExtensionPaths=resolveCliPaths(cwd,parsed.extensions),resolvedSkillPaths=resolveCliPaths(cwd,parsed.skills),resolvedPromptTemplatePaths=resolveCliPaths(cwd,parsed.promptTemplates),resolvedThemePaths=resolveCliPaths(cwd,parsed.themes),createRuntime=async({cwd:cwd2,agentDir:agentDir2,sessionManager:sessionManager2,sessionStartEvent,projectTrustContext})=>{let isInitialRuntime=sessionStartEvent===void 0,projectTrustDiagnostics=[],cachedProjectTrust=projectTrustByCwd.get(cwd2),hasTrustRequiringResources=hasTrustRequiringProjectResources(cwd2),shouldResolveProjectTrust=parsed.projectTrustOverride===void 0&&cachedProjectTrust===void 0&&hasTrustRequiringResources,projectTrusted=shouldResolveProjectTrust?!1:cachedProjectTrust??parsed.projectTrustOverride??(!hasTrustRequiringResources||trustStore.get(cwd2)===!0),runtimeSettingsManager=SettingsManager.create(cwd2,agentDir2,{projectTrusted}),services2=await createAgentSessionServices({cwd:cwd2,agentDir:agentDir2,settingsManager:runtimeSettingsManager,modelRuntimeSignal:AbortSignal.timeout(15e3),extensionFlagValues:parsed.unknownFlags,resourceLoaderReloadOptions:shouldResolveProjectTrust?{resolveProjectTrust:async({extensionsResult})=>{let trusted=await resolveProjectTrusted({cwd:cwd2,trustStore,trustOverride:parsed.projectTrustOverride,defaultProjectTrust:startupSettingsManager.getDefaultProjectTrust(),extensionsResult,projectTrustContext:projectTrustContext??createProjectTrustContext({cwd:cwd2,mode:isInitialRuntime?trustPromptMode:appMode,settingsManager:startupSettingsManager,hasUI:isInitialRuntime&&trustPromptMode==="interactive"}),onExtensionError:message=>projectTrustDiagnostics.push({type:"warning",message})});return projectTrustByCwd.set(cwd2,trusted),trusted}}:void 0,resourceLoaderOptions:{additionalExtensionPaths:resolvedExtensionPaths,additionalSkillPaths:resolvedSkillPaths,additionalPromptTemplatePaths:resolvedPromptTemplatePaths,additionalThemePaths:resolvedThemePaths,noExtensions:parsed.noExtensions,disabledBuiltinExtensions:parsed.noMcp?["mcp"]:void 0,noSkills:parsed.noSkills,noPromptTemplates:parsed.noPromptTemplates,noThemes:parsed.noThemes,noContextFiles:parsed.noContextFiles,systemPrompt:parsed.systemPrompt,appendSystemPrompt:parsed.appendSystemPrompt,extensionFactories}}),{settingsManager:settingsManager2,modelRuntime:modelRuntime2,resourceLoader:resourceLoader2}=services2,diagnostics=[...projectTrustDiagnostics,...services2.diagnostics,...collectSettingsDiagnostics(settingsManager2),...resourceLoader2.getExtensions().errors.map(({path:path14,error})=>({type:"error",message:`Failed to load extension "${path14}": ${error}`})),...(resourceLoader2.getExtensions().warnings??[]).map(({path:path14,warning})=>({type:"warning",message:`Extension package "${path14}": ${warning}`}))],modelPatterns=parsed.models??settingsManager2.getEnabledModels(),scopedModels=modelPatterns&&modelPatterns.length>0?await resolveModelScope(modelPatterns,modelRuntime2,{signal:AbortSignal.timeout(15e3)}):[],{options:sessionOptions,cliThinkingFromModel,diagnostics:sessionOptionDiagnostics}=buildSessionOptions(parsed,scopedModels,sessionManager2.buildSessionContext().messages.length>0,modelRuntime2,settingsManager2);diagnostics.push(...sessionOptionDiagnostics),parsed.apiKey&&(sessionOptions.model?await modelRuntime2.setRuntimeApiKey(sessionOptions.model.provider,parsed.apiKey):diagnostics.push({type:"error",message:"--api-key requires a model to be specified via --model, --provider/--model, or --models"}));let created=await createAgentSessionFromServices({services:services2,sessionManager:sessionManager2,sessionStartEvent,model:sessionOptions.model,thinkingLevel:sessionOptions.thinkingLevel,scopedModels:sessionOptions.scopedModels,tools:sessionOptions.tools,excludeTools:sessionOptions.excludeTools,noTools:sessionOptions.noTools,customTools:sessionOptions.customTools}),cliThinkingOverride=parsed.thinking!==void 0||cliThinkingFromModel;return created.session.model&&cliThinkingOverride&&created.session.setThinkingLevel(created.session.thinkingLevel),{...created,services:services2,diagnostics}};time("createRuntime");let runtime=await createAgentSessionRuntime(createRuntime,{cwd:sessionManager.getCwd(),agentDir,sessionManager});time("createAgentSessionRuntime");let{services,session,modelFallbackMessage}=runtime,{settingsManager,modelRuntime,resourceLoader}=services;if(setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),applyHttpProxySettings(settingsManager.getGlobalSettings().httpProxy),configureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs()),parsed.help){reportDiagnostics(startupSettingsDiagnostics);let extensionFlags=resourceLoader.getExtensions().extensions.flatMap(extension=>Array.from(extension.flags.values()));printHelp(extensionFlags),process.exit(0)}if(parsed.listModels!==void 0){reportDiagnostics(startupSettingsDiagnostics);let searchPattern=typeof parsed.listModels=="string"?parsed.listModels:void 0;await listModels(modelRuntime,searchPattern,AbortSignal.timeout(15e3)),process.exit(0)}let stdinContent;appMode!=="rpc"&&(stdinContent=await readPipedStdin(),stdinContent!==void 0&&appMode==="interactive"&&(appMode="print")),time("readPipedStdin");let{initialMessage,initialImages}=await prepareInitialMessage(parsed,stdinContent);time("prepareInitialMessage"),initTheme(settingsManager.getTheme(),appMode==="interactive"),time("initTheme"),appMode==="interactive"&&deprecationWarnings.length>0&&await showDeprecationWarnings(deprecationWarnings),time("resolveModelScope");let startupDiagnostics=deduplicateDiagnostics([...startupSettingsDiagnostics,...runtime.diagnostics]),hasRuntimeErrors=runtime.diagnostics.some(diagnostic=>diagnostic.type==="error");(appMode!=="interactive"||hasRuntimeErrors)&&reportDiagnostics(startupDiagnostics),hasRuntimeErrors&&(runtime.diagnostics.some(diagnostic=>diagnostic.message.includes("Failed to load extension"))&&console.error(source_default.yellow(EXTENSION_LOAD_FAILURE_HINT)),process.exit(1)),time("createAgentSession"),appMode!=="interactive"&&!session.model&&(console.error(source_default.red(formatNoModelsAvailableMessage())),process.exit(1));let startupBenchmark=isTruthyEnvFlag2(process.env.PI_STARTUP_BENCHMARK);if(startupBenchmark&&appMode!=="interactive"&&(console.error(source_default.red("Error: PI_STARTUP_BENCHMARK only supports interactive mode")),process.exit(1)),!offlineMode&&appMode==="rpc"){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);modelRuntime.refresh({signal:controller.signal}).catch(()=>{}).finally(()=>clearTimeout(timeout))}if(appMode==="rpc")printTimings(),await runRpcMode(runtime);else if(appMode==="interactive"){let interactiveMode=new InteractiveMode(runtime,{migratedProviders,startupDiagnostics,modelFallbackMessage,autoTrustOnReloadCwd,initialMessage,initialImages,initialMessages:parsed.messages,verbose:parsed.verbose,tuiMode:parsed.tuiMode,initialThemeSetting:parsed.useTheme});if(startupBenchmark){await interactiveMode.init(),time("interactiveMode.init"),await new Promise(resolve20=>setTimeout(resolve20,150)),interactiveMode.stop(),stopThemeWatcher(),printTimings(),process.stdout.writableLength>0&&await new Promise(resolve20=>process.stdout.once("drain",resolve20)),process.stderr.writableLength>0&&await new Promise(resolve20=>process.stderr.once("drain",resolve20));return}printTimings(),await interactiveMode.run()}else{printTimings();let exitCode=await runPrintMode(runtime,{mode:toPrintOutputMode(appMode),messages:parsed.messages,initialMessage,initialImages});stopThemeWatcher(),restoreStdout(),exitCode!==0&&(process.exitCode=exitCode);return}}export{getPackageDir,getReadmePath,getDocsPath,getExamplesPath,DISTRIBUTION_PACKAGE_NAME,APP_NAME,CONFIG_DIR_NAME,VERSION,getAgentDir,configureHttpDispatcher,build_exports,value_exports2 as value_exports,compile_exports,Container,SelectList,dist_exports,SettingsManager,parseArgs,resolveModelScopeWithDiagnostics,resolveCliModel,all_exports,getShellConfig,getPowerShellConfig,readStoredCredential,compat_exports,VIRTUAL_MODEL_STATE_ENTRY,CredentialSynchronizationError,ModelRuntime,convertToPng,resizeImage,formatDimensionNote,detectSupportedImageMimeTypeFromFile,createSyntheticSourceInfo,DefaultPackageManager,Theme,getAvailableThemes,initTheme,highlightCode,getLanguageFromPath,getMarkdownTheme,getSelectListTheme,getSettingsListTheme,DynamicBorder,keyText,keyHint,rawKeyHint,ExtensionInputComponent,ExtensionSelectorComponent,SessionSelectorComponent,parseFrontmatter,stripFrontmatter,loadSkillsFromDir,formatSkillsForPrompt,loadSkills,TaskRuntime,ExtensionRunner,convertToLlm,CURRENT_SESSION_VERSION,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,SessionManager,createEventBus,dist_exports2,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES2 as DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,serializeConversation,DEFAULT_COMPACTION_SETTINGS,calculateContextTokens,getLastAssistantUsage,shouldCompact,estimateTokens2 as estimateTokens,findTurnStartIndex,findCutPoint,generateSummary,generateSummaryWithUsage,compact,collectEntriesForBranchSummary,prepareBranchEntries,generateBranchSummary,defineTool,isBashToolResult,isPowerShellToolResult,isReadToolResult,isEditToolResult,isWriteToolResult,isGrepToolResult,isFindToolResult,isLsToolResult,isToolCallEventType,wrapRegisteredTool,wrapRegisteredTools,ModelRegistry,generateUnifiedPatch,generateDiffString,withFileMutationQueue,renderDiff,formatReadLineRange,createEditToolDefinition,createEditTool,createFindToolDefinition,createFindTool,createGrepToolDefinition,createGrepTool,createLsToolDefinition,createLsTool,truncateToVisualLines,createLocalBashOperations,createBashToolDefinition,createBashTool,createLocalPowerShellOperations,createPowerShellToolDefinition,createPowerShellTool,createReadToolDefinition,createReadTool,createWriteToolDefinition,createWriteTool,createCodingTools,createReadOnlyTools,parseSkillBlock,AgentSession,createAgentSession,hasTrustRequiringProjectResources,ProjectTrustStore,createCodemodeExtension,copyToClipboard,createMcpExtension,createToolSearchExtension,BorderedLoader,ExtensionEditorComponent,ArminComponent,AssistantMessageComponent,BashExecutionComponent,BranchSummaryMessageComponent,CompactionSummaryMessageComponent,CustomEditor,CustomMessageComponent,FooterComponent,LoginDialogComponent,ModelSelectorComponent,OAuthSelectorComponent,SettingsSelectorComponent,SkillInvocationMessageComponent,ThinkingSelectorComponent,ToolExecutionComponent,TreeSelectorComponent,UserMessageComponent,UserMessageSelectorComponent,InteractiveMode,runPrintMode,RpcClient,runRpcMode,createExtensionRuntime,discoverAndLoadExtensions,loadProjectContextFiles,DefaultResourceLoader,createAgentSessionServices,createAgentSessionFromServices,AgentSessionRuntime,createAgentSessionRuntime,main};
|