@bingjiang0611/rotom 0.1.24 → 0.1.25
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/THIRD_PARTY_NOTICES.md +2 -2
- package/extensions/third-party/node_modules/.package-lock.json +3 -3
- package/extensions/third-party/node_modules/sol-pi/UPSTREAM.md +7 -3
- package/extensions/third-party/node_modules/sol-pi/package.json +1 -1
- package/extensions/third-party/node_modules/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +5 -2
- package/extensions/third-party/node_modules/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +21 -0
- package/extensions/third-party/node_modules/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +7 -1
- package/extensions/third-party/package-lock.json +4 -4
- package/extensions/third-party/package.json +1 -1
- package/extensions/third-party/vendor/README.md +5 -4
- package/extensions/third-party/vendor/sol-pi-0.1.0-rotom.1.tgz +0 -0
- package/package.json +9 -9
- package/runtime/pi/fork-build.json +23 -23
- package/runtime/pi/node_modules/.package-lock.json +29 -29
- package/runtime/pi/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +30 -7
- package/runtime/pi/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/runtime/pi/node_modules/@earendil-works/pi-ai/package.json +3 -3
- package/runtime/pi/node_modules/@earendil-works/pi-codemode/package.json +2 -2
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/chunks/{chunk-3CD5ZAQX.js → chunk-6NUCYK64.js} +4 -4
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/chunks/{chunk-XQ3UQBJ2.js → chunk-DSV77X2M.js} +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/chunks/{virtual-modules-C5BH2VI2.js → virtual-modules-INPREDLP.js} +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/cli-runtime.js +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/index.js +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/bundle/rpc-entry.js +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +4 -0
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +1 -0
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +8 -0
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +1 -0
- package/runtime/pi/node_modules/@earendil-works/pi-coding-agent/package.json +7 -7
- package/runtime/pi/node_modules/@earendil-works/pi-mcp/package.json +2 -2
- package/runtime/pi/node_modules/@earendil-works/pi-telemetry/package.json +2 -2
- package/runtime/pi/node_modules/@earendil-works/pi-tui/package.json +2 -2
- package/runtime/pi/package-lock.json +37 -37
- package/runtime/pi/package.json +15 -15
- package/runtime/pi/vendor/earendil-works-pi-agent-core-1.3.0-rotom.2.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-ai-1.3.0-rotom.2.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-codemode-1.3.0-rotom.2.tgz +0 -0
- package/runtime/pi/vendor/{earendil-works-pi-coding-agent-1.3.0-rotom.1.tgz → earendil-works-pi-coding-agent-1.3.0-rotom.2.tgz} +0 -0
- package/runtime/pi/vendor/earendil-works-pi-mcp-1.3.0-rotom.2.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-telemetry-1.3.0-rotom.2.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-tui-1.3.0-rotom.2.tgz +0 -0
- package/runtime/product-config.mjs +4 -4
- package/extensions/third-party/vendor/sol-pi-0.1.0-rotom.0.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-agent-core-1.3.0-rotom.1.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-ai-1.3.0-rotom.1.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-codemode-1.3.0-rotom.1.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-mcp-1.3.0-rotom.1.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-telemetry-1.3.0-rotom.1.tgz +0 -0
- package/runtime/pi/vendor/earendil-works-pi-tui-1.3.0-rotom.1.tgz +0 -0
|
@@ -520,7 +520,7 @@ In addition to the tools above, you may have access to other custom tools depend
|
|
|
520
520
|
- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing
|
|
521
521
|
- 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}>
|
|
522
522
|
${content}
|
|
523
|
-
</${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,text]of Object.entries(current))previous[name]!==text&&(patch[name]=text);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={};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 result=candidate.result;if(typeof result!="object"||result===null)return!1;let resultRecord=result;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{extensions;runtime;uiContext;mode="print";cwd;sessionManager;modelRegistry;errorListeners=new Set;getModel=()=>{};getScopedModels=()=>[];isIdleFn=()=>!0;isProjectTrustedFn=()=>!0;getSignalFn=()=>{};waitForIdleFn=async()=>{};abortFn=()=>{};hasPendingMessagesFn=()=>!1;getContextUsageFn=()=>{};compactFn=()=>{};getSystemPromptFn=()=>"";getSystemPromptOptionsFn=()=>normalizeBuildSystemPromptOptions({cwd:this.cwd});executeToolFn;getCallableToolsFn=()=>[];reportedMcpServers=new Set;newSessionHandler=async()=>({cancelled:!1});forkHandler=async()=>({cancelled:!1});navigateTreeHandler=async()=>({cancelled:!1});switchSessionHandler=async()=>({cancelled:!1});reloadHandler=async()=>{};shutdownHandler=()=>{};shortcutDiagnostics=[];commandDiagnostics=[];staleMessage;uiPromptDepth=0;activeUIPrompt;constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions,contextActions,providerActions){this.runtime.sendMessage=actions.sendMessage,this.runtime.sendUserMessage=actions.sendUserMessage,this.runtime.appendEntry=actions.appendEntry,this.runtime.setSessionName=actions.setSessionName,this.runtime.getSessionName=actions.getSessionName,this.runtime.setLabel=actions.setLabel,this.runtime.getActiveTools=actions.getActiveTools,this.runtime.getAllTools=actions.getAllTools,this.runtime.getSettings=actions.getSettings,this.runtime.setActiveTools=actions.setActiveTools,this.runtime.refreshTools=actions.refreshTools,this.runtime.getCommands=actions.getCommands,this.runtime.setModel=actions.setModel,this.runtime.getThinkingLevel=actions.getThinkingLevel,this.runtime.setThinkingLevel=actions.setThinkingLevel,this.runtime.createContext=()=>this.createContext(),this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>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(actions){if(actions){this.waitForIdleFn=actions.waitForIdle,this.newSessionHandler=actions.newSession,this.forkHandler=actions.fork,this.navigateTreeHandler=actions.navigateTree,this.switchSessionHandler=actions.switchSession,this.reloadHandler=actions.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(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.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??[]),resolve16=index3=>index3<resolvers.length?resolvers[index3](toolName,()=>resolve16(index3+1)):base();return resolve16(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 ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}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),valid4=!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),valid4=!0}catch(err){valid4=!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 valid4?{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(),result;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&&(result=handlerResult,result.cancel))return result}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 result}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 result=await handler(event,ctx);result?.action!==void 0&&(action=result.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(),result;for(let{handlers}of snapshotEventHandlers(this.extensions,"tool_call"))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result=handlerResult,result.block))return result}return result}async emitUserBash(event){let ctx=this.createContext();for(let{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 result=handlerResult;result.message&&messages.push(result.message),result.systemPrompt!==void 0&&(currentOptions.forceSystemPrompt=result.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 result=await handler({type:"resources_discover",cwd,reason},ctx);result?.skillPaths?.length&&skillPaths.push(...result.skillPaths.map(path10=>({path:path10,extensionPath:ext2.path}))),result?.promptPaths?.length&&promptPaths.push(...result.promptPaths.map(path10=>({path:path10,extensionPath:ext2.path}))),result?.themePaths?.length&&themePaths.push(...result.themePaths.map(path10=>({path:path10,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(text,images,source,streamingBehavior){let ctx=this.createContext(),currentText=text,currentImages=images;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"input"))for(let handler of handlers)try{let result=await handler({type:"input",text:currentText,images:currentImages,source,streamingBehavior},ctx);if(result?.action==="handled")return result;result?.action==="transform"&&(currentText=result.text,currentImages=result.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!==text||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:
|
|
523
|
+
</${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,text]of Object.entries(current))previous[name]!==text&&(patch[name]=text);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={};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 result=candidate.result;if(typeof result!="object"||result===null)return!1;let resultRecord=result;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{extensions;runtime;uiContext;mode="print";cwd;sessionManager;modelRegistry;errorListeners=new Set;getModel=()=>{};getScopedModels=()=>[];isIdleFn=()=>!0;isProjectTrustedFn=()=>!0;getSignalFn=()=>{};waitForIdleFn=async()=>{};abortFn=()=>{};hasPendingMessagesFn=()=>!1;getContextUsageFn=()=>{};compactFn=()=>{};getSystemPromptFn=()=>"";getSystemPromptOptionsFn=()=>normalizeBuildSystemPromptOptions({cwd:this.cwd});executeToolFn;getCallableToolsFn=()=>[];reportedMcpServers=new Set;newSessionHandler=async()=>({cancelled:!1});forkHandler=async()=>({cancelled:!1});navigateTreeHandler=async()=>({cancelled:!1});switchSessionHandler=async()=>({cancelled:!1});reloadHandler=async()=>{};shutdownHandler=()=>{};shortcutDiagnostics=[];commandDiagnostics=[];staleMessage;uiPromptDepth=0;activeUIPrompt;constructor(extensions,runtime,cwd,sessionManager,modelRegistry){this.extensions=extensions,this.runtime=runtime,this.uiContext=noOpUIContext,this.cwd=cwd,this.sessionManager=sessionManager,this.modelRegistry=modelRegistry}bindCore(actions,contextActions,providerActions){this.runtime.sendMessage=actions.sendMessage,this.runtime.sendUserMessage=actions.sendUserMessage,this.runtime.appendEntry=actions.appendEntry,this.runtime.appendUsage=actions.appendUsage,this.runtime.setSessionName=actions.setSessionName,this.runtime.getSessionName=actions.getSessionName,this.runtime.setLabel=actions.setLabel,this.runtime.getActiveTools=actions.getActiveTools,this.runtime.getAllTools=actions.getAllTools,this.runtime.getSettings=actions.getSettings,this.runtime.setActiveTools=actions.setActiveTools,this.runtime.refreshTools=actions.refreshTools,this.runtime.getCommands=actions.getCommands,this.runtime.setModel=actions.setModel,this.runtime.getThinkingLevel=actions.getThinkingLevel,this.runtime.setThinkingLevel=actions.setThinkingLevel,this.runtime.createContext=()=>this.createContext(),this.getModel=contextActions.getModel,this.getScopedModels=contextActions.getScopedModels,this.isIdleFn=contextActions.isIdle,this.isProjectTrustedFn=contextActions.isProjectTrusted,this.getSignalFn=contextActions.getSignal,this.abortFn=contextActions.abort,this.hasPendingMessagesFn=contextActions.hasPendingMessages,this.shutdownHandler=contextActions.shutdown,this.getContextUsageFn=contextActions.getContextUsage,this.compactFn=contextActions.compact,this.getSystemPromptFn=contextActions.getSystemPrompt,this.getSystemPromptOptionsFn=contextActions.getSystemPromptOptions??(()=>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(actions){if(actions){this.waitForIdleFn=actions.waitForIdle,this.newSessionHandler=actions.newSession,this.forkHandler=actions.fork,this.navigateTreeHandler=actions.navigateTree,this.switchSessionHandler=actions.switchSession,this.reloadHandler=actions.reload;return}this.waitForIdleFn=async()=>{},this.newSessionHandler=async()=>({cancelled:!1}),this.forkHandler=async()=>({cancelled:!1}),this.navigateTreeHandler=async()=>({cancelled:!1}),this.switchSessionHandler=async()=>({cancelled:!1}),this.reloadHandler=async()=>{}}setUIContext(uiContext,mode="print"){this.uiContext=uiContext?this.wrapUIPromptContext(uiContext):noOpUIContext,this.mode=mode}wrapUIPromptContext(ui){return{...ui,select:(title,options,opts)=>this.withUIPrompt("select",title,()=>ui.select(title,options,opts)),confirm:(title,message,opts)=>this.withUIPrompt("confirm",title,()=>ui.confirm(title,message,opts)),input:(title,placeholder,opts)=>this.withUIPrompt("input",title,()=>ui.input(title,placeholder,opts)),editor:(title,prefill)=>this.withUIPrompt("editor",title,()=>ui.editor(title,prefill)),custom:(factory,options)=>this.withUIPrompt("custom",void 0,()=>ui.custom(factory,options))}}withUIPrompt(kind,title,run){this.uiPromptDepth++===0&&(this.activeUIPrompt={kind,title},this.emitUIPromptEvent({type:"ui_prompt_start",reason:"ui_prompt",kind,...title?{title}:{}}));let finish=()=>{if(--this.uiPromptDepth>0)return;this.uiPromptDepth=0;let prompt=this.activeUIPrompt??{kind,title};this.activeUIPrompt=void 0,this.emitUIPromptEvent({type:"ui_prompt_end",reason:"ui_prompt",kind:prompt.kind,...prompt.title?{title:prompt.title}:{}})};try{return run().finally(finish)}catch(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.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??[]),resolve16=index3=>index3<resolvers.length?resolvers[index3](toolName,()=>resolve16(index3+1)):base();return resolve16(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 ui(){return runner.assertActive(),runner.uiContext},get mode(){return runner.assertActive(),runner.mode},get hasUI(){return runner.assertActive(),runner.hasUI()},get cwd(){return runner.assertActive(),runner.cwd},get sessionManager(){return runner.assertActive(),runner.sessionManager},get modelRegistry(){return runner.assertActive(),runner.modelRegistry},get model(){return runner.assertActive(),getModel2()},get scopedModels(){return runner.assertActive(),getScopedModels()},get thinkingLevel(){return runner.assertActive(),runner.runtime.getThinkingLevel()},isIdle:()=>(runner.assertActive(),runner.isIdleFn()),isProjectTrusted:()=>(runner.assertActive(),runner.isProjectTrustedFn()),get signal(){return runner.assertActive(),runner.getSignalFn()},abort:()=>{runner.assertActive(),runner.abortFn()},hasPendingMessages:()=>(runner.assertActive(),runner.hasPendingMessagesFn()),shutdown:()=>{runner.assertActive(),runner.shutdownHandler()},getContextUsage:()=>(runner.assertActive(),runner.getContextUsageFn()),compact:options=>{runner.assertActive(),runner.compactFn(options)},getSystemPrompt:()=>(runner.assertActive(),runner.getSystemPromptFn())}}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),valid4=!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),valid4=!0}catch(err){valid4=!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 valid4?{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(),result;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&&(result=handlerResult,result.cancel))return result}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 result}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 result=await handler(event,ctx);result?.action!==void 0&&(action=result.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(),result;for(let{handlers}of snapshotEventHandlers(this.extensions,"tool_call"))for(let handler of handlers){let handlerResult=await handler(event,ctx);if(handlerResult&&(result=handlerResult,result.block))return result}return result}async emitUserBash(event){let ctx=this.createContext();for(let{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 result=handlerResult;result.message&&messages.push(result.message),result.systemPrompt!==void 0&&(currentOptions.forceSystemPrompt=result.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 result=await handler({type:"resources_discover",cwd,reason},ctx);result?.skillPaths?.length&&skillPaths.push(...result.skillPaths.map(path10=>({path:path10,extensionPath:ext2.path}))),result?.promptPaths?.length&&promptPaths.push(...result.promptPaths.map(path10=>({path:path10,extensionPath:ext2.path}))),result?.themePaths?.length&&themePaths.push(...result.themePaths.map(path10=>({path:path10,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(text,images,source,streamingBehavior){let ctx=this.createContext(),currentText=text,currentImages=images;for(let{ext:ext2,handlers}of snapshotEventHandlers(this.extensions,"input"))for(let handler of handlers)try{let result=await handler({type:"input",text:currentText,images:currentImages,source,streamingBehavior},ctx);if(result?.action==="handled")return result;result?.action==="transform"&&(currentText=result.text,currentImages=result.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!==text||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:
|
|
524
524
|
|
|
525
525
|
<summary>
|
|
526
526
|
`,COMPACTION_SUMMARY_SUFFIX=`
|
|
@@ -547,7 +547,7 @@ Command exited with code ${msg.exitCode}`),msg.truncated&&msg.fullOutputPath&&(t
|
|
|
547
547
|
`);else{if(!this._hasConversation())return;let fd=openSync(this.sessionFile,"wx");try{for(let e of this.fileEntries)writeFileSync3(fd,`${JSON.stringify(e)}
|
|
548
548
|
`)}finally{closeSync(fd)}this.flushed=!0}}_appendEntry(entry){this.fileEntries.push(entry),this.byId.set(entry.id,entry),this.leafId=entry.id,this._persist(entry)}appendMessage(message){let entry={type:"message",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),message};return this._appendEntry(entry),entry.id}appendThinkingLevelChange(thinkingLevel){let entry={type:"thinking_level_change",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),thinkingLevel};return this._appendEntry(entry),entry.id}appendModelChange(provider,modelId){let entry={type:"model_change",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),provider,modelId};return this._appendEntry(entry),entry.id}appendUsage(kind,provider,model,usage,note){let entry={type:"usage",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),kind,provider,model,usage,...note?{note}:{}};return this._appendEntry(entry),entry}appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromHook,usage){let timestamp=new Date().toISOString(),systemMessage=getCurrentSystemMessage(this.buildSessionProjection().messages),id=generateId(this.byId),entry={type:"compaction",id,parentId:this.leafId,timestamp,summary,firstKeptEntryId:firstKeptEntryId??id,tokensBefore,details,usage,fromHook,...systemMessage?{systemMessage:{...systemMessage,timestamp:new Date(timestamp).getTime()}}:{}};return this._appendEntry(entry),entry.id}appendCustomEntry(customType,data){let entry={type:"custom",customType,data,id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendSessionInfo(name){let sanitizedName=name.replace(/[\r\n]+/g," ").trim(),entry={type:"session_info",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),name:sanitizedName};return this._appendEntry(entry),entry.id}getSessionName(){for(let i=this.fileEntries.length-1;i>=0;i--){let entry=this.fileEntries[i];if(entry.type==="session_info")return entry.name?.trim()||void 0}}appendCustomMessageEntry(customType,content,display,details){let entry={type:"custom_message",customType,content,display,details,id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendContextEdit(targetId,replacement){if(replacement!==null&&(typeof replacement!="object"||!("content"in replacement)||typeof replacement.content!="string"&&!Array.isArray(replacement.content)))throw new Error("Context edit replacement must be null or contain string/array content");let target=this.byId.get(targetId);if(!target)throw new Error(`Entry ${targetId} not found`);if(!this.getBranch().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} is not on the active branch`);if(!(target.type==="custom_message"||target.type==="message"&&(target.message.role==="user"||target.message.role==="assistant"||target.message.role==="toolResult")))throw new Error(`Entry ${targetId} does not contribute editable model content`);let targetRole=target.type==="message"?target.message.role:"custom",normalizedReplacement=replacement!==null&&(targetRole==="assistant"||targetRole==="toolResult")&&typeof replacement.content=="string"?{content:[{type:"text",text:replacement.content}]}:replacement,entry={type:"context_edit",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,replacement:normalizedReplacement};return this._appendEntry(entry),entry.id}getLeafId(){return this.leafId}getLeafEntry(){return this.leafId?this.byId.get(this.leafId):void 0}getEntry(id){return this.byId.get(id)}getChildren(parentId){let children=[];for(let entry of this.byId.values())entry.parentId===parentId&&children.push(entry);return children}getLabel(id){return this.labelsById.get(id)}appendLabelChange(targetId,label){if(!this.byId.has(targetId))throw new Error(`Entry ${targetId} not found`);let entry={type:"label",id:generateId(this.byId),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,label};return this._appendEntry(entry),label?(this.labelsById.set(targetId,label),this.labelTimestampsById.set(targetId,entry.timestamp)):(this.labelsById.delete(targetId),this.labelTimestampsById.delete(targetId)),entry.id}getBranch(fromId){let path10=[],startId=fromId??this.leafId,current=startId?this.byId.get(startId):void 0;for(;current;)path10.push(current),current=current.parentId?this.byId.get(current.parentId):void 0;return path10.reverse(),path10}buildContextEntries(){return buildContextEntries(this.getEntries(),this.leafId,this.byId)}buildSessionProjection(){return buildSessionProjection(this.getEntries(),this.leafId,this.byId)}buildSessionContext(){let{messages,thinkingLevel,model}=this.buildSessionProjection();return{messages,thinkingLevel,model}}getHeader(){let h=this.fileEntries.find(e=>e.type==="session");return h||null}getEntryCount(){return this.byId.size}getEntries(){return this.fileEntries.filter(e=>e.type!=="session")}getTree(){let entries=this.getEntries(),nodeMap=new Map,roots=[];for(let entry of entries){let label=this.labelsById.get(entry.id),labelTimestamp=this.labelTimestampsById.get(entry.id);nodeMap.set(entry.id,{entry,children:[],label,labelTimestamp})}for(let entry of entries){let node=nodeMap.get(entry.id);if(entry.parentId===null||entry.parentId===entry.id)roots.push(node);else{let parent=nodeMap.get(entry.parentId);parent?parent.children.push(node):roots.push(node)}}let stack=[...roots];for(;stack.length>0;){let node=stack.pop();node.children.sort((a,b)=>new Date(a.entry.timestamp).getTime()-new Date(b.entry.timestamp).getTime()),stack.push(...node.children)}return roots}branch(branchFromId){if(!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);this.leafId=branchFromId}resetLeaf(){this.leafId=null}branchWithSummary(branchFromId,summary,details,fromHook,usage){if(branchFromId!==null&&!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let fromId=this.leafId??"root";this.leafId=branchFromId;let entry={type:"branch_summary",id:generateId(this.byId),parentId:branchFromId,timestamp:new Date().toISOString(),fromId,summary,details,usage,fromHook};return this._appendEntry(entry),entry.id}createBranchedSession(leafId){let previousSessionFile=this.sessionFile,path10=this.getBranch(leafId);if(path10.length===0)throw new Error(`Entry ${leafId} not found`);let pathWithoutLabels=[],replacementByLabelId=new Map,pendingLabelIds=[],pathParentId=null;for(let entry of path10){if(entry.type==="label"){pendingLabelIds.push(entry.id);continue}for(let labelId of pendingLabelIds)replacementByLabelId.set(labelId,entry.id);pendingLabelIds.length=0,pathWithoutLabels.push(entry.type==="compaction"?{...entry,parentId:pathParentId,firstKeptEntryId:entry.firstKeptEntryId===entry.id?entry.id:replacementByLabelId.get(entry.firstKeptEntryId)??entry.firstKeptEntryId}:{...entry,parentId:pathParentId}),pathParentId=entry.id}let newSessionId=createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join8(this.getSessionDir(),`${fileTimestamp}_${newSessionId}.jsonl`),header={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:this.cwd,parentSession:this.persist?previousSessionFile:void 0},pathEntryIds=new Set(pathWithoutLabels.map(e=>e.id)),labelsToWrite=[];for(let[targetId,label]of this.labelsById)pathEntryIds.has(targetId)&&labelsToWrite.push({targetId,label,timestamp:this.labelTimestampsById.get(targetId)});if(this.persist){let parentId2=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null,labelEntries2=[];for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set(pathEntryIds)),parentId:parentId2,timestamp:labelTimestamp,targetId,label};pathEntryIds.add(labelEntry.id),labelEntries2.push(labelEntry),parentId2=labelEntry.id}return this.fileEntries=[header,...pathWithoutLabels,...labelEntries2],this.sessionId=newSessionId,this.sessionFile=newSessionFile,this._buildIndex(),this._hasConversation()?(this._rewriteFile(),this.flushed=!0):this.flushed=!1,newSessionFile}let labelEntries=[],parentId=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null;for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set([...pathEntryIds,...labelEntries.map(e=>e.id)])),parentId,timestamp:labelTimestamp,targetId,label};labelEntries.push(labelEntry),parentId=labelEntry.id}this.fileEntries=[header,...pathWithoutLabels,...labelEntries],this.sessionId=newSessionId,this._buildIndex()}static create(cwd,sessionDir,options){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd);return new _SessionManager(cwd,dir,void 0,!0,options)}static open(path10,sessionDir,cwdOverride){let resolvedPath=resolvePath(path10),header=null,preloadedFileEntries;if(cwdOverride===void 0&&existsSync6(resolvedPath))try{header=readSessionHeader(resolvedPath)}catch(error){if(!(error instanceof SessionHeaderScanLimitError))throw error;preloadedFileEntries=loadEntriesFromFile(resolvedPath);let firstEntry=preloadedFileEntries[0];header=firstEntry?.type==="session"?firstEntry:null}let cwd=cwdOverride??(header?getSessionHeaderCwd(header):void 0)??process.cwd(),dir=sessionDir?normalizePath(sessionDir):resolve3(resolvedPath,"..");return new _SessionManager(cwd,dir,resolvedPath,!0,void 0,preloadedFileEntries)}static continueRecent(cwd,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),mostRecent=findMostRecentSession(dir,filterCwd?cwd:void 0);return mostRecent?new _SessionManager(cwd,dir,mostRecent,!0):new _SessionManager(cwd,dir,void 0,!0)}static inMemory(cwd=process.cwd(),options,entries){return new _SessionManager(cwd,"",void 0,!1,options,entries)}static forkFrom(sourcePath,targetCwd,sessionDir,options){let resolvedSourcePath=resolvePath(sourcePath),resolvedTargetCwd=resolvePath(targetCwd),sourceEntries=loadEntriesFromFile(resolvedSourcePath);if(sourceEntries.length===0)throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);if(!sourceEntries.find(e=>e.type==="session"))throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(resolvedTargetCwd);existsSync6(dir)||mkdirSync3(dir,{recursive:!0}),options?.id!==void 0&&assertValidSessionId(options.id);let newSessionId=options?.id??createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join8(dir,`${fileTimestamp}_${newSessionId}.jsonl`);writeFileSync3(newSessionFile,`${JSON.stringify({type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:resolvedTargetCwd,parentSession:resolvedSourcePath})}
|
|
549
549
|
`,{flag:"wx"});for(let entry of sourceEntries)entry.type!=="session"&&appendFileSync(newSessionFile,`${JSON.stringify(entry)}
|
|
550
|
-
`);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd);try{for(let file of readdirSync3(dir)){if(!file.endsWith(".jsonl"))continue;let path10=join8(dir,file),header=readSessionHeaderForDiscovery(path10);if(header?.id===id&&!(filterCwd&&!sessionCwdMatches(getSessionHeaderCwd(header),resolvedCwd)))return path10}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd),includeSession=session=>!filterCwd||sessionCwdMatches(session.cwd,resolvedCwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync6(sessionsDir))return[];let dirs=(await readdir(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join8(sessionsDir,entry.name)),allFiles=(await mapWithConcurrency(dirs,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async dir=>{try{return(await readdir(dir)).filter(file=>file.endsWith(".jsonl")).map(file=>join8(dir,file))}catch{return[]}},abortSignal)).flat(),candidates=await mapWithConcurrency(allFiles,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async path10=>{try{return{path:path10,stats:await stat(path10)}}catch{return{path:path10}}},abortSignal);candidates.sort((a,b)=>(b.stats?.mtimeMs??Number.NEGATIVE_INFINITY)-(a.stats?.mtimeMs??Number.NEGATIVE_INFINITY)||basename3(b.path).localeCompare(basename3(a.path)));let totalFiles=candidates.length,loaded=0,firstCandidateLoaded=!1,partialSessions=[],results=await buildSessionInfosWithConcurrency(candidates,(info,index3)=>{loaded++,index3===0&&(firstCandidateLoaded=!0),info&&partialSessions.push(info);let publishPartial=firstCandidateLoaded&&(index3===0||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles);progress?.(loaded,totalFiles,publishPartial?sortSessionInfos([...partialSessions]):void 0)},abortSignal);return sortSessionInfos(results.filter(info=>info!==null))}catch{return abortSignal?.throwIfAborted(),[]}}};import{EventEmitter as EventEmitter2}from"node:events";function createEventBus(){let emitter=new EventEmitter2;return{emit:(channel,data)=>{emitter.emit(channel,data)},on:(channel,handler)=>{let safeHandler=async data=>{try{await handler(data)}catch(err){console.error(`Event handler error (${channel}):`,err)}};return emitter.on(channel,safeHandler),()=>emitter.off(channel,safeHandler)},clear:()=>{emitter.removeAllListeners()}}}var dist_exports={};__export(dist_exports,{Agent:()=>Agent,agentLoop:()=>agentLoop,agentLoopContinue:()=>agentLoopContinue,runAgentLoop:()=>runAgentLoop,runAgentLoopContinue:()=>runAgentLoopContinue,runToolCall:()=>runToolCall,setDefaultStreamFn:()=>setDefaultStreamFn,streamProxy:()=>streamProxy});var defaultStreamFn;function setDefaultStreamFn(streamFn){defaultStreamFn=streamFn}function getDefaultStreamFn(){if(!defaultStreamFn)throw new Error("No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().");return defaultStreamFn}function agentLoop(prompts,context,config,signal,streamFn){let stream2=createAgentStream();return runAgentLoop(prompts,context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}function agentLoopContinue(context,config,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let stream2=createAgentStream();return runAgentLoopContinue(context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}async function runAgentLoop(prompts,context,config,emit,signal,streamFn){let initialMessages=declareToolChanges(context,prompts),newMessages=[...initialMessages],currentContext={...context,messages:[...context.messages,...initialMessages]};await emit({type:"agent_start"}),await emit({type:"turn_start"});for(let message of initialMessages)await emit({type:"message_start",message}),await emit({type:"message_end",message});return await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}async function runAgentLoopContinue(context,config,emit,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let newMessages=[],currentContext={...context};return await emit({type:"agent_start"}),await emit({type:"turn_start"}),await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}function createAgentStream(){return new EventStream(event=>event.type==="agent_end",event=>event.type==="agent_end"?event.messages:[])}async function runLoop(initialContext,newMessages,initialConfig,signal,emit,streamFunction){let currentContext=initialContext,config=initialConfig,lastCompletedTurn,explicitContinuation=!1,pendingMessages=await config.getSteeringMessages?.()||[];for(;;){let hasMoreToolCalls=!0;for(;hasMoreToolCalls||pendingMessages.length>0;){let preparedMessages=[];if(lastCompletedTurn){let nextTurnSnapshot=await config.prepareNextTurn?.(lastCompletedTurn);nextTurnSnapshot&&(currentContext=nextTurnSnapshot.context??currentContext,preparedMessages=nextTurnSnapshot.messages??[],config={...config,model:nextTurnSnapshot.model??config.model,reasoning:nextTurnSnapshot.thinkingLevel===void 0?config.reasoning:nextTurnSnapshot.thinkingLevel==="off"?void 0:nextTurnSnapshot.thinkingLevel}),pendingMessages.length===0&&(pendingMessages=await config.getSteeringMessages?.()||[]),await emit({type:"turn_start"})}for(let message2 of declareToolChanges(currentContext,[...preparedMessages,...pendingMessages]))await emit({type:"message_start",message:message2}),await emit({type:"message_end",message:message2}),currentContext.messages.push(message2),newMessages.push(message2);pendingMessages=[];let requestUpdate=await config.prepareRequest?.({context:currentContext,model:config.model,thinkingLevel:config.reasoning??"off"},signal);requestUpdate&&(currentContext=requestUpdate.context??currentContext,config={...config,model:requestUpdate.model??config.model,reasoning:requestUpdate.thinkingLevel===void 0?config.reasoning:requestUpdate.thinkingLevel==="off"?void 0:requestUpdate.thinkingLevel});let message=await streamAssistantResponse(currentContext,config,signal,emit,streamFunction);if(newMessages.push(message),message.stopReason==="error"||message.stopReason==="aborted"){lastCompletedTurn={message,toolResults:[],context:currentContext,newMessages},await config.finishTurn?.(lastCompletedTurn,signal),await emit({type:"turn_end",message,toolResults:[]}),await emit({type:"agent_end",messages:newMessages});return}let toolCalls=message.content.filter(c=>c.type==="toolCall"),toolResults=[];if(hasMoreToolCalls=!1,toolCalls.length>0){let executedToolBatch=message.stopReason==="length"?await failToolCallsFromTruncatedMessage(toolCalls,emit):await executeToolCalls(currentContext,message,config,signal,emit);toolResults.push(...executedToolBatch.messages),hasMoreToolCalls=!executedToolBatch.terminate;for(let result of toolResults)currentContext.messages.push(result),newMessages.push(result)}lastCompletedTurn={message,toolResults,context:currentContext,newMessages};let decision=await config.finishTurn?.(lastCompletedTurn,signal);if(await emit({type:"turn_end",message,toolResults}),decision?.action==="end"){await emit({type:"agent_end",messages:newMessages});return}if(signal?.aborted){await emit({type:"agent_end",messages:newMessages});return}explicitContinuation=decision?.action==="continue",pendingMessages=await config.getSteeringMessages?.()||[],(hasMoreToolCalls||pendingMessages.length>0)&&(explicitContinuation=!1)}let followUpMessages=await config.getFollowUpMessages?.()||[];if(followUpMessages.length>0){explicitContinuation=!1,pendingMessages=followUpMessages;continue}if(explicitContinuation){explicitContinuation=!1;continue}break}await emit({type:"agent_end",messages:newMessages})}function declareToolChanges(context,pendingMessages){let systemIndex=-1;for(let i=pendingMessages.length-1;i>=0;i--)if(pendingMessages[i].role==="system"){systemIndex=i;break}let pending=pendingMessages[systemIndex],baseline=pending?pendingMessages.map((message,index4)=>index4===systemIndex?withToolChanges(pending,NO_CHANGES):message):pendingMessages,changes=getToolStateChanges(getCurrentTools([...context.messages,...baseline]),(context.tools??[]).map(toToolDeclaration)),unchanged=changes.toolsAdded.length===0&&changes.toolsRemoved.length===0;if(pending)return unchanged&&!pending.toolsAdded?.length&&!pending.toolsRemoved?.length?pendingMessages:baseline.map((message,index4)=>index4===systemIndex?withToolChanges(pending,changes):message);if(unchanged)return pendingMessages;let update=withToolChanges({role:"system",content:"",timestamp:Date.now()},changes),insertIndex=pendingMessages.findIndex(message=>message.role!=="system"),index3=insertIndex===-1?pendingMessages.length:insertIndex;return[...pendingMessages.slice(0,index3),update,...pendingMessages.slice(index3)]}var NO_CHANGES={toolsAdded:[],toolsRemoved:[]};function withToolChanges(message,{toolsAdded,toolsRemoved}){let{toolsAdded:_added,toolsRemoved:_removed,...rest}=message;return{...rest,...toolsAdded.length>0?{toolsAdded}:{},...toolsRemoved.length>0?{toolsRemoved}:{}}}async function streamAssistantResponse(context,config,signal,emit,streamFunction){let messages=context.messages;config.transformContext&&(messages=await config.transformContext(messages,signal));let llmMessages=await config.convertToLlm(messages),llmContext=normalizeContext({messages:llmMessages}),resolvedApiKey=(config.getApiKey?await config.getApiKey(config.model.provider):void 0)||config.apiKey,response=await streamFunction(config.model,llmContext,{...config,apiKey:resolvedApiKey,signal}),result=async()=>Object.assign(await response.result(),{thinkingLevel:config.reasoning??"off"}),partialMessage=null,addedPartial=!1;for await(let event of response)switch(event.type){case"start":partialMessage=event.partial,context.messages.push(partialMessage),addedPartial=!0,await emit({type:"message_start",message:{...partialMessage}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":partialMessage&&(partialMessage=event.partial,context.messages[context.messages.length-1]=partialMessage,await emit({type:"message_update",assistantMessageEvent:event,message:{...partialMessage}}));break;case"done":case"error":{let finalMessage2=await result();return addedPartial?context.messages[context.messages.length-1]=finalMessage2:context.messages.push(finalMessage2),addedPartial||await emit({type:"message_start",message:{...finalMessage2}}),await emit({type:"message_end",message:finalMessage2}),finalMessage2}}let finalMessage=await result();return addedPartial?context.messages[context.messages.length-1]=finalMessage:(context.messages.push(finalMessage),await emit({type:"message_start",message:{...finalMessage}})),await emit({type:"message_end",message:finalMessage}),finalMessage}async function failToolCallsFromTruncatedMessage(toolCalls,emit){let messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let finalized={toolCall,result:createErrorToolResult(`Tool call "${toolCall.name}" was not executed: the response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`,"truncated_arguments"),isError:!0};await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:!1}}async function executeToolCalls(currentContext,assistantMessage,config,signal,emit){let toolCalls=assistantMessage.content.filter(c=>c.type==="toolCall"),hasSequentialToolCall=toolCalls.some(tc=>currentContext.tools?.find(t=>t.name===tc.name)?.executionMode==="sequential");return config.toolExecution==="sequential"||hasSequentialToolCall?executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit):executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit)}async function executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[],messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal),finalized;if(preparation.kind==="immediate")finalized={toolCall,result:preparation.result,isError:preparation.isError};else{let executed=await executePreparedToolCall(preparation,signal,emitToolExecutionUpdate(toolCall,emit));finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal)}await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);if(await emitToolResultMessage(toolResultMessage,emit),finalizedCalls.push(finalized),messages.push(toolResultMessage),signal?.aborted)break}return{messages,terminate:shouldTerminateToolBatch(finalizedCalls)}}async function executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal);if(preparation.kind==="immediate"){let finalized={toolCall,result:preparation.result,isError:preparation.isError};if(await emitToolExecutionEnd(finalized,emit),finalizedCalls.push(finalized),signal?.aborted)break;continue}if(finalizedCalls.push(async()=>{if(signal?.aborted){let finalized2={toolCall,result:createErrorToolResult("Operation aborted","aborted"),isError:!0};return await emitToolExecutionEnd(finalized2,emit),finalized2}let executed=await executePreparedToolCall(preparation,signal,emitToolExecutionUpdate(toolCall,emit)),finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal);return await emitToolExecutionEnd(finalized,emit),finalized}),signal?.aborted)break}let orderedFinalizedCalls=await Promise.all(finalizedCalls.map(entry=>typeof entry=="function"?entry():Promise.resolve(entry))),messages=[];for(let finalized of orderedFinalizedCalls){let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:shouldTerminateToolBatch(orderedFinalizedCalls)}}function shouldTerminateToolBatch(finalizedCalls){return finalizedCalls.length>0&&finalizedCalls.every(finalized=>finalized.result.terminate===!0)}function prepareToolCallArguments(tool,toolCall){if(!tool.prepareArguments)return toolCall;let preparedArguments=tool.prepareArguments(toolCall.arguments);return preparedArguments===toolCall.arguments?toolCall:{...toolCall,arguments:preparedArguments}}async function prepareToolCall(currentContext,assistantMessage,toolCall,config,signal,tools=currentContext.tools??[]){let tool=tools.find(t=>t.name===toolCall.name);if(!tool)return{kind:"immediate",result:createErrorToolResult(`Tool ${toolCall.name} not found`,"tool_not_found"),isError:!0};let validatedArgs;try{validatedArgs=validateToolArguments(tool,prepareToolCallArguments(tool,toolCall))}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error),"validation_error"),isError:!0}}try{if(config.beforeToolCall){let beforeResult=await config.beforeToolCall({assistantMessage,toolCall,args:validatedArgs,context:currentContext},signal);if(signal?.aborted)return{kind:"immediate",result:createErrorToolResult("Operation aborted","aborted"),isError:!0};if(beforeResult?.block){let result=createErrorToolResult(beforeResult.reason||"Tool execution was blocked","blocked");return beforeResult.terminate===!0&&(result.terminate=!0),{kind:"immediate",result,isError:!0}}}return signal?.aborted?{kind:"immediate",result:createErrorToolResult("Operation aborted","aborted"),isError:!0}:{kind:"prepared",toolCall,tool,args:validatedArgs}}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}}function emitToolExecutionUpdate(toolCall,emit){return partialResult=>emit({type:"tool_execution_update",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments,partialResult})}async function runToolCall(toolCall,options){let{assistantMessage,context,signal}=options,preparation=await prepareToolCall(context,assistantMessage,toolCall,options,signal,options.tools);if(preparation.kind==="immediate")return{toolCall,result:preparation.result,isError:preparation.isError};let executed=await executePreparedToolCall(preparation,signal,options.onUpdate??(()=>{}));return finalizeExecutedToolCall(context,assistantMessage,preparation,executed,options,signal)}async function executePreparedToolCall(prepared,signal,onUpdate){let updateEvents=[],acceptingUpdates=!0,startedAt=performance.now(),elapsed=()=>Math.round(performance.now()-startedAt);try{let result=await prepared.tool.execute(prepared.toolCall.id,prepared.args,signal,partialResult=>{acceptingUpdates&&updateEvents.push(Promise.resolve(onUpdate(partialResult)))}),durationMs=elapsed();return acceptingUpdates=!1,await Promise.all(updateEvents),{result,isError:result.isError===!0,durationMs}}catch(error){let durationMs=elapsed();return acceptingUpdates=!1,await Promise.all(updateEvents),{result:createErrorToolResult(error instanceof Error?error.message:String(error),thrownErrorCode(error)),isError:!0,durationMs}}finally{acceptingUpdates=!1}}async function finalizeExecutedToolCall(currentContext,assistantMessage,prepared,executed,config,signal){let result=executed.result,isError=executed.isError;if(config.afterToolCall)try{let afterResult=await config.afterToolCall({assistantMessage,toolCall:prepared.toolCall,args:prepared.args,result,isError,context:currentContext},signal);if(afterResult){let structuredContent=afterResult.structuredContent??(afterResult.content?void 0:result.structuredContent);result={...result,content:afterResult.content??result.content,details:afterResult.details??result.details,usage:afterResult.usage??result.usage,terminate:afterResult.terminate??result.terminate},structuredContent===void 0?delete result.structuredContent:result.structuredContent=structuredContent,isError=afterResult.isError??isError}}catch(error){result=createErrorToolResult(error instanceof Error?error.message:String(error)),isError=!0}return{toolCall:prepared.toolCall,result,isError,durationMs:executed.durationMs}}function createErrorToolResult(message,code){return{content:[{type:"text",text:message}],details:code?{code}:{}}}function thrownErrorCode(error){let code=error instanceof Error?error.code:void 0;return typeof code=="string"&&/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(code)?code:void 0}async function emitToolExecutionEnd(finalized,emit){await emit({type:"tool_execution_end",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,result:finalized.result,isError:finalized.isError,...finalized.durationMs===void 0?{}:{durationMs:finalized.durationMs}})}function createToolResultMessage(finalized){return{role:"toolResult",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,content:finalized.result.content??[],details:finalized.result.details,usage:finalized.result.usage,isError:finalized.isError,...finalized.durationMs===void 0?{}:{durationMs:finalized.durationMs},timestamp:Date.now()}}async function emitToolResultMessage(toolResultMessage,emit){await emit({type:"message_start",message:toolResultMessage}),await emit({type:"message_end",message:toolResultMessage})}function defaultConvertToLlm(messages){return messages.filter(message=>message.role==="system"||message.role==="user"||message.role==="assistant"||message.role==="toolResult")}var EMPTY_USAGE={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},DEFAULT_MODEL={id:"unknown",name:"unknown",api:"unknown",provider:"unknown",baseUrl:"",reasoning:!1,input:[],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:0,maxTokens:0};function createMutableAgentState(initialState){let tools=initialState?.tools?.slice()??[],messages=initialState?.messages?.slice()??[],initialMessage=createInitialSystemMessage(initialState?.systemPrompt,tools.map(toToolDeclaration));return messages[0]?.role!=="system"&&initialMessage&&messages.unshift(initialMessage),{get systemPrompt(){return getCurrentSystemPrompt(messages)},model:initialState?.model??DEFAULT_MODEL,thinkingLevel:initialState?.thinkingLevel??"off",get tools(){return tools},set tools(nextTools){tools=nextTools.slice()},get messages(){return messages},set messages(nextMessages){messages=nextMessages.slice()},isStreaming:!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:void 0}}var PendingMessageQueue=class{messages=[];mode;constructor(mode){this.mode=mode}enqueue(message){this.messages.push(message)}hasItems(){return this.messages.length>0}peek(){if(this.mode==="all")return this.messages.slice();let first=this.messages[0];return first?[first]:[]}drain(){let drained=this.peek();return this.messages=this.messages.slice(drained.length),drained}clear(){this.messages=[]}},Agent=class{_state;listeners=new Set;steeringQueue;followUpQueue;convertToLlm;transformContext;streamFunction;getApiKey;onPayload;onResponse;onProviderStreamEvent;beforeToolCall;afterToolCall;finishTurn;prepareRequest;prepareNextTurn;prepareNextTurnWithContext;activeRun;sessionId;thinkingBudgets;transport;maxRetryDelayMs;toolExecution;constructor(options){let runtimeOptions=options??{};this._state=createMutableAgentState(runtimeOptions.initialState),this.convertToLlm=runtimeOptions.convertToLlm??defaultConvertToLlm,this.transformContext=runtimeOptions.transformContext,this.streamFunction=runtimeOptions.streamFn??getDefaultStreamFn(),this.getApiKey=runtimeOptions.getApiKey,this.onPayload=runtimeOptions.onPayload,this.onResponse=runtimeOptions.onResponse,this.onProviderStreamEvent=runtimeOptions.onProviderStreamEvent,this.beforeToolCall=runtimeOptions.beforeToolCall,this.afterToolCall=runtimeOptions.afterToolCall,this.finishTurn=runtimeOptions.finishTurn,this.prepareRequest=runtimeOptions.prepareRequest,this.prepareNextTurn=runtimeOptions.prepareNextTurn,this.prepareNextTurnWithContext=runtimeOptions.prepareNextTurnWithContext,this.steeringQueue=new PendingMessageQueue(runtimeOptions.steeringMode??"one-at-a-time"),this.followUpQueue=new PendingMessageQueue(runtimeOptions.followUpMode??"one-at-a-time"),this.sessionId=runtimeOptions.sessionId,this.thinkingBudgets=runtimeOptions.thinkingBudgets,this.transport=runtimeOptions.transport??"auto",this.maxRetryDelayMs=runtimeOptions.maxRetryDelayMs,this.toolExecution=runtimeOptions.toolExecution??"parallel"}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}get state(){return this._state}set steeringMode(mode){this.steeringQueue.mode=mode}get steeringMode(){return this.steeringQueue.mode}set followUpMode(mode){this.followUpQueue.mode=mode}get followUpMode(){return this.followUpQueue.mode}steer(message){this.steeringQueue.enqueue(message)}followUp(message){this.followUpQueue.enqueue(message)}clearSteeringQueue(){this.steeringQueue.clear()}clearFollowUpQueue(){this.followUpQueue.clear()}clearAllQueues(){this.clearSteeringQueue(),this.clearFollowUpQueue()}hasQueuedMessages(){return this.steeringQueue.hasItems()||this.followUpQueue.hasItems()}peekQueuedMessages(){let steering=this.steeringQueue.peek();return steering.length>0?steering:this.followUpQueue.peek()}get signal(){return this.activeRun?.abortController.signal}abort(){this.activeRun?.abortController.abort()}waitForIdle(){return this.activeRun?.promise??Promise.resolve()}reset(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before resetting.");let baseline=getCurrentSystemMessage(this._state.messages);this._state.messages=baseline?[baseline]:[],this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this._state.errorMessage=void 0,this.clearFollowUpQueue(),this.clearSteeringQueue()}async prompt(input2,images){if(this.activeRun)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");let messages=this.normalizePromptInput(input2,images);await this.runPromptMessages(messages)}async continue(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before continuing.");let lastMessage=this._state.messages[this._state.messages.length-1];if(!lastMessage||this._state.messages.every(message=>message.role==="system"))throw new Error("No messages to continue from");if(lastMessage.role==="assistant"){let queuedSteering=this.steeringQueue.drain();if(queuedSteering.length>0){await this.runPromptMessages(queuedSteering,{skipInitialSteeringPoll:!0});return}let queuedFollowUps=this.followUpQueue.drain();if(queuedFollowUps.length>0){await this.runPromptMessages(queuedFollowUps);return}throw new Error("Cannot continue from message role: assistant")}await this.runContinuation()}normalizePromptInput(input2,images){if(Array.isArray(input2))return input2;if(typeof input2!="string")return[input2];let content=[{type:"text",text:input2}];return images&&images.length>0&&content.push(...images),[{role:"user",content,timestamp:Date.now()}]}async runPromptMessages(messages,options={}){await this.runWithLifecycle(async signal=>{await runAgentLoop(messages,this.createContextSnapshot(),this.createLoopConfig(options),event=>this.processEvents(event),signal,this.streamFunction)})}async runContinuation(){await this.runWithLifecycle(async signal=>{await runAgentLoopContinue(this.createContextSnapshot(),this.createLoopConfig(),event=>this.processEvents(event),signal,this.streamFunction)})}createContextSnapshot(){return{messages:this._state.messages.slice(),tools:this._state.tools.slice()}}createLoopConfig(options={}){let skipInitialSteeringPoll=options.skipInitialSteeringPoll===!0;return{model:this._state.model,reasoning:this._state.thinkingLevel==="off"?void 0:this._state.thinkingLevel,sessionId:this.sessionId,onPayload:this.onPayload,onResponse:this.onResponse,onProviderStreamEvent:this.onProviderStreamEvent,transport:this.transport,thinkingBudgets:this.thinkingBudgets,maxRetryDelayMs:this.maxRetryDelayMs,toolExecution:this.toolExecution,beforeToolCall:this.beforeToolCall,afterToolCall:this.afterToolCall,finishTurn:this.finishTurn,prepareRequest:this.prepareRequest,prepareNextTurn:this.prepareNextTurnWithContext||this.prepareNextTurn?async context=>this.prepareNextTurnWithContext?await this.prepareNextTurnWithContext(context,this.signal):await this.prepareNextTurn?.(this.signal):void 0,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>skipInitialSteeringPoll?(skipInitialSteeringPoll=!1,[]):this.steeringQueue.drain(),getFollowUpMessages:async()=>this.followUpQueue.drain()}}async runWithLifecycle(executor){if(this.activeRun)throw new Error("Agent is already processing.");let abortController=new AbortController,resolvePromise=()=>{},promise=new Promise(resolve16=>{resolvePromise=resolve16});this.activeRun={promise,resolve:resolvePromise,abortController},this._state.isStreaming=!0,this._state.streamingMessage=void 0,this._state.errorMessage=void 0;try{await executor(abortController.signal)}catch(error){await this.handleRunFailure(error,abortController.signal.aborted)}finally{this.finishRun()}}async handleRunFailure(error,aborted){let failureMessage={role:"assistant",content:[{type:"text",text:""}],api:this._state.model.api,provider:this._state.model.provider,model:this._state.model.id,usage:EMPTY_USAGE,stopReason:aborted?"aborted":"error",errorMessage:error instanceof Error?error.message:String(error),timestamp:Date.now()};await this.processEvents({type:"message_start",message:failureMessage}),await this.processEvents({type:"message_end",message:failureMessage}),await this.processEvents({type:"turn_end",message:failureMessage,toolResults:[]}),await this.processEvents({type:"agent_end",messages:[failureMessage]})}finishRun(){this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this.activeRun?.resolve(),this.activeRun=void 0}async processEvents(event){switch(event.type){case"message_start":this._state.streamingMessage=event.message;break;case"message_update":this._state.streamingMessage=event.message;break;case"message_end":this._state.streamingMessage=void 0,this._state.messages.push(event.message);break;case"tool_execution_start":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.add(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"tool_execution_end":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.delete(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"turn_end":event.message.role==="assistant"&&event.message.errorMessage&&(this._state.errorMessage=event.message.errorMessage);break;case"agent_end":this._state.streamingMessage=void 0;break}let signal=this.activeRun?.abortController.signal;if(!signal)throw new Error("Agent listener invoked outside active run");for(let listener of this.listeners)await listener(event,signal)}};function buildProxyRequestOptions(options){return{temperature:options.temperature,samplingParams:options.samplingParams,maxTokens:options.maxTokens,reasoning:options.reasoning,cacheRetention:options.cacheRetention,sessionId:options.sessionId,headers:options.headers,metadata:options.metadata,transport:options.transport,thinkingBudgets:options.thinkingBudgets,maxRetryDelayMs:options.maxRetryDelayMs}}function streamProxy(model,context,options){let stream2=createAssistantMessageEventStream();return(async()=>{let partial={role:"assistant",stopReason:"pending",content:[],api:model.api,provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()},reader,abortHandler=()=>{reader&&reader.cancel("Request aborted by user").catch(()=>{})};options.signal&&options.signal.addEventListener("abort",abortHandler);try{let response=await fetch(`${options.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${options.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model,context,options:buildProxyRequestOptions(options)}),signal:options.signal});if(!response.ok){let errorMessage5=`Proxy error: ${response.status} ${response.statusText}`;try{let errorData=await response.json();errorData.error&&(errorMessage5=`Proxy error: ${errorData.error}`)}catch{}throw new Error(errorMessage5)}reader=response.body.getReader();let decoder=new TextDecoder,buffer="",sawTerminalEvent=!1,processLine=line=>{if(!line.startsWith("data: "))return;let data=line.slice(6).trim();if(!data)return;let proxyEvent=JSON.parse(data),event=processProxyEvent(proxyEvent,partial);event&&((event.type==="done"||event.type==="error")&&(sawTerminalEvent=!0),stream2.push(event))};for(;;){let{done,value}=await reader.read();if(done)break;if(options.signal?.aborted)throw new Error("Request aborted by user");buffer+=decoder.decode(value,{stream:!0});let lines=buffer.split(`
|
|
550
|
+
`);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd);try{for(let file of readdirSync3(dir)){if(!file.endsWith(".jsonl"))continue;let path10=join8(dir,file),header=readSessionHeaderForDiscovery(path10);if(header?.id===id&&!(filterCwd&&!sessionCwdMatches(getSessionHeaderCwd(header),resolvedCwd)))return path10}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),resolvedCwd=resolvePath(cwd),includeSession=session=>!filterCwd||sessionCwdMatches(session.cwd,resolvedCwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync6(sessionsDir))return[];let dirs=(await readdir(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join8(sessionsDir,entry.name)),allFiles=(await mapWithConcurrency(dirs,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async dir=>{try{return(await readdir(dir)).filter(file=>file.endsWith(".jsonl")).map(file=>join8(dir,file))}catch{return[]}},abortSignal)).flat(),candidates=await mapWithConcurrency(allFiles,MAX_CONCURRENT_SESSION_DISCOVERY_LOADS,async path10=>{try{return{path:path10,stats:await stat(path10)}}catch{return{path:path10}}},abortSignal);candidates.sort((a,b)=>(b.stats?.mtimeMs??Number.NEGATIVE_INFINITY)-(a.stats?.mtimeMs??Number.NEGATIVE_INFINITY)||basename3(b.path).localeCompare(basename3(a.path)));let totalFiles=candidates.length,loaded=0,firstCandidateLoaded=!1,partialSessions=[],results=await buildSessionInfosWithConcurrency(candidates,(info,index3)=>{loaded++,index3===0&&(firstCandidateLoaded=!0),info&&partialSessions.push(info);let publishPartial=firstCandidateLoaded&&(index3===0||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles);progress?.(loaded,totalFiles,publishPartial?sortSessionInfos([...partialSessions]):void 0)},abortSignal);return sortSessionInfos(results.filter(info=>info!==null))}catch{return abortSignal?.throwIfAborted(),[]}}};import{EventEmitter as EventEmitter2}from"node:events";function createEventBus(){let emitter=new EventEmitter2;return{emit:(channel,data)=>{emitter.emit(channel,data)},on:(channel,handler)=>{let safeHandler=async data=>{try{await handler(data)}catch(err){console.error(`Event handler error (${channel}):`,err)}};return emitter.on(channel,safeHandler),()=>emitter.off(channel,safeHandler)},clear:()=>{emitter.removeAllListeners()}}}var dist_exports={};__export(dist_exports,{Agent:()=>Agent,agentLoop:()=>agentLoop,agentLoopContinue:()=>agentLoopContinue,runAgentLoop:()=>runAgentLoop,runAgentLoopContinue:()=>runAgentLoopContinue,runToolCall:()=>runToolCall,setDefaultStreamFn:()=>setDefaultStreamFn,streamProxy:()=>streamProxy});var defaultStreamFn;function setDefaultStreamFn(streamFn){defaultStreamFn=streamFn}function getDefaultStreamFn(){if(!defaultStreamFn)throw new Error("No default stream function configured. Pass streamFn explicitly or call setDefaultStreamFn().");return defaultStreamFn}function agentLoop(prompts,context,config,signal,streamFn){let stream2=createAgentStream();return runAgentLoop(prompts,context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}function agentLoopContinue(context,config,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let stream2=createAgentStream();return runAgentLoopContinue(context,config,async event=>{stream2.push(event)},signal,streamFn).then(messages=>{stream2.end(messages)}),stream2}async function runAgentLoop(prompts,context,config,emit,signal,streamFn){let initialMessages=declareToolChanges(context,prompts),newMessages=[...initialMessages],currentContext={...context,messages:[...context.messages,...initialMessages]};await emit({type:"agent_start"}),await emit({type:"turn_start"});for(let message of initialMessages)await emit({type:"message_start",message}),await emit({type:"message_end",message});return await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}async function runAgentLoopContinue(context,config,emit,signal,streamFn){if(context.messages.length===0)throw new Error("Cannot continue: no messages in context");if(context.messages[context.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");let newMessages=[],currentContext={...context};return await emit({type:"agent_start"}),await emit({type:"turn_start"}),await runLoop(currentContext,newMessages,config,signal,emit,streamFn??getDefaultStreamFn()),newMessages}function createAgentStream(){return new EventStream(event=>event.type==="agent_end",event=>event.type==="agent_end"?event.messages:[])}async function runLoop(initialContext,newMessages,initialConfig,signal,emit,streamFunction){let currentContext=initialContext,config=initialConfig,lastCompletedTurn,explicitContinuation=!1,pendingMessages=await config.getSteeringMessages?.()||[];for(;;){let hasMoreToolCalls=!0;for(;hasMoreToolCalls||pendingMessages.length>0;){let preparedMessages=[];if(lastCompletedTurn){let nextTurnSnapshot=await config.prepareNextTurn?.(lastCompletedTurn);nextTurnSnapshot&&(currentContext=nextTurnSnapshot.context??currentContext,preparedMessages=nextTurnSnapshot.messages??[],config={...config,model:nextTurnSnapshot.model??config.model,reasoning:nextTurnSnapshot.thinkingLevel===void 0?config.reasoning:nextTurnSnapshot.thinkingLevel==="off"?void 0:nextTurnSnapshot.thinkingLevel}),pendingMessages.length===0&&(pendingMessages=await config.getSteeringMessages?.()||[]),await emit({type:"turn_start"})}for(let message2 of declareToolChanges(currentContext,[...preparedMessages,...pendingMessages]))await emit({type:"message_start",message:message2}),await emit({type:"message_end",message:message2}),currentContext.messages.push(message2),newMessages.push(message2);pendingMessages=[];let requestUpdate=await config.prepareRequest?.({context:currentContext,model:config.model,thinkingLevel:config.reasoning??"off"},signal);requestUpdate&&(currentContext=requestUpdate.context??currentContext,config={...config,model:requestUpdate.model??config.model,reasoning:requestUpdate.thinkingLevel===void 0?config.reasoning:requestUpdate.thinkingLevel==="off"?void 0:requestUpdate.thinkingLevel});let message=await streamAssistantResponse(currentContext,config,signal,emit,streamFunction);if(newMessages.push(message),message.stopReason==="error"||message.stopReason==="aborted"){lastCompletedTurn={message,toolResults:[],context:currentContext,newMessages},await config.finishTurn?.(lastCompletedTurn,signal),await emit({type:"turn_end",message,toolResults:[]}),await emit({type:"agent_end",messages:newMessages});return}let toolCalls=message.content.filter(c=>c.type==="toolCall"),toolResults=[];if(hasMoreToolCalls=!1,toolCalls.length>0){let executedToolBatch=message.stopReason==="length"?await failToolCallsFromTruncatedMessage(toolCalls,emit):await executeToolCalls(currentContext,message,config,signal,emit);toolResults.push(...executedToolBatch.messages),hasMoreToolCalls=!executedToolBatch.terminate;for(let result of toolResults)currentContext.messages.push(result),newMessages.push(result)}lastCompletedTurn={message,toolResults,context:currentContext,newMessages};let decision=await config.finishTurn?.(lastCompletedTurn,signal);if(await emit({type:"turn_end",message,toolResults}),decision?.action==="end"){await emit({type:"agent_end",messages:newMessages});return}explicitContinuation=decision?.action==="continue",pendingMessages=await config.getSteeringMessages?.()||[],(hasMoreToolCalls||pendingMessages.length>0)&&(explicitContinuation=!1)}let followUpMessages=await config.getFollowUpMessages?.()||[];if(followUpMessages.length>0){explicitContinuation=!1,pendingMessages=followUpMessages;continue}if(explicitContinuation){explicitContinuation=!1;continue}break}await emit({type:"agent_end",messages:newMessages})}function declareToolChanges(context,pendingMessages){let systemIndex=-1;for(let i=pendingMessages.length-1;i>=0;i--)if(pendingMessages[i].role==="system"){systemIndex=i;break}let pending=pendingMessages[systemIndex],baseline=pending?pendingMessages.map((message,index4)=>index4===systemIndex?withToolChanges(pending,NO_CHANGES):message):pendingMessages,changes=getToolStateChanges(getCurrentTools([...context.messages,...baseline]),(context.tools??[]).map(toToolDeclaration)),unchanged=changes.toolsAdded.length===0&&changes.toolsRemoved.length===0;if(pending)return unchanged&&!pending.toolsAdded?.length&&!pending.toolsRemoved?.length?pendingMessages:baseline.map((message,index4)=>index4===systemIndex?withToolChanges(pending,changes):message);if(unchanged)return pendingMessages;let update=withToolChanges({role:"system",content:"",timestamp:Date.now()},changes),insertIndex=pendingMessages.findIndex(message=>message.role!=="system"),index3=insertIndex===-1?pendingMessages.length:insertIndex;return[...pendingMessages.slice(0,index3),update,...pendingMessages.slice(index3)]}var NO_CHANGES={toolsAdded:[],toolsRemoved:[]};function withToolChanges(message,{toolsAdded,toolsRemoved}){let{toolsAdded:_added,toolsRemoved:_removed,...rest}=message;return{...rest,...toolsAdded.length>0?{toolsAdded}:{},...toolsRemoved.length>0?{toolsRemoved}:{}}}async function streamAssistantResponse(context,config,signal,emit,streamFunction){if(signal?.aborted){let aborted={role:"assistant",content:[],api:config.model.api,provider:config.model.provider,model:config.model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"aborted",errorMessage:"Request was aborted",timestamp:Date.now(),thinkingLevel:config.reasoning??"off"};return context.messages.push(aborted),await emit({type:"message_start",message:{...aborted}}),await emit({type:"message_end",message:aborted}),aborted}let messages=context.messages;config.transformContext&&(messages=await config.transformContext(messages,signal));let llmMessages=await config.convertToLlm(messages),llmContext=normalizeContext({messages:llmMessages}),resolvedApiKey=(config.getApiKey?await config.getApiKey(config.model.provider):void 0)||config.apiKey,response=await streamFunction(config.model,llmContext,{...config,apiKey:resolvedApiKey,signal}),result=async()=>Object.assign(await response.result(),{thinkingLevel:config.reasoning??"off"}),partialMessage=null,addedPartial=!1;for await(let event of response)switch(event.type){case"start":partialMessage=event.partial,context.messages.push(partialMessage),addedPartial=!0,await emit({type:"message_start",message:{...partialMessage}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":partialMessage&&(partialMessage=event.partial,context.messages[context.messages.length-1]=partialMessage,await emit({type:"message_update",assistantMessageEvent:event,message:{...partialMessage}}));break;case"done":case"error":{let finalMessage2=await result();return addedPartial?context.messages[context.messages.length-1]=finalMessage2:context.messages.push(finalMessage2),addedPartial||await emit({type:"message_start",message:{...finalMessage2}}),await emit({type:"message_end",message:finalMessage2}),finalMessage2}}let finalMessage=await result();return addedPartial?context.messages[context.messages.length-1]=finalMessage:(context.messages.push(finalMessage),await emit({type:"message_start",message:{...finalMessage}})),await emit({type:"message_end",message:finalMessage}),finalMessage}async function failToolCallsFromTruncatedMessage(toolCalls,emit){let messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let finalized={toolCall,result:createErrorToolResult(`Tool call "${toolCall.name}" was not executed: the response hit the output token limit, so its arguments may be truncated. Re-issue the tool call with complete arguments.`,"truncated_arguments"),isError:!0};await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:!1}}async function executeToolCalls(currentContext,assistantMessage,config,signal,emit){let toolCalls=assistantMessage.content.filter(c=>c.type==="toolCall"),hasSequentialToolCall=toolCalls.some(tc=>currentContext.tools?.find(t=>t.name===tc.name)?.executionMode==="sequential");return config.toolExecution==="sequential"||hasSequentialToolCall?executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit):executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit)}async function executeToolCallsSequential(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[],messages=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal),finalized;if(preparation.kind==="immediate")finalized={toolCall,result:preparation.result,isError:preparation.isError};else{let executed=await executePreparedToolCall(preparation,signal,emitToolExecutionUpdate(toolCall,emit));finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal)}await emitToolExecutionEnd(finalized,emit);let toolResultMessage=createToolResultMessage(finalized);if(await emitToolResultMessage(toolResultMessage,emit),finalizedCalls.push(finalized),messages.push(toolResultMessage),signal?.aborted)break}return{messages,terminate:shouldTerminateToolBatch(finalizedCalls)}}async function executeToolCallsParallel(currentContext,assistantMessage,toolCalls,config,signal,emit){let finalizedCalls=[];for(let toolCall of toolCalls){await emit({type:"tool_execution_start",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments});let preparation=await prepareToolCall(currentContext,assistantMessage,toolCall,config,signal);if(preparation.kind==="immediate"){let finalized={toolCall,result:preparation.result,isError:preparation.isError};if(await emitToolExecutionEnd(finalized,emit),finalizedCalls.push(finalized),signal?.aborted)break;continue}if(finalizedCalls.push(async()=>{if(signal?.aborted){let finalized2={toolCall,result:createErrorToolResult("Operation aborted","aborted"),isError:!0};return await emitToolExecutionEnd(finalized2,emit),finalized2}let executed=await executePreparedToolCall(preparation,signal,emitToolExecutionUpdate(toolCall,emit)),finalized=await finalizeExecutedToolCall(currentContext,assistantMessage,preparation,executed,config,signal);return await emitToolExecutionEnd(finalized,emit),finalized}),signal?.aborted)break}let orderedFinalizedCalls=await Promise.all(finalizedCalls.map(entry=>typeof entry=="function"?entry():Promise.resolve(entry))),messages=[];for(let finalized of orderedFinalizedCalls){let toolResultMessage=createToolResultMessage(finalized);await emitToolResultMessage(toolResultMessage,emit),messages.push(toolResultMessage)}return{messages,terminate:shouldTerminateToolBatch(orderedFinalizedCalls)}}function shouldTerminateToolBatch(finalizedCalls){return finalizedCalls.length>0&&finalizedCalls.every(finalized=>finalized.result.terminate===!0)}function prepareToolCallArguments(tool,toolCall){if(!tool.prepareArguments)return toolCall;let preparedArguments=tool.prepareArguments(toolCall.arguments);return preparedArguments===toolCall.arguments?toolCall:{...toolCall,arguments:preparedArguments}}async function prepareToolCall(currentContext,assistantMessage,toolCall,config,signal,tools=currentContext.tools??[]){let tool=tools.find(t=>t.name===toolCall.name);if(!tool)return{kind:"immediate",result:createErrorToolResult(`Tool ${toolCall.name} not found`,"tool_not_found"),isError:!0};let validatedArgs;try{validatedArgs=validateToolArguments(tool,prepareToolCallArguments(tool,toolCall))}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error),"validation_error"),isError:!0}}try{if(config.beforeToolCall){let beforeResult=await config.beforeToolCall({assistantMessage,toolCall,args:validatedArgs,context:currentContext},signal);if(signal?.aborted)return{kind:"immediate",result:createErrorToolResult("Operation aborted","aborted"),isError:!0};if(beforeResult?.block){let result=createErrorToolResult(beforeResult.reason||"Tool execution was blocked","blocked");return beforeResult.terminate===!0&&(result.terminate=!0),{kind:"immediate",result,isError:!0}}}return signal?.aborted?{kind:"immediate",result:createErrorToolResult("Operation aborted","aborted"),isError:!0}:{kind:"prepared",toolCall,tool,args:validatedArgs}}catch(error){return{kind:"immediate",result:createErrorToolResult(error instanceof Error?error.message:String(error)),isError:!0}}}function emitToolExecutionUpdate(toolCall,emit){return partialResult=>emit({type:"tool_execution_update",toolCallId:toolCall.id,toolName:toolCall.name,args:toolCall.arguments,partialResult})}async function runToolCall(toolCall,options){let{assistantMessage,context,signal}=options,preparation=await prepareToolCall(context,assistantMessage,toolCall,options,signal,options.tools);if(preparation.kind==="immediate")return{toolCall,result:preparation.result,isError:preparation.isError};let executed=await executePreparedToolCall(preparation,signal,options.onUpdate??(()=>{}));return finalizeExecutedToolCall(context,assistantMessage,preparation,executed,options,signal)}async function executePreparedToolCall(prepared,signal,onUpdate){let updateEvents=[],acceptingUpdates=!0,startedAt=performance.now(),elapsed=()=>Math.round(performance.now()-startedAt);try{let result=await prepared.tool.execute(prepared.toolCall.id,prepared.args,signal,partialResult=>{acceptingUpdates&&updateEvents.push(Promise.resolve(onUpdate(partialResult)))}),durationMs=elapsed();return acceptingUpdates=!1,await Promise.all(updateEvents),{result,isError:result.isError===!0,durationMs}}catch(error){let durationMs=elapsed();return acceptingUpdates=!1,await Promise.all(updateEvents),{result:createErrorToolResult(error instanceof Error?error.message:String(error),thrownErrorCode(error)),isError:!0,durationMs}}finally{acceptingUpdates=!1}}async function finalizeExecutedToolCall(currentContext,assistantMessage,prepared,executed,config,signal){let result=executed.result,isError=executed.isError;if(config.afterToolCall)try{let afterResult=await config.afterToolCall({assistantMessage,toolCall:prepared.toolCall,args:prepared.args,result,isError,context:currentContext},signal);if(afterResult){let structuredContent=afterResult.structuredContent??(afterResult.content?void 0:result.structuredContent);result={...result,content:afterResult.content??result.content,details:afterResult.details??result.details,usage:afterResult.usage??result.usage,terminate:afterResult.terminate??result.terminate},structuredContent===void 0?delete result.structuredContent:result.structuredContent=structuredContent,isError=afterResult.isError??isError}}catch(error){result=createErrorToolResult(error instanceof Error?error.message:String(error)),isError=!0}return{toolCall:prepared.toolCall,result,isError,durationMs:executed.durationMs}}function createErrorToolResult(message,code){return{content:[{type:"text",text:message}],details:code?{code}:{}}}function thrownErrorCode(error){let code=error instanceof Error?error.code:void 0;return typeof code=="string"&&/^[A-Za-z][A-Za-z0-9_]{0,63}$/.test(code)?code:void 0}async function emitToolExecutionEnd(finalized,emit){await emit({type:"tool_execution_end",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,result:finalized.result,isError:finalized.isError,...finalized.durationMs===void 0?{}:{durationMs:finalized.durationMs}})}function createToolResultMessage(finalized){return{role:"toolResult",toolCallId:finalized.toolCall.id,toolName:finalized.toolCall.name,content:finalized.result.content??[],details:finalized.result.details,usage:finalized.result.usage,isError:finalized.isError,...finalized.durationMs===void 0?{}:{durationMs:finalized.durationMs},timestamp:Date.now()}}async function emitToolResultMessage(toolResultMessage,emit){await emit({type:"message_start",message:toolResultMessage}),await emit({type:"message_end",message:toolResultMessage})}function defaultConvertToLlm(messages){return messages.filter(message=>message.role==="system"||message.role==="user"||message.role==="assistant"||message.role==="toolResult")}var EMPTY_USAGE={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},DEFAULT_MODEL={id:"unknown",name:"unknown",api:"unknown",provider:"unknown",baseUrl:"",reasoning:!1,input:[],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:0,maxTokens:0};function createMutableAgentState(initialState){let tools=initialState?.tools?.slice()??[],messages=initialState?.messages?.slice()??[],initialMessage=createInitialSystemMessage(initialState?.systemPrompt,tools.map(toToolDeclaration));return messages[0]?.role!=="system"&&initialMessage&&messages.unshift(initialMessage),{get systemPrompt(){return getCurrentSystemPrompt(messages)},model:initialState?.model??DEFAULT_MODEL,thinkingLevel:initialState?.thinkingLevel??"off",get tools(){return tools},set tools(nextTools){tools=nextTools.slice()},get messages(){return messages},set messages(nextMessages){messages=nextMessages.slice()},isStreaming:!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:void 0}}var PendingMessageQueue=class{messages=[];mode;constructor(mode){this.mode=mode}enqueue(message){this.messages.push(message)}hasItems(){return this.messages.length>0}peek(){if(this.mode==="all")return this.messages.slice();let first=this.messages[0];return first?[first]:[]}drain(){let drained=this.peek();return this.messages=this.messages.slice(drained.length),drained}clear(){this.messages=[]}},Agent=class{_state;listeners=new Set;steeringQueue;followUpQueue;convertToLlm;transformContext;streamFunction;getApiKey;onPayload;onResponse;onProviderStreamEvent;beforeToolCall;afterToolCall;finishTurn;prepareRequest;prepareNextTurn;prepareNextTurnWithContext;activeRun;sessionId;thinkingBudgets;transport;maxRetryDelayMs;toolExecution;constructor(options){let runtimeOptions=options??{};this._state=createMutableAgentState(runtimeOptions.initialState),this.convertToLlm=runtimeOptions.convertToLlm??defaultConvertToLlm,this.transformContext=runtimeOptions.transformContext,this.streamFunction=runtimeOptions.streamFn??getDefaultStreamFn(),this.getApiKey=runtimeOptions.getApiKey,this.onPayload=runtimeOptions.onPayload,this.onResponse=runtimeOptions.onResponse,this.onProviderStreamEvent=runtimeOptions.onProviderStreamEvent,this.beforeToolCall=runtimeOptions.beforeToolCall,this.afterToolCall=runtimeOptions.afterToolCall,this.finishTurn=runtimeOptions.finishTurn,this.prepareRequest=runtimeOptions.prepareRequest,this.prepareNextTurn=runtimeOptions.prepareNextTurn,this.prepareNextTurnWithContext=runtimeOptions.prepareNextTurnWithContext,this.steeringQueue=new PendingMessageQueue(runtimeOptions.steeringMode??"one-at-a-time"),this.followUpQueue=new PendingMessageQueue(runtimeOptions.followUpMode??"one-at-a-time"),this.sessionId=runtimeOptions.sessionId,this.thinkingBudgets=runtimeOptions.thinkingBudgets,this.transport=runtimeOptions.transport??"auto",this.maxRetryDelayMs=runtimeOptions.maxRetryDelayMs,this.toolExecution=runtimeOptions.toolExecution??"parallel"}subscribe(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}get state(){return this._state}set steeringMode(mode){this.steeringQueue.mode=mode}get steeringMode(){return this.steeringQueue.mode}set followUpMode(mode){this.followUpQueue.mode=mode}get followUpMode(){return this.followUpQueue.mode}steer(message){this.steeringQueue.enqueue(message)}followUp(message){this.followUpQueue.enqueue(message)}clearSteeringQueue(){this.steeringQueue.clear()}clearFollowUpQueue(){this.followUpQueue.clear()}clearAllQueues(){this.clearSteeringQueue(),this.clearFollowUpQueue()}hasQueuedMessages(){return this.steeringQueue.hasItems()||this.followUpQueue.hasItems()}peekQueuedMessages(){let steering=this.steeringQueue.peek();return steering.length>0?steering:this.followUpQueue.peek()}get signal(){return this.activeRun?.abortController.signal}abort(){this.activeRun?.abortController.abort()}waitForIdle(){return this.activeRun?.promise??Promise.resolve()}reset(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before resetting.");let baseline=getCurrentSystemMessage(this._state.messages);this._state.messages=baseline?[baseline]:[],this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this._state.errorMessage=void 0,this.clearFollowUpQueue(),this.clearSteeringQueue()}async prompt(input2,images){if(this.activeRun)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");let messages=this.normalizePromptInput(input2,images);await this.runPromptMessages(messages)}async continue(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before continuing.");let lastMessage=this._state.messages[this._state.messages.length-1];if(!lastMessage||this._state.messages.every(message=>message.role==="system"))throw new Error("No messages to continue from");if(lastMessage.role==="assistant"){let queuedSteering=this.steeringQueue.drain();if(queuedSteering.length>0){await this.runPromptMessages(queuedSteering,{skipInitialSteeringPoll:!0});return}let queuedFollowUps=this.followUpQueue.drain();if(queuedFollowUps.length>0){await this.runPromptMessages(queuedFollowUps);return}throw new Error("Cannot continue from message role: assistant")}await this.runContinuation()}normalizePromptInput(input2,images){if(Array.isArray(input2))return input2;if(typeof input2!="string")return[input2];let content=[{type:"text",text:input2}];return images&&images.length>0&&content.push(...images),[{role:"user",content,timestamp:Date.now()}]}async runPromptMessages(messages,options={}){await this.runWithLifecycle(async signal=>{await runAgentLoop(messages,this.createContextSnapshot(),this.createLoopConfig(options),event=>this.processEvents(event),signal,this.streamFunction)})}async runContinuation(){await this.runWithLifecycle(async signal=>{await runAgentLoopContinue(this.createContextSnapshot(),this.createLoopConfig(),event=>this.processEvents(event),signal,this.streamFunction)})}createContextSnapshot(){return{messages:this._state.messages.slice(),tools:this._state.tools.slice()}}createLoopConfig(options={}){let skipInitialSteeringPoll=options.skipInitialSteeringPoll===!0;return{model:this._state.model,reasoning:this._state.thinkingLevel==="off"?void 0:this._state.thinkingLevel,sessionId:this.sessionId,onPayload:this.onPayload,onResponse:this.onResponse,onProviderStreamEvent:this.onProviderStreamEvent,transport:this.transport,thinkingBudgets:this.thinkingBudgets,maxRetryDelayMs:this.maxRetryDelayMs,toolExecution:this.toolExecution,beforeToolCall:this.beforeToolCall,afterToolCall:this.afterToolCall,finishTurn:this.finishTurn,prepareRequest:this.prepareRequest,prepareNextTurn:this.prepareNextTurnWithContext||this.prepareNextTurn?async context=>this.prepareNextTurnWithContext?await this.prepareNextTurnWithContext(context,this.signal):await this.prepareNextTurn?.(this.signal):void 0,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>skipInitialSteeringPoll?(skipInitialSteeringPoll=!1,[]):this.steeringQueue.drain(),getFollowUpMessages:async()=>this.followUpQueue.drain()}}async runWithLifecycle(executor){if(this.activeRun)throw new Error("Agent is already processing.");let abortController=new AbortController,resolvePromise=()=>{},promise=new Promise(resolve16=>{resolvePromise=resolve16});this.activeRun={promise,resolve:resolvePromise,abortController},this._state.isStreaming=!0,this._state.streamingMessage=void 0,this._state.errorMessage=void 0;try{await executor(abortController.signal)}catch(error){await this.handleRunFailure(error,abortController.signal.aborted)}finally{this.finishRun()}}async handleRunFailure(error,aborted){let failureMessage={role:"assistant",content:[{type:"text",text:""}],api:this._state.model.api,provider:this._state.model.provider,model:this._state.model.id,usage:EMPTY_USAGE,stopReason:aborted?"aborted":"error",errorMessage:error instanceof Error?error.message:String(error),timestamp:Date.now()};await this.processEvents({type:"message_start",message:failureMessage}),await this.processEvents({type:"message_end",message:failureMessage}),await this.processEvents({type:"turn_end",message:failureMessage,toolResults:[]}),await this.processEvents({type:"agent_end",messages:[failureMessage]})}finishRun(){this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this.activeRun?.resolve(),this.activeRun=void 0}async processEvents(event){switch(event.type){case"message_start":this._state.streamingMessage=event.message;break;case"message_update":this._state.streamingMessage=event.message;break;case"message_end":this._state.streamingMessage=void 0,this._state.messages.push(event.message);break;case"tool_execution_start":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.add(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"tool_execution_end":{let pendingToolCalls=new Set(this._state.pendingToolCalls);pendingToolCalls.delete(event.toolCallId),this._state.pendingToolCalls=pendingToolCalls;break}case"turn_end":event.message.role==="assistant"&&event.message.errorMessage&&(this._state.errorMessage=event.message.errorMessage);break;case"agent_end":this._state.streamingMessage=void 0;break}let signal=this.activeRun?.abortController.signal;if(!signal)throw new Error("Agent listener invoked outside active run");for(let listener of this.listeners)await listener(event,signal)}};function buildProxyRequestOptions(options){return{temperature:options.temperature,samplingParams:options.samplingParams,maxTokens:options.maxTokens,reasoning:options.reasoning,cacheRetention:options.cacheRetention,sessionId:options.sessionId,headers:options.headers,metadata:options.metadata,transport:options.transport,thinkingBudgets:options.thinkingBudgets,maxRetryDelayMs:options.maxRetryDelayMs}}function streamProxy(model,context,options){let stream2=createAssistantMessageEventStream();return(async()=>{let partial={role:"assistant",stopReason:"pending",content:[],api:model.api,provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()},reader,abortHandler=()=>{reader&&reader.cancel("Request aborted by user").catch(()=>{})};options.signal&&options.signal.addEventListener("abort",abortHandler);try{let response=await fetch(`${options.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${options.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model,context,options:buildProxyRequestOptions(options)}),signal:options.signal});if(!response.ok){let errorMessage5=`Proxy error: ${response.status} ${response.statusText}`;try{let errorData=await response.json();errorData.error&&(errorMessage5=`Proxy error: ${errorData.error}`)}catch{}throw new Error(errorMessage5)}reader=response.body.getReader();let decoder=new TextDecoder,buffer="",sawTerminalEvent=!1,processLine=line=>{if(!line.startsWith("data: "))return;let data=line.slice(6).trim();if(!data)return;let proxyEvent=JSON.parse(data),event=processProxyEvent(proxyEvent,partial);event&&((event.type==="done"||event.type==="error")&&(sawTerminalEvent=!0),stream2.push(event))};for(;;){let{done,value}=await reader.read();if(done)break;if(options.signal?.aborted)throw new Error("Request aborted by user");buffer+=decoder.decode(value,{stream:!0});let lines=buffer.split(`
|
|
551
551
|
`);buffer=lines.pop()||"";for(let line of lines)processLine(line)}if(options.signal?.aborted)throw new Error("Request aborted by user");buffer+=decoder.decode(),buffer&&processLine(buffer),sawTerminalEvent||(partial.stopReason="error",partial.errorMessage="Connection closed by proxy server before the response completed",stream2.push({type:"error",reason:"error",error:partial})),stream2.end()}catch(error){let errorMessage5=error instanceof Error?error.message:String(error),reason=options.signal?.aborted?"aborted":"error";partial.stopReason=reason,partial.errorMessage=errorMessage5,stream2.push({type:"error",reason,error:partial}),stream2.end()}finally{options.signal&&options.signal.removeEventListener("abort",abortHandler)}})(),stream2}function processProxyEvent(proxyEvent,partial){switch(proxyEvent.type){case"start":return{type:"start",partial};case"text_start":return partial.content[proxyEvent.contentIndex]={type:"text",text:""},{type:"text_start",contentIndex:proxyEvent.contentIndex,partial};case"text_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="text")return content.text+=proxyEvent.delta,{type:"text_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received text_delta for non-text content")}case"text_end":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="text")return content.textSignature=proxyEvent.contentSignature,{type:"text_end",contentIndex:proxyEvent.contentIndex,content:content.text,partial};throw new Error("Received text_end for non-text content")}case"thinking_start":return partial.content[proxyEvent.contentIndex]={type:"thinking",thinking:""},{type:"thinking_start",contentIndex:proxyEvent.contentIndex,partial};case"thinking_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="thinking")return content.thinking+=proxyEvent.delta,{type:"thinking_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received thinking_delta for non-thinking content")}case"thinking_end":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="thinking")return content.thinkingSignature=proxyEvent.contentSignature,{type:"thinking_end",contentIndex:proxyEvent.contentIndex,content:content.thinking,partial};throw new Error("Received thinking_end for non-thinking content")}case"toolcall_start":return partial.content[proxyEvent.contentIndex]={type:"toolCall",id:proxyEvent.id,name:proxyEvent.toolName,arguments:{},partialJson:""},{type:"toolcall_start",contentIndex:proxyEvent.contentIndex,partial};case"toolcall_delta":{let content=partial.content[proxyEvent.contentIndex];if(content?.type==="toolCall")return content.partialJson+=proxyEvent.delta,content.arguments=parseStreamingJson(content.partialJson)||{},partial.content[proxyEvent.contentIndex]={...content},{type:"toolcall_delta",contentIndex:proxyEvent.contentIndex,delta:proxyEvent.delta,partial};throw new Error("Received toolcall_delta for non-toolCall content")}case"toolcall_end":{let content=partial.content[proxyEvent.contentIndex];return content?.type==="toolCall"?(Object.assign(content,proxyEvent.toolCall),delete content.partialJson,{type:"toolcall_end",contentIndex:proxyEvent.contentIndex,toolCall:content,partial}):void 0}case"done":return partial.stopReason=proxyEvent.reason,partial.usage=proxyEvent.usage,proxyEvent.providerThinkingLevel!==void 0&&(partial.providerThinkingLevel=proxyEvent.providerThinkingLevel),{type:"done",reason:proxyEvent.reason,message:partial};case"error":return partial.stopReason=proxyEvent.reason,partial.errorMessage=proxyEvent.errorMessage,partial.usage=proxyEvent.usage,proxyEvent.providerThinkingLevel!==void 0&&(partial.providerThinkingLevel=proxyEvent.providerThinkingLevel),{type:"error",reason:proxyEvent.reason,error:partial};default:{let _exhaustiveCheck=proxyEvent;console.warn(`Unhandled proxy event type: ${proxyEvent.type}`);return}}}function createFileOps(){return{read:new Set,written:new Set,edited:new Set}}function extractFileOpsFromMessage(message,fileOps){if(message.role==="toolResult"){for(let call of message.nestedCalls?.calls??[])addFileOp(call.name,call.arguments,fileOps);return}if(message.role==="assistant"&&!(!("content"in message)||!Array.isArray(message.content)))for(let block of message.content)typeof block!="object"||block===null||!("type"in block)||block.type!=="toolCall"||!("arguments"in block)||!("name"in block)||addFileOp(block.name,block.arguments,fileOps)}function addFileOp(toolName,args,fileOps){let path10=typeof args?.path=="string"?args.path:void 0;if(path10)switch(toolName){case"read":fileOps.read.add(path10);break;case"write":fileOps.written.add(path10);break;case"edit":fileOps.edited.add(path10);break}}function computeFileLists(fileOps){let modified=new Set([...fileOps.edited,...fileOps.written]),readOnly=[...fileOps.read].filter(f=>!modified.has(f)).sort(),modifiedFiles=[...modified].sort();return{readFiles:readOnly,modifiedFiles}}function formatFileOperations(readFiles,modifiedFiles){let sections=[];return readFiles.length>0&§ions.push(`<read-files>
|
|
552
552
|
${readFiles.join(`
|
|
553
553
|
`)}
|
|
@@ -706,7 +706,7 @@ ${conversationText}
|
|
|
706
706
|
|
|
707
707
|
${instructions}`}],timestamp:Date.now()}],maxTokens=Math.min(4096,model.maxTokens>0?model.maxTokens:Number.POSITIVE_INFINITY),context=normalizeContext({systemPrompt:SUMMARIZATION_SYSTEM_PROMPT,messages:summarizationMessages}),response=await completeSummarization(model,context,{apiKey,headers,env,signal,maxTokens},streamFn,retry,callbacks);if(response.stopReason==="aborted")return{aborted:!0};let failure=getSummarizationFailure(response,"Branch summarization");if(failure)return{error:failure};if(response.content.some(block=>block.type==="toolCall"))return{error:"Branch summarization attempted to call a tool"};let summary=contentText(response.content);summary=BRANCH_SUMMARY_PREAMBLE+summary;let{readFiles,modifiedFiles}=computeFileLists(fileOps);return summary+=formatFileOperations(readFiles,modifiedFiles),{summary:summary||"No summary generated",usage:response.usage,readFiles,modifiedFiles}}function defineTool(tool){return tool}function isBashToolResult(e){return e.toolName==="bash"}function isPowerShellToolResult(e){return e.toolName==="powershell"}function isReadToolResult(e){return e.toolName==="read"}function isEditToolResult(e){return e.toolName==="edit"}function isWriteToolResult(e){return e.toolName==="write"}function isGrepToolResult(e){return e.toolName==="grep"}function isFindToolResult(e){return e.toolName==="find"}function isLsToolResult(e){return e.toolName==="ls"}function isToolCallEventType(toolName,event){return event.toolName===toolName}function 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 fs2 from"node:fs";import{createRequire as createRequire2}from"node:module";import*as path3 from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";import{spawn}from"node:child_process";async function execCommand(command,args,cwd,options){return new Promise(resolve16=>{let proc=spawn(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),resolve16({stdout,stderr,code:code??0,killed})}).catch(_err=>{timeoutId&&clearTimeout(timeoutId),options?.signal&&options.signal.removeEventListener("abort",killProcess),resolve16({stdout,stderr,code:1,killed})})})}var ENABLED=process.env.PI_TIMING==="1",timingNamespaces=new Map;function resetTimings(namespace="main"){ENABLED&&timingNamespaces.set(namespace,{timings:[],lastTime:Date.now()})}function time(label,namespace="main"){if(!ENABLED)return;let now=Date.now();timingNamespaces.has(namespace)||resetTimings(namespace);let timingNamespace=timingNamespaces.get(namespace);timingNamespace.timings.push({label,ms:now-timingNamespace.lastTime}),timingNamespace.lastTime=now}function printTimingGroup(title,timings){let printableTimings=timings.filter(timing=>timing.ms>=0);if(printableTimings.length!==0){console.error(`
|
|
708
708
|
--- ${title} ---`);for(let t of printableTimings)console.error(` ${t.label}: ${t.ms}ms`);console.error(` TOTAL: ${printableTimings.reduce((a,b)=>a+b.ms,0)}ms`),console.error(`${"-".repeat(title.length+8)}
|
|
709
|
-
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire2(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path3.extname(fileURLToPath2(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-E6ANQD5T.js"):import("./jiti-loader-C3NU2SDH.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-C5BH2VI2.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname=path3.dirname(fileURLToPath2(import.meta.url)),packageIndex=path3.resolve(__dirname,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),packagesRoot=path3.resolve(__dirname,"../../../../"),resolveWorkspaceOrImport=(workspaceRelativePath,specifier)=>{let workspacePath=path3.join(packagesRoot,workspaceRelativePath);return fs2.existsSync(workspacePath)?workspacePath:fileURLToPath2(import.meta.resolve(specifier))},piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveWorkspaceOrImport("agent/dist/index.js","@earendil-works/pi-agent-core"),piTuiEntry=resolveWorkspaceOrImport("tui/dist/index.js","@earendil-works/pi-tui"),piAiCompatEntry=resolveWorkspaceOrImport("ai/dist/compat.js","@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveWorkspaceOrImport("ai/dist/oauth.js","@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveWorkspaceOrImport("ai/dist/providers/all.js","@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,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),list=extension.handlers.get(event)??[];return list.push(registeredHandler),extension.handlers.set(event,list),()=>{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:path3.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=path3.join(dir,"package.json");if(fs2.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path3.resolve(dir,extPath);fs2.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path3.join(dir,"index.ts"),indexJs=path3.join(dir,"index.js");return fs2.existsSync(indexTs)?[indexTs]:fs2.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs2.existsSync(dir))return[];let discovered=[];try{let entries=fs2.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path3.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=path3.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path3.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path3.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs2.existsSync(resolved)&&fs2.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{runtime;constructor(runtime){this.runtime=runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(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()}};import{constants}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn2}from"child_process";import{open as open2}from"node:fs/promises";function byteLength(text){return Buffer.byteLength(text,"utf-8")}var OutputAccumulator=class{maxLines;maxBytes;maxRollingBytes;tempFilePrefix;decoder=new TextDecoder;rawChunks=[];tailText="";tailBytes=0;tailStartsAtLineBoundary=!0;totalRawBytes=0;totalDecodedBytes=0;completedLines=0;totalLines=0;currentLineBytes=0;hasOpenLine=!1;finished=!1;tempFilePath;tempFileStream;constructor(options={}){this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"pi-output"}append(data){if(this.finished)throw new Error("Cannot append to a finished output accumulator");this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),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 tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes:this.maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>this.maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>this.maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes:this.maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}async closeTempFile(){if(!this.tempFileStream)return;let stream2=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve16,reject)=>{let onError=error=>{stream2.off("finish",onFinish),reject(error)},onFinish=()=>{stream2.off("error",onError),resolve16()};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 open2(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),tail=Buffer.alloc(tailBytes);await file.read(head,0,headBytes,0),await file.read(tail,0,tailBytes,size-tailBytes);let headText=new TextDecoder().decode(head,{stream:!0}),tailStart=0;for(;tailStart<tail.length&&(tail[tailStart]&192)===128;)tailStart++;let tailText=new TextDecoder().decode(tail.subarray(tailStart)),omitted=size-headBytes-tailBytes;return{content:`${headText}
|
|
709
|
+
`)}}function printTimings(){if(ENABLED)for(let[namespace,timingNamespace]of timingNamespaces)printTimingGroup(`Startup Timings: ${namespace}`,timingNamespace.timings)}var require3=createRequire2(import.meta.url),isNodeSeaBinary="sea"in process.features&&process.features.sea===!0||process.getBuiltinModule("node:sea")?.isSea()===!0,isTypeScriptSourceRuntime=!isBunBinary&&path3.extname(fileURLToPath2(import.meta.url))===".ts",usesEmbeddedModules=isBunBinary||isNodeSeaBinary||isBundledNode,createJitiPromise;function getCreateJiti(){return createJitiPromise??=(usesEmbeddedModules?import("./jiti-static-loader-E6ANQD5T.js"):import("./jiti-loader-C3NU2SDH.js")).then(module=>module.createJiti),createJitiPromise}var virtualModulesPromise;function getVirtualModules(){return virtualModulesPromise??=import("./virtual-modules-INPREDLP.js").then(module=>module.VIRTUAL_MODULES),virtualModulesPromise}var _aliases=null;function getAliases(){if(_aliases)return _aliases;let __dirname=path3.dirname(fileURLToPath2(import.meta.url)),packageIndex=path3.resolve(__dirname,"../..","index.js"),typeboxEntry=require3.resolve("typebox"),typeboxCompileEntry=require3.resolve("typebox/compile"),typeboxValueEntry=require3.resolve("typebox/value"),packagesRoot=path3.resolve(__dirname,"../../../../"),resolveWorkspaceOrImport=(workspaceRelativePath,specifier)=>{let workspacePath=path3.join(packagesRoot,workspaceRelativePath);return fs2.existsSync(workspacePath)?workspacePath:fileURLToPath2(import.meta.resolve(specifier))},piCodingAgentEntry=packageIndex,piAgentCoreEntry=resolveWorkspaceOrImport("agent/dist/index.js","@earendil-works/pi-agent-core"),piTuiEntry=resolveWorkspaceOrImport("tui/dist/index.js","@earendil-works/pi-tui"),piAiCompatEntry=resolveWorkspaceOrImport("ai/dist/compat.js","@earendil-works/pi-ai/compat"),piAiOauthEntry=resolveWorkspaceOrImport("ai/dist/oauth.js","@earendil-works/pi-ai/oauth"),piAiProvidersEntry=resolveWorkspaceOrImport("ai/dist/providers/all.js","@earendil-works/pi-ai/providers/all");return _aliases={"@earendil-works/pi-coding-agent":piCodingAgentEntry,"@earendil-works/pi-agent-core":piAgentCoreEntry,"@earendil-works/pi-tui":piTuiEntry,"@earendil-works/pi-ai/providers/all":piAiProvidersEntry,"@earendil-works/pi-ai/compat":piAiCompatEntry,"@earendil-works/pi-ai/oauth":piAiOauthEntry,"@earendil-works/pi-ai":piAiCompatEntry,"@mariozechner/pi-coding-agent":piCodingAgentEntry,"@mariozechner/pi-agent-core":piAgentCoreEntry,"@mariozechner/pi-tui":piTuiEntry,"@mariozechner/pi-ai/providers/all":piAiProvidersEntry,"@mariozechner/pi-ai/compat":piAiCompatEntry,"@mariozechner/pi-ai/oauth":piAiOauthEntry,"@mariozechner/pi-ai":piAiCompatEntry,typebox:typeboxEntry,"typebox/compile":typeboxCompileEntry,"typebox/value":typeboxValueEntry,"@sinclair/typebox":typeboxEntry,"@sinclair/typebox/compile":typeboxCompileEntry,"@sinclair/typebox/value":typeboxValueEntry},_aliases}var extensionCacheCwd,extensionCacheGeneration=0,extensionCache=new Map;function clearExtensionCache(){extensionCache.clear(),extensionCacheCwd=void 0,extensionCacheGeneration++}function useExtensionCacheCwd(cwd){let resolvedCwd=resolvePath(cwd);return extensionCacheCwd!==void 0&&extensionCacheCwd!==resolvedCwd&&clearExtensionCache(),extensionCacheCwd=resolvedCwd,{cwd:resolvedCwd,generation:extensionCacheGeneration}}function createExtensionRuntime(){let notInitialized=()=>{throw new Error("Extension runtime not initialized. Action methods cannot be called during extension loading.")},state2={},eventBusUnsubscribers=new Set,assertActive=()=>{if(state2.staleMessage)throw new Error(state2.staleMessage)},runtime={sendMessage:notInitialized,sendUserMessage:notInitialized,appendEntry:notInitialized,appendUsage: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),list=extension.handlers.get(event)??[];return list.push(registeredHandler),extension.handlers.set(event,list),()=>{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)},appendUsage(kind,provider,model,usage,note){assertActive(),runtime.appendUsage(kind,provider,model,usage,note)},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:path3.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=path3.join(dir,"package.json");if(fs2.existsSync(packageJsonPath)){let manifest=readPiManifest(packageJsonPath);if(manifest?.extensions?.length){let entries=[];for(let extPath of manifest.extensions){let resolvedExtPath=path3.resolve(dir,extPath);fs2.existsSync(resolvedExtPath)&&entries.push(resolvedExtPath)}if(entries.length>0)return entries}}let indexTs=path3.join(dir,"index.ts"),indexJs=path3.join(dir,"index.js");return fs2.existsSync(indexTs)?[indexTs]:fs2.existsSync(indexJs)?[indexJs]:null}function discoverExtensionsInDir(dir){if(!fs2.existsSync(dir))return[];let discovered=[];try{let entries=fs2.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let entryPath=path3.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=path3.resolve(p);seen.has(resolved)||(seen.add(resolved),allPaths.push(p))}},localExtDir=path3.join(resolvedCwd,CONFIG_DIR_NAME,"extensions");addPaths(discoverExtensionsInDir(localExtDir));let globalExtDir=path3.join(resolvedAgentDir,"extensions");addPaths(discoverExtensionsInDir(globalExtDir));for(let p of configuredPaths){let resolved=resolvePath(p,resolvedCwd,{normalizeUnicodeSpaces:!0});if(fs2.existsSync(resolved)&&fs2.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{runtime;constructor(runtime){this.runtime=runtime}refresh(options){return this.runtime.refresh(options)}getError(){return this.runtime.getError()}getAll(){return[...this.runtime.getModels()]}getAvailable(){return[...this.runtime.getAvailableSnapshot()]}find(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()}};import{constants}from"node:fs";import{access as fsAccess}from"node:fs/promises";import{constants as osConstants}from"node:os";import{spawn as spawn2}from"child_process";import{open as open2}from"node:fs/promises";function byteLength(text){return Buffer.byteLength(text,"utf-8")}var OutputAccumulator=class{maxLines;maxBytes;maxRollingBytes;tempFilePrefix;decoder=new TextDecoder;rawChunks=[];tailText="";tailBytes=0;tailStartsAtLineBoundary=!0;totalRawBytes=0;totalDecodedBytes=0;completedLines=0;totalLines=0;currentLineBytes=0;hasOpenLine=!1;finished=!1;tempFilePath;tempFileStream;constructor(options={}){this.maxLines=options.maxLines??2e3,this.maxBytes=options.maxBytes??51200,this.maxRollingBytes=Math.max(this.maxBytes*2,1),this.tempFilePrefix=options.tempFilePrefix??"pi-output"}append(data){if(this.finished)throw new Error("Cannot append to a finished output accumulator");this.totalRawBytes+=data.length,this.appendDecodedText(this.decoder.decode(data,{stream:!0})),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 tailTruncation=truncateTail(this.getSnapshotText(),{maxLines:this.maxLines,maxBytes:this.maxBytes}),truncated=this.totalLines>this.maxLines||this.totalDecodedBytes>this.maxBytes,truncatedBy=truncated?tailTruncation.truncatedBy??(this.totalDecodedBytes>this.maxBytes?"bytes":"lines"):null,truncation={...tailTruncation,truncated,truncatedBy,totalLines:this.totalLines,totalBytes:this.totalDecodedBytes,maxLines:this.maxLines,maxBytes:this.maxBytes};return options.persistIfTruncated&&truncation.truncated&&this.ensureTempFile(),{content:truncation.content,truncation,fullOutputPath:this.tempFilePath}}async closeTempFile(){if(!this.tempFileStream)return;let stream2=this.tempFileStream;this.tempFileStream=void 0,await new Promise((resolve16,reject)=>{let onError=error=>{stream2.off("finish",onFinish),reject(error)},onFinish=()=>{stream2.off("error",onError),resolve16()};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 open2(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),tail=Buffer.alloc(tailBytes);await file.read(head,0,headBytes,0),await file.read(tail,0,tailBytes,size-tailBytes);let headText=new TextDecoder().decode(head,{stream:!0}),tailStart=0;for(;tailStart<tail.length&&(tail[tailStart]&192)===128;)tailStart++;let tailText=new TextDecoder().decode(tail.subarray(tailStart)),omitted=size-headBytes-tailBytes;return{content:`${headText}
|
|
710
710
|
|
|
711
711
|
[... ${omitted} bytes omitted ...]
|
|
712
712
|
|
|
@@ -878,7 +878,7 @@ ${body}
|
|
|
878
878
|
</skill>`;return args?`${skillBlock}
|
|
879
879
|
|
|
880
880
|
${args}`:skillBlock}catch(err){return this._extensionRunner.emitError({extensionPath:skill.filePath,event:"skill_expansion",error:err instanceof Error?err.message:String(err)}),text}}async _queueUserInput(text,images,behavior,source){text.startsWith("/")&&this._throwIfExtensionCommand(text);let processedInput=await this._runInputHandlers(text,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(text,images,options){return this._queueUserInput(text,images,"steer",options?.source??"interactive")}async followUp(text,images,options){return this._queueUserInput(text,images,"followUp",options?.source??"interactive")}async _queueSteer(text,images){this._steeringMessages.push(text),this._emitQueueUpdate();let content=[{type:"text",text}];images&&content.push(...images),this.agent.steer({role:"user",content,timestamp:Date.now()})}async _queueFollowUp(text,images){this._followUpMessages.push(text),this._emitQueueUpdate();let content=[{type:"text",text}];images&&content.push(...images),this.agent.followUp({role:"user",content,timestamp:Date.now()})}_throwIfExtensionCommand(text){let spaceIndex=text.indexOf(" "),commandName=spaceIndex===-1?text.slice(1):text.slice(1,spaceIndex);if(this._extensionRunner.getCommand(commandName))throw new Error(`Extension command "/${commandName}" cannot be queued. Use prompt() or execute the command when not streaming.`)}async sendCustomMessage(message,options){let appMessage={role:"custom",customType:message.customType,content:message.content??[],display:message.display,details:message.details,timestamp:Date.now()};if(options?.deliverAs==="nextTurn")this._pendingNextTurnMessages.push(appMessage);else if(this.isStreaming&&options?.triggerTurn!==!1)options?.deliverAs==="followUp"?this.agent.followUp(appMessage):this.agent.steer(appMessage);else if(options?.triggerTurn){if(this._isEmittingAgentSettled){this._deferredSettledActions.push(async()=>await this.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._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 text,images;if(typeof content=="string")text=content;else{let textParts=[];images=[];for(let part of content)part.type==="text"?textParts.push(part.text):images.push(part);text=textParts.join(`
|
|
881
|
-
`),images.length===0&&(images=void 0)}await this.prompt(text,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];return this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues(),this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._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,options.thinkingLevel);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(m=>modelsAreEqual(m,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}getThinkingLevelForModel(model){let scopedLevel=this._scopedModels.find(scoped=>modelsAreEqual(scoped.model,model))?.thinkingLevel,requested=modelsAreEqual(this.model,model)?this.thinkingLevel:this._getThinkingLevelForModelSwitch(model,scopedLevel);return clampThinkingLevel(model,requested)}_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),compactionThinkingLevel=this.settingsManager.getCompactionThinkingLevel(),thinkingLevel=compactionThinkingLevel===void 0?request.thinkingLevel:clampThinkingLevel(request.model,compactionThinkingLevel);return compact(preparation,request.model,request.apiKey,request.headers,customInstructions,signal,thinkingLevel,this.agent.streamFunction,request.env,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._manualCompactionPending=!1,this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._runRequestedCompaction("manual",customInstructions)}async compactFromExtension(customInstructions){return this._runRequestedCompaction("extension",customInstructions)}async _runRequestedCompaction(reason,customInstructions){this._manualCompactionPending=!0;try{await this.abort()}catch(error){throw this._clearManualCompactionState(),error}this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings=this.settingsManager.getCompactionSettings(model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason,willRetry:!1,signal:this._compactionAbortController.signal});if(result?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result?.compaction&&(extensionCompaction=result.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details,summaryCalls;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result=await this._runDefaultCompaction(preparation,model,customInstructions,this._compactionAbortController.signal,reason);summary=result.summary,firstKeptEntryId=result.firstKeptEntryId,tokensBefore=result.tokensBefore,usage=result.usage,details=result.details,summaryCalls=result.summaryCalls}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry:!1,...summaryCalls?{summaryCalls}:{}});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason,result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage5=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage5}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage5,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0,toolResults=[]){let settings=this.settingsManager.getCompactionSettings(this.model);if(!settings.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 errorMessage5=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:errorMessage5}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage5,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage,toolResults);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=estimateContextTokens(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact(contextTokens,contextWindow,settings)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){let model=this.model,settings=this.settingsManager.getCompactionSettings(model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings);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,summaryCalls;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,summaryCalls=compactResult.summaryCalls}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry,...summaryCalls?{summaryCalls}:{}});let result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result,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 errorMessage5=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:errorMessage5}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage5,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){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:dirname11(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return isSyntheticPath(extensionPath)?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(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)},{getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),compact:options=>{(async()=>{try{let result=await this.compactFromExtension(options?.customInstructions);options?.onComplete?.(result)}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){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();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();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._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,errorMessage5)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage5})},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 settings=this.settingsManager.getRetrySettings();if(!settings.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep(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}
|
|
881
|
+
`),images.length===0&&(images=void 0)}await this.prompt(text,{expandPromptTemplates:options?.expandPromptTemplates??!1,streamingBehavior:options?.deliverAs,images,source:"extension"})}clearQueue(){let steering=[...this._steeringMessages],followUp=[...this._followUpMessages];return this._steeringMessages=[],this._followUpMessages=[],this.agent.clearAllQueues(),this._emitQueueUpdate(),{steering,followUp}}get pendingMessageCount(){return this._steeringMessages.length+this._followUpMessages.length}getSteeringMessages(){return this._steeringMessages}getFollowUpMessages(){return this._followUpMessages}get resourceLoader(){return this._resourceLoader}async abort(){this._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,options.thinkingLevel);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(m=>modelsAreEqual(m,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}getThinkingLevelForModel(model){let scopedLevel=this._scopedModels.find(scoped=>modelsAreEqual(scoped.model,model))?.thinkingLevel,requested=modelsAreEqual(this.model,model)?this.thinkingLevel:this._getThinkingLevelForModelSwitch(model,scopedLevel);return clampThinkingLevel(model,requested)}_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),compactionThinkingLevel=this.settingsManager.getCompactionThinkingLevel(),thinkingLevel=compactionThinkingLevel===void 0?request.thinkingLevel:clampThinkingLevel(request.model,compactionThinkingLevel);return compact(preparation,request.model,request.apiKey,request.headers,customInstructions,signal,thinkingLevel,this.agent.streamFunction,request.env,this.settingsManager.getRetrySettings(),this._summarizationRetryCallbacks({source:"compaction",reason}),void 0)}_clearManualCompactionState(){this._manualCompactionPending=!1,this._compactionAbortController=void 0,this._resolveIdleWaitIfIdle()}async compact(customInstructions){return this._runRequestedCompaction("manual",customInstructions)}async compactFromExtension(customInstructions){return this._runRequestedCompaction("extension",customInstructions)}async _runRequestedCompaction(reason,customInstructions){this._manualCompactionPending=!0;try{await this.abort()}catch(error){throw this._clearManualCompactionState(),error}this._compactionAbortController=new AbortController,this._emit({type:"compaction_start",reason});let fromExtension=!1,cancelledByExtension=!1;try{let model=this.model;if(!model)throw new Error(formatNoModelSelectedMessage());let settings=this.settingsManager.getCompactionSettings(model),pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings);if(!preparation)throw pathEntries[pathEntries.length-1]?.type==="compaction"?new Error("Already compacted"):new Error("Nothing to compact (session too small)");let extensionCompaction;if(this._extensionRunner.hasHandlers("session_before_compact")){let result=await this._extensionRunner.emit({type:"session_before_compact",preparation,branchEntries:pathEntries,customInstructions,reason,willRetry:!1,signal:this._compactionAbortController.signal});if(result?.cancel)throw cancelledByExtension=!0,new Error("Compaction cancelled");result?.compaction&&(extensionCompaction=result.compaction,fromExtension=!0)}let summary,firstKeptEntryId,tokensBefore,usage,details,summaryCalls;if(extensionCompaction)summary=extensionCompaction.summary,firstKeptEntryId=extensionCompaction.firstKeptEntryId,tokensBefore=extensionCompaction.tokensBefore,usage=extensionCompaction.usage,details=extensionCompaction.details;else{let result=await this._runDefaultCompaction(preparation,model,customInstructions,this._compactionAbortController.signal,reason);summary=result.summary,firstKeptEntryId=result.firstKeptEntryId,tokensBefore=result.tokensBefore,usage=result.usage,details=result.details,summaryCalls=result.summaryCalls}if(this._compactionAbortController.signal.aborted)throw new Error("Compaction cancelled");this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry:!1,...summaryCalls?{summaryCalls}:{}});let compactionResult={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._clearManualCompactionState(),this._emit({type:"compaction_end",reason,result:compactionResult,aborted:!1,willRetry:!1}),compactionResult}catch(error){let message=error instanceof Error?error.message:String(error),aborted=this._compactionAbortController.signal.aborted||cancelledByExtension,errorMessage5=aborted?void 0:`Compaction failed: ${message}`;throw this._clearManualCompactionState(),this._emit({type:"compaction_end",reason,result:void 0,aborted,willRetry:!1,errorMessage:errorMessage5}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage5,aborted,willRetry:!1,fromExtension}),error}finally{this._clearManualCompactionState()}}abortCompaction(){this._compactionAbortController?.abort(),this._autoCompactionAbortController?.abort()}abortBranchSummary(){this._branchSummaryAbortController?.abort()}async _checkCompaction(assistantMessage,skipAbortedCheck=!0,toolResults=[]){let settings=this.settingsManager.getCompactionSettings(this.model);if(!settings.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 errorMessage5=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:errorMessage5}),await this._emitSessionCompactFailed({reason:"overflow",errorMessage:errorMessage5,aborted:!1,willRetry:!1,fromExtension:!1}),!1}this._overflowRecoveryAttempted=!0,this._omitRecoveryAttempt(assistantMessage,toolResults);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=estimateContextTokens(messages);if(estimate.lastUsageIndex!==null){let usageMsg=messages[estimate.lastUsageIndex];if(compactionEntry&&usageMsg.role==="assistant"&&usageMsg.timestamp<=new Date(compactionEntry.timestamp).getTime())return!1}contextTokens=estimate.tokens}else contextTokens=directContextTokens;return shouldCompact(contextTokens,contextWindow,settings)?await this._runAutoCompaction("threshold",!1):!1}async _runAutoCompaction(reason,willRetry){let model=this.model,settings=this.settingsManager.getCompactionSettings(model),abortController,started=!1,fromExtension=!1,cancelledByExtension=!1;try{if(!model)return!1;let pathEntries=this.sessionManager.getBranch(),preparation=prepareCompaction(pathEntries,settings);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,summaryCalls;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,summaryCalls=compactResult.summaryCalls}abortController.signal.throwIfAborted(),this.sessionManager.appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromExtension,usage);let newEntries=this.sessionManager.getEntries();this._refreshFinalizedContext();let estimatedTokensAfter=estimateMessagesTokens(this.sessionManager.buildSessionProjection().messages),savedCompactionEntry=newEntries.find(e=>e.type==="compaction"&&e.summary===summary);this._extensionRunner&&savedCompactionEntry&&await this._extensionRunner.emit({type:"session_compact",compactionEntry:savedCompactionEntry,fromExtension,reason,willRetry,...summaryCalls?{summaryCalls}:{}});let result={summary,firstKeptEntryId,tokensBefore,estimatedTokensAfter,usage,details};return this._emit({type:"compaction_end",reason,result,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 errorMessage5=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:errorMessage5}),await this._emitSessionCompactFailed({reason,errorMessage:errorMessage5,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){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:dirname11(entry.extensionPath);return{path:entry.path,metadata:{source,scope:"temporary",origin:"top-level",baseDir}}})}getExtensionSourceLabel(extensionPath){return isSyntheticPath(extensionPath)?`extension:${extensionPath.replace(/[<>]/g,"")}`:`extension:${basename7(extensionPath).replace(/\.(ts|js)$/,"")}`}_applyExtensionBindings(runner){runner.setUIContext(this._extensionUIContext,this._extensionMode),runner.bindCommandContext(this._extensionCommandContextActions),this._extensionErrorUnsubscriber?.(),this._extensionErrorUnsubscriber=this._extensionErrorListener?runner.onError(this._extensionErrorListener):void 0}_refreshCurrentModelFromRegistry(){let currentModel=this.model;if(!currentModel)return;let refreshedModel=this._modelRuntime.getModel(currentModel.provider,currentModel.id);!refreshedModel||refreshedModel===currentModel||(this.agent.state.model=refreshedModel)}_bindExtensionCore(runner){let getCommands=()=>{let extensionCommands=runner.getRegisteredCommands().map(command=>({name:command.invocationName,description:command.description,source:"extension",sourceInfo:command.sourceInfo})),templates=this.promptTemplates.map(template=>({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo})),skills=this._resourceLoader.getSkills().skills.map(skill=>({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo}));return[...extensionCommands,...templates,...skills]};runner.bindCore({sendMessage:(message,options)=>{this.sendCustomMessage(message,options).catch(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})},appendUsage:(kind,provider,model,usage,note)=>{let entry=this.sessionManager.appendUsage(kind,provider,model,usage,note);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)},{getModel:()=>this.model,getScopedModels:()=>this._scopedModels,isIdle:()=>this.isIdle,isProjectTrusted:()=>this.settingsManager.isProjectTrusted(),getSignal:()=>this.agent.signal,abort:()=>{if(this._extensionAbortHandler){this._extensionAbortHandler();return}this.abort()},hasPendingMessages:()=>this.pendingMessageCount>0,shutdown:()=>{this._extensionShutdownHandler?.()},getContextUsage:()=>this.getContextUsage(),compact:options=>{(async()=>{try{let result=await this.compactFromExtension(options?.customInstructions);options?.onComplete?.(result)}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){let oldRunner=this._extensionRunner,previousFlagValues=oldRunner.getFlagValues();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();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._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,errorMessage5)=>{this._emit({type:"summarization_retry_scheduled",attempt:attempt2,maxAttempts,delayMs,errorMessage:errorMessage5})},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 settings=this.settingsManager.getRetrySettings();if(!settings.enabled)return!1;if(this._retryAttempt++,this._retryAttempt>settings.maxRetries)return this._retryAttempt--,!1;let delayMs=retryDelayMs(settings,this._retryAttempt);this._emit({type:"auto_retry_start",attempt:this._retryAttempt,maxAttempts:settings.maxRetries,delayMs,errorMessage:message.errorMessage||"Unknown error"}),this._omitRecoveryAttempt(message),this._retryAbortController=new AbortController;try{await sleep(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}
|
|
882
882
|
${command}`:command;try{let result=await executeBashWithOperations(resolvedCommand,this.sessionManager.getCwd(),options?.operations??createLocalBashOperations({shellPath}),{onChunk:delta=>{onChunk?.(delta),this._emit({type:"bash_execution_update",id:options?.id,delta})},signal:abortController.signal});return this.recordBashResult(command,result,options),result}finally{this._bashAbortControllers.delete(abortController)}}recordBashResult(command,result,options){let bashMessage={role:"bashExecution",command,output:result.output,exitCode:result.exitCode,cancelled:result.cancelled,truncated:result.truncated,fullOutputPath:result.fullOutputPath,timestamp:Date.now(),excludeFromContext:options?.excludeFromContext};this.isStreaming?this._pendingBashMessages.push(bashMessage):(this.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};this._branchSummaryAbortController=new AbortController;try{let extensionSummary,fromExtension=!1;if(this._extensionRunner.hasHandlers("session_before_tree")){let result=await this._extensionRunner.emit({type:"session_before_tree",preparation,signal:this._branchSummaryAbortController.signal});if(result?.cancel)return{cancelled:!0};result?.summary&&options.summarize&&(extensionSummary=result.summary,fromExtension=!0),result?.customInstructions!==void 0&&(customInstructions=result.customInstructions),result?.replaceInstructions!==void 0&&(replaceInstructions=result.replaceInstructions),result?.label!==void 0&&(label=result.label)}let summaryText,summaryDetails,summaryUsage;if(options.summarize&&entriesToSummarize.length>0&&!extensionSummary){let signal=this._branchSummaryAbortController.signal,branchSummarySettings=this.settingsManager.getBranchSummarySettings(),result=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(result.aborted)return{cancelled:!0,aborted:!0};if(result.error)throw new Error(result.error);summaryText=result.summary,summaryUsage=result.usage,summaryDetails={readFiles:result.readFiles||[],modifiedFiles:result.modifiedFiles||[]}}else extensionSummary&&(summaryText=extensionSummary.summary,summaryDetails=extensionSummary.details,summaryUsage=extensionSummary.usage);let newLeafId,editorText;targetEntry.type==="message"&&targetEntry.message.role==="user"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.message.content,"")):targetEntry.type==="custom_message"?(newLeafId=targetEntry.parentId,editorText=contentText(targetEntry.content,"")):newLeafId=targetId;let summaryEntry;if(summaryText){let summaryId=this.sessionManager.branchWithSummary(newLeafId,summaryText,summaryDetails,fromExtension,summaryUsage);summaryEntry=this.sessionManager.getEntry(summaryId),label&&this.sessionManager.appendLabelChange(summaryId,label)}else newLeafId===null?this.sessionManager.resetLeaf():this.sessionManager.branch(newLeafId);return label&&!summaryText&&this.sessionManager.appendLabelChange(targetId,label),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()}}getUserMessagesForForking(){let entries=this.sessionManager.getEntries(),result=[];for(let entry of entries){if(entry.type!=="message"||entry.message.role!=="user")continue;let text=contentText(entry.message.content,"");text&&result.push({entryId:entry.id,text})}return result}getSessionStats(){let userMessages=0,assistantMessages=0,toolResults=0,totalMessages=0,toolCalls=0,usageTotals=createUsageTotals();for(let entry of this.sessionManager.getEntries()){if(entry.type==="usage"?addUsageToTotals(usageTotals,entry.usage):(entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage&&addUsageToTotals(usageTotals,entry.usage),entry.type!=="message")continue;totalMessages++;let message=entry.message;if(message.role==="user")userMessages++;else if(message.role==="toolResult")toolResults++,message.usage&&addUsageToTotals(usageTotals,message.usage);else if(message.role==="assistant"){assistantMessages++;let assistantMsg=message;Array.isArray(assistantMsg.content)&&(toolCalls+=assistantMsg.content.filter(c=>c.type==="toolCall").length),addUsageToTotals(usageTotals,assistantMsg.usage)}}return{sessionFile:this.sessionFile,sessionId:this.sessionId,userMessages,assistantMessages,toolCalls,toolResults,totalMessages,tokens:{input:usageTotals.input,output:usageTotals.output,cacheRead:usageTotals.cacheRead,cacheWrite:usageTotals.cacheWrite,total:usageTotals.input+usageTotals.output+usageTotals.cacheRead+usageTotals.cacheWrite},cost:usageTotals.cost,contextUsage:this.getContextUsage()}}getContextUsage(){let 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(m=>{if(m.role!=="assistant")return!1;let msg=m;return!(msg.stopReason==="aborted"&&msg.content.length===0)});if(!lastAssistant)return;let text="";for(let content of lastAssistant.content)content.type==="text"&&(text+=content.text);return text.trim()||void 0}createReplacedSessionContext(){let context=Object.defineProperties({},Object.getOwnPropertyDescriptors(this._extensionRunner.createCommandContext()));return context.sendMessage=(message,options)=>this.sendCustomMessage(message,options),context.sendUserMessage=(content,options)=>this.sendUserMessage(content,options),context}hasExtensionHandlers(eventType){return this._extensionRunner.hasHandlers(eventType)}get extensionRunner(){return this._extensionRunner}};import{join as join18}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,tokens){let usage={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0},...tokens};return calculateCost(model,usage).total}var CacheWarmer=class{run;inactive;models;sessionManager;getMode;decide;onWarmed;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()}var OPENROUTER_HOST="openrouter.ai",NVIDIA_NIM_HOST="integrate.api.nvidia.com",CLOUDFLARE_API_HOST="api.cloudflare.com",CLOUDFLARE_AI_GATEWAY_HOST="gateway.ai.cloudflare.com",OPENCODE_HOST="opencode.ai";function matchesHost(baseUrl,expectedHost){try{return new URL(baseUrl).hostname===expectedHost}catch{return!1}}function isOpenRouterModel(model){return model.provider==="openrouter"||model.baseUrl.includes(OPENROUTER_HOST)}function isNvidiaNimModel(model){return model.provider==="nvidia"||matchesHost(model.baseUrl,NVIDIA_NIM_HOST)}function isCloudflareModel(model){return model.provider==="cloudflare-workers-ai"||model.provider==="cloudflare-ai-gateway"||matchesHost(model.baseUrl,CLOUDFLARE_API_HOST)||matchesHost(model.baseUrl,CLOUDFLARE_AI_GATEWAY_HOST)}function getDefaultAttributionHeaders(model,settingsManager){if(isInstallTelemetryEnabled(settingsManager)){if(isOpenRouterModel(model))return{"HTTP-Referer":"https://pi.dev","X-OpenRouter-Title":"pi","X-OpenRouter-Categories":"cli-agent"};if(isNvidiaNimModel(model))return{"X-BILLING-INVOKE-ORIGIN":"Pi"};if(isCloudflareModel(model))return{"User-Agent":"pi-coding-agent"}}}function getSessionHeaders(model,sessionId){if(sessionId&&!(model.provider!=="opencode"&&model.provider!=="opencode-go"&&!matchesHost(model.baseUrl,OPENCODE_HOST)))return{"x-opencode-session":sessionId,"x-opencode-client":"pi"}}function mergeProviderAttributionHeaders(model,settingsManager,sessionId,...headerSources){let merged={...getSessionHeaders(model,sessionId),...getDefaultAttributionHeaders(model,settingsManager)};for(let headers of headerSources)headers&&Object.assign(merged,headers);return Object.keys(merged).length>0?merged:void 0}import{existsSync as existsSync13,readdirSync as readdirSync7,readFileSync as readFileSync10,statSync as statSync7}from"node:fs";import{basename as basename8,dirname as dirname13,join as join15,resolve as resolve8,sep as sep6}from"node:path";import{execFile,spawnSync as spawnSync3}from"child_process";import{existsSync as existsSync12,readFileSync as readFileSync9,statSync as statSync6,unwatchFile,watchFile}from"fs";import{dirname as dirname12,join as join14,resolve as resolve7}from"path";function findGitPaths(cwd){let dir=cwd;for(;;){let gitPath=join14(dir,".git");if(existsSync12(gitPath))try{let stat3=statSync6(gitPath);if(stat3.isFile()){let content=readFileSync9(gitPath,"utf8").trim();if(content.startsWith("gitdir: ")){let gitDir=resolve7(dir,content.slice(8).trim()),headPath=join14(gitDir,"HEAD");if(!existsSync12(headPath))return null;let commonDirPath=join14(gitDir,"commondir"),commonGitDir=existsSync12(commonDirPath)?resolve7(gitDir,readFileSync9(commonDirPath,"utf8").trim()):gitDir;return{repoDir:dir,commonGitDir,headPath}}}else if(stat3.isDirectory()){let headPath=join14(gitPath,"HEAD");return existsSync12(headPath)?{repoDir:dir,commonGitDir:gitPath,headPath}:null}}catch{return null}let parent=dirname12(dir);if(parent===dir)return null;dir=parent}}function resolveBranchWithGitSync(repoDir){let result=spawnSync3("git",["--no-optional-locks","symbolic-ref","--quiet","--short","HEAD"],{cwd:repoDir,encoding:"utf8",stdio:["ignore","pipe","ignore"]});return(result.status===0?result.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{cwd;static WATCH_DEBOUNCE_MS=500;extensionStatuses=new Map;cachedBranch=void 0;gitPaths=void 0;headWatcher=null;headWatchFilePath=null;headWatchFileListener=null;reftableWatcher=null;reftableTablesListWatcher=null;reftableTablesListPath=null;branchChangeCallbacks=new Set;availableProviderCount=0;refreshTimer=null;gitWatcherRetryTimer=null;refreshInFlight=!1;refreshPending=!1;disposed=!1;constructor(cwd){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,text){text===void 0?this.extensionStatuses.delete(key):this.extensionStatuses.set(key,text)}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=readFileSync9(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=readFileSync9(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(dirname12(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=join14(this.gitPaths.commonGitDir,"reftable");if(existsSync12(reftableDir)){if(this.reftableWatcher=watchWithErrorHandler(reftableDir,()=>{this.scheduleRefresh()},()=>this.handleGitWatcherError()),!this.reftableWatcher)return;let tablesListPath=join14(reftableDir,"tables.list");if(existsSync12(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=join15(packageRoot,"package.json");if(!existsSync13(packageJsonPath))continue;let manifest=JSON.parse(stripBom(readFileSync10(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(result,warnings){result.warnings=[...new Map([...result.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(existsSync13(input2))try{return stripBom(readFileSync10(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=join15(dir,filename);if(existsSync13(filePath))try{if(!statSync7(filePath).isFile())continue;return{path:filePath,content:stripBom(readFileSync10(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=dirname13(commonGitDir);if(!worktreeRoot.startsWith(`${mainRepoRoot}${sep6}`)||canonicalizePath(join15(mainRepoRoot,".git"))!==commonGitDir)return;let worktreeContextFile=loadContextFileFromDir(worktreeRoot);return worktreeContextFile?join15(mainRepoRoot,basename8(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&&join15(canonicalizePath(currentDir),basename8(contextFile.path))===shadowedContextFile;contextFile&&!isShadowed&&!seenPaths.has(contextFile.path)&&(ancestorContextFiles.unshift(contextFile),seenPaths.add(contextFile.path));let parentDir=dirname13(currentDir);if(parentDir===currentDir)break;currentDir=parentDir}return contextFiles.push(...ancestorContextFiles),contextFiles}var DefaultResourceLoader=class{cwd;agentDir;settingsManager;eventBus;packageManager;additionalExtensionPaths;additionalSkillPaths;additionalPromptTemplatePaths;additionalThemePaths;extensionFactories;builtinExtensions;noExtensions;disabledBuiltinExtensions;noSkills;noPromptTemplates;noThemes;noContextFiles;systemPromptSource;appendSystemPromptSource;extensionsOverride;skillsOverride;promptsOverride;themesOverride;agentsFilesOverride;systemPromptOverride;appendSystemPromptOverride;extensionsResult;skills;skillDiagnostics;prompts;promptDiagnostics;themes;themeDiagnostics;agentsFiles;systemPrompt;systemPromptSourcePath;appendSystemPrompt;appendSystemPromptSourcePaths;lastSkillPaths;extensionSkillSourceInfos;extensionPromptSourceInfos;extensionThemeSourceInfos;resourceMetadataByPath;lastPromptPaths;lastThemePaths;loaded;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(path10=>({path:path10}))}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(path10=>!path10.startsWith(BUILTIN_PATH_PREFIX)||!this.disabledBuiltinExtensions.has(path10.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);existsSync13(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);!existsSync13(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);!existsSync13(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);!existsSync13(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&&existsSync13(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=>existsSync13(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(path10=>!path10.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(path10){return isSyntheticPath(path10)?path10:resolvePath(path10,this.cwd,{normalizeUnicodeSpaces:!0})}async loadExtensionPaths(paths,runtime){let isBuiltinPath=path10=>path10.startsWith(BUILTIN_PATH_PREFIX),result=await loadExtensionsCached(paths.filter(path10=>!isBuiltinPath(path10)),this.cwd,this.eventBus,runtime);for(let path10 of paths.filter(isBuiltinPath)){let builtin=this.builtinExtensions.get(path10.slice(BUILTIN_PATH_PREFIX.length));if(!builtin){result.errors.push({path:path10,error:`Unknown built-in extension: ${path10}`});continue}try{let extension=await loadExtensionFromFactory(builtin.factory,this.cwd,this.eventBus,result.runtime,path10);extension.hidden=!0,extension.replaceable=builtin.replaceable===!0,result.extensions.push(extension)}catch(error){result.errors.push({path:path10,error:error instanceof Error?error.message:"failed to load extension"})}}return result}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(path10=>{let resolvedPath=this.resolveExtensionLoadPath(path10);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(path10=>loadedByPath.get(this.resolveExtensionLoadPath(path10))).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(!statSync7(resource.path).isDirectory())return resource.path}catch{return resource.path}let skillFile=join15(resource.path,"SKILL.md");return existsSync13(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=resolve8(resourcePath);if(extraSourceInfos)for(let[sourcePath,sourceInfo]of extraSourceInfos.entries()){let normalizedSourcePath=resolve8(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep6}`))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=resolve8(sourcePath);if(normalizedResourcePath===normalizedSourcePath||normalizedResourcePath.startsWith(`${normalizedSourcePath}${sep6}`))return createSourceInfo(resourcePath,metadata)}}}getDefaultSourceInfoForPath(filePath){let syntheticSource=getSyntheticPathSource(filePath);if(syntheticSource)return{path:filePath,source:syntheticSource,scope:"temporary",origin:"top-level"};let normalizedPath=resolve8(filePath),agentRoots=[join15(this.agentDir,"skills"),join15(this.agentDir,"prompts"),join15(this.agentDir,"themes"),join15(this.agentDir,"extensions")],projectRoots=[join15(this.cwd,CONFIG_DIR_NAME,"skills"),join15(this.cwd,CONFIG_DIR_NAME,"prompts"),join15(this.cwd,CONFIG_DIR_NAME,"themes"),join15(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:statSync7(normalizedPath).isDirectory()?normalizedPath:resolve8(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=[join15(this.agentDir,"themes"),join15(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(!existsSync13(resolved)){diagnostics.push({type:"warning",message:"theme path does not exist",path:resolved});continue}try{let stats=statSync7(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(existsSync13(dir))try{let entries=readdirSync7(dir,{withFileTypes:!0});for(let entry of entries){let isFile=entry.isFile();if(entry.isSymbolicLink())try{isFile=statSync7(join15(dir,entry.name)).isFile()}catch{continue}isFile&&entry.name.endsWith(".json")&&this.loadThemeFromFile(join15(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=join15(this.cwd,CONFIG_DIR_NAME,"SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync13(projectPath))return projectPath;let globalPath=join15(this.agentDir,"SYSTEM.md");if(existsSync13(globalPath))return globalPath}discoverAppendSystemPromptFile(){let projectPath=join15(this.cwd,CONFIG_DIR_NAME,"APPEND_SYSTEM.md");if(this.settingsManager.isProjectTrusted()&&existsSync13(projectPath))return projectPath;let globalPath=join15(this.agentDir,"APPEND_SYSTEM.md");if(existsSync13(globalPath))return globalPath}isUnderPath(target,root){let normalizedRoot=resolve8(root);if(target===normalizedRoot)return!0;let prefix=normalizedRoot.endsWith(sep6)?normalizedRoot:`${normalizedRoot}${sep6}`;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 constants6,copyFileSync,existsSync as existsSync15,mkdirSync as mkdirSync6}from"node:fs";import{basename as basename9,join as join17,parse as parse2,resolve as resolve9}from"node:path";import{existsSync as existsSync14}from"node:fs";function getMissingSessionCwdIssue(sessionManager,fallbackCwd){let sessionFile=sessionManager.getSessionFile();if(!sessionFile)return;let sessionCwd=sessionManager.getCwd();if(!(!sessionCwd||existsSync14(sessionCwd)))return{sessionFile,sessionCwd,fallbackCwd}}function formatMissingSessionCwdError(issue){let sessionFile=issue.sessionFile?`
|
|
883
883
|
Session file: ${issue.sessionFile}`:"";return`Stored session working directory does not exist: ${issue.sessionCwd}${sessionFile}
|
|
884
884
|
Current working directory: ${issue.fallbackCwd}`}function formatMissingSessionCwdPrompt(issue){return`cwd from session file does not exist
|